Cách tải tệp bằng cURL: Cờ lệnh, cách khắc phục và script

Cập nhật lần cuối vào August 11, 2026
Hand-drawn file download flowing from a terminal window into a verified folder
Tóm tắt bằng AI
Hướng dẫn thực hành tải tệp bằng cURL, bao gồm chuyển hướng, xác thực, thử lại, tiếp tục tải, script batch, kiểm tra tệp và các chế độ lỗi thường gặp.

Tôi đã không ít lần thức khuya chỉ để gỡ lỗi những script vốn dĩ chỉ nên “tải một tệp rồi xong”. Phần lớn trường hợp, thủ phạm lại chính là cURL đang làm đúng những gì tôi yêu cầu, chứ không phải những gì tôi thực sự muốn. Hóa ra có một khoảng cách rất lớn giữa câu “curl -O chạy được” và “curl -O chạy ổn định trong môi trường production.”

Chính vì khoảng cách đó mà bài hướng dẫn này ra đời. cURL được cài sẵn trên macOS, hầu hết các bản phân phối Linux, và Windows 10 trở lên, nghĩa là rất có thể máy bạn đã có sẵn công cụ này. Nhưng giữa lỗi chuyển hướng âm thầm, các mã 403 bí ẩn, và bước nhảy từ “tải một tệp” sang “tải 500 tệp mà không làm nghẽn terminal”, vẫn còn vô số chỗ dễ mắc kẹt. Tôi sẽ đi qua các cờ lệnh quan trọng, những lệnh thực tế tôi hay dùng, các lỗi thường gặp nhất, và cả lúc cURL thật sự không còn giúp được nữa — cùng lựa chọn thay thế phù hợp.

cURL là gì (và vì sao bạn nên quan tâm)?

cURL là một công cụ dòng lệnh miễn phí, mã nguồn mở, dùng để truyền dữ liệu tới hoặc từ máy chủ thông qua URL. Nó hỗ trợ HTTP, HTTPS, FTP, SFTP và rất nhiều giao thức khác, nên xuất hiện khắp nơi từ script bash, Dockerfile cho đến pipeline CI. Ẩn phía sau, lệnh curl bạn gõ trong terminal sử dụng libcurl, thư viện truyền dữ liệu bằng C mà rất nhiều ứng dụng và binding ngôn ngữ lập trình tích hợp. Ví dụ, extension cURL của PHP là một trường hợp như vậy; còn thư viện Requests phổ biến của Python là một HTTP client riêng, xây dựng trên urllib3 chứ không phải libcurl.

Phiên bản ổn định hiện tại tại thời điểm viết bài là curl 8.21.0, phát hành vào tháng 6 năm 2026 — nhưng đừng mặc định rằng hệ điều hành của bạn đang đi kèm đúng bản build đó. Các bản curl do distro đóng gói thường chậm hơn dự án gốc vài tháng, thậm chí lâu hơn, nên tốt nhất hãy chạy curl --version trước khi cho rằng một cờ lệnh như --parallel đã khả dụng.

Vì sao nên tải tệp bằng cURL? Các trường hợp sử dụng hàng đầu

Tôi thường được hỏi: tại sao phải dùng công cụ dòng lệnh trong khi trình duyệt tải tệp rất ổn? Câu trả lời thật lòng là: trình duyệt rất tốt cho đến khi bạn cần tự động hóa.

Trường hợp sử dụngVì sao cURL nổi bật
Tải binary trong pipeline CI/CDCó thể viết script, không cần giao diện đồ họa
Lấy phản hồi API hoặc xuất dữ liệuHỗ trợ header tùy chỉnh, xác thực, và chuyển đầu ra qua pipeline
Tiếp tục tải tệp lớn qua SSHCó sẵn chức năng tiếp tục tải (-C -)
Tự động tải theo lịch (cron)Nhẹ, dễ kết hợp với shell script
Lấy tệp phía sau lớp đăng nhậpCờ xác thực linh hoạt (basic, token, cookie, .netrc)

Tải bằng trình duyệt là thao tác thủ công, chỉ dùng một lần. cURL biến thao tác đó thành thứ bạn có thể lên lịch, nối vào pipeline, thử lại khi lỗi, và chạy đồng nhất trên hàng trăm máy chủ cùng lúc. Đó chính là sức hút của nó — không hào nhoáng hơn, chỉ là lặp lại được.

Dòng chảy minh họa từ nguồn web đến tệp đã tải xuống và thư mục cục bộ

Các cờ cURL thiết yếu để tải tệp

Tôi thường quay lại khoảng hơn chục cờ lệnh quen thuộc cho 90% công việc của mình. Đây là phần “phao cứu sinh” mà giá như có ai đưa cho tôi từ nhiều năm trước, được nhóm theo đúng chức năng thực tế.

Cờ xuất ra và lưu tệp

  • -O (--remote-name) lưu tệp bằng phần cuối của URL làm tên file. Tiện, nhưng có thể âm thầm ghi đè lên tệp đã tồn tại cùng tên.
  • -o <filename> (--output) cho phép bạn tự chọn chính xác tên tệp: curl -o report.pdf https://example.com/downloads/file.pdf.
  • -J (--remote-header-name) dùng tên tệp từ header Content-Disposition của máy chủ thay vì lấy từ URL. Cách này rất tiện cho việc tải từ API, nhưng hãy coi tên tệp do máy chủ cung cấp là dữ liệu không đáng tin — nên tải vào một thư mục riêng thay vì thư mục home, đúng như khuyến nghị bảo mật của curl.

Các cờ hành vi mà mọi lượt tải đều cần

  • -L (--location) bảo curl đi theo các chuyển hướng HTTP. Nếu không có nó, phản hồi 3xx có thể bị lưu thành một trang HTML chuyển hướng nhỏ xíu thay vì tệp thật — đây là lỗi “sao file tải về bị hỏng” mà tôi gặp nhiều nhất.
  • -C - (--continue-at -) tiếp tục tải từ đúng chỗ bị gián đoạn.
  • -s / -S chạy ở chế độ im lặng nhưng vẫn hiện lỗi — rất hợp cho script khi bạn không muốn thanh tiến trình làm rối log.
  • --limit-rate 1M giới hạn băng thông (hữu ích khi dùng chung mạng hoặc không muốn chiếm hết đường truyền tính cước).
  • --connect-timeout 10--max-time 300 ngăn kết nối treo làm script đứng chết ở đó mãi.
  • --retry 3--retry-delay 5 tự thử lại khi lỗi tạm thời — theo trang man của curl, chỉ nên ghép thêm --retry-all-errors khi việc lặp lại đúng y nguyên request đó thực sự an toàn.

Cờ tiến trình và gỡ lỗi

  • -# hiển thị thanh tiến trình đơn giản thay cho bảng thống kê mặc định.
  • -v xuất ra thông tin chi tiết, bao gồm toàn bộ header request/response — đây là lựa chọn tôi dùng khi có gì đó hoạt động bất thường.
  • -I (--head) chỉ lấy header phản hồi, rất phù hợp để kiểm tra trước khi quyết định tải một tệp lớn.
  • -w cho phép in đầu ra tùy chỉnh sau khi truyền xong, ví dụ curl -o /dev/null -s -w "%{http_code}\n" <url> để chỉ kiểm tra mã trạng thái.

Trước khi bắt đầu

  • Độ khó: Từ cơ bản đến trung cấp (phần batch và xác thực sẽ nâng cao hơn một chút)
  • Thời gian cần thiết: Khoảng 15–20 phút để đi qua các lệnh cốt lõi
  • Bạn cần gì: Một terminal (macOS Terminal, shell Linux, hoặc Windows PowerShell/WSL), cURL đã cài sẵn (kiểm tra bằng curl --version), và một URL thử nghiệm — tôi sẽ dùng một asset phát hành công khai trên GitHub làm ví dụ vì nó ổn định và dễ truy cập

Cách tải tệp bằng cURL: hướng dẫn từng bước

Bước 1: Tải một tệp duy nhất

Cú pháp cơ bản nhất: curl -O <url> sẽ lưu tệp theo tên gốc của nó, còn curl -o myfile.zip <url> cho phép bạn đổi tên ngay lúc tải.

curl -LO https://github.com/curl/curl/releases/download/curl-8_21_0/curl-8.21.0.tar.gz

Hiện tại tôi luôn thêm -L, không có ngoại lệ nào cả — tôi đã quá nhiều lần bị redirect biến “lượt tải” thành một file HTML 400 byte mà không hề báo trước. Bạn sẽ thấy thanh tiến trình chạy lên trong terminal, và cuối cùng file nằm trong thư mục hiện tại.

Khi lệnh thành công, thanh tiến trình sẽ đạt 100% và curl-8.21.0.tar.gz sẽ xuất hiện trong thư mục hiện tại. Hãy xác nhận tệp trước khi dùng:

ls -lh curl-8.21.0.tar.gz

Bước 2: Tải và đổi tên tệp

Dùng -o khi bạn muốn đặt tên tệp cục bộ cụ thể thay vì cái tên mà URL vốn có:

curl -L -o curl-latest.tar.gz -S https://github.com/curl/curl/releases/download/curl-8_21_0/curl-8.21.0.tar.gz

-S ở đây sẽ bật lại phần hiển thị lỗi trong trường hợp bạn đã dùng -s ở nơi khác trong script. Bộ này — -L -o <name> -S — gần như là lệnh tải một tệp mặc định của tôi.

Bước 3: Tiếp tục tải khi bị gián đoạn

Nếu một file lớn bị rớt giữa chừng (wifi chập chờn, VPN có vấn đề, v.v.), đừng tải lại từ đầu. Hãy chạy:

curl -C - -LO https://example.com/large-file.iso

Điều cần lưu ý: cách này chỉ hoạt động nếu máy chủ hỗ trợ byte-range request. Accept-Ranges: bytes là tín hiệu tích cực hữu ích, nhưng việc không có nó chưa đủ để kết luận là máy chủ không hỗ trợ range. Cách kiểm tra đáng tin cậy là xem phản hồi thật của máy chủ với một request range: phản hồi có thể tiếp tục tải thường sẽ trả về 206 Partial Content cùng Content-Range hợp lệ. Hãy chạy lệnh tiếp tục tải rồi kiểm tra trạng thái bằng -v hoặc -D -; nếu máy chủ bỏ qua range hoặc từ chối offset, hãy chủ động tải lại từ đầu thay vì cho rằng file dở dang vẫn an toàn.

Một lượt tải cURL bền bỉ tiếp tục sau gián đoạn và hoàn tất kèm kiểm tra checksum

Bước 4: Tải với thanh tiến trình hoặc ở chế độ im lặng

Nếu muốn giao diện gọn hơn trong terminal tương tác: curl -# -LO <url>. Nếu viết script hoặc cron job và chỉ muốn xem lỗi, không muốn tiếng ồn: curl -sS -LO <url>. Tôi dùng bản im lặng ở hầu hết mọi nơi, trừ lúc gỡ lỗi thủ công.

Bước 5: Giới hạn tốc độ tải

Trên mạng văn phòng dùng chung (hoặc khi tôi không muốn trở thành người “ngốn” hết băng thông trong một cuộc gọi video), tôi sẽ giới hạn tốc độ bằng:

curl --limit-rate 1M -LO https://example.com/big-dataset.zip

Đơn vị là K, M, và G tương ứng với kilobyte, megabyte và gigabyte mỗi giây.

Bước 6: Lưu header phản hồi cùng với tệp

Đôi khi tôi cần biết chính xác máy chủ trả về những gì — loại nội dung, header cache, và các thông tin tương tự — mà không làm terminal rối mắt:

curl -L -D headers.txt -o file.zip https://example.com/file.zip

Lệnh này ghi header phản hồi vào headers.txt trong khi tệp thật được lưu thành file.zip. Rất hữu ích để gỡ lỗi lệch loại nội dung hoặc kiểm tra xem CDN có đang cache đúng thứ bạn nghĩ là nó đang cache hay không.

Mẹo và lỗi thường gặp

  • Mẹo: Luôn mặc định dùng -L. Thực sự tôi không nghĩ ra điểm bất lợi nào khi thêm nó, và tôi đã mất hàng giờ chỉ vì quên.
  • Mẹo: Khi viết script, hãy kết hợp --fail với lệnh tải để phản hồi không phải 2xx khiến script thoát lỗi thật sự, thay vì âm thầm lưu một trang lỗi như thể đó là file bạn cần.
  • Lỗi thường gặp: Đừng ghép -C - với --remove-on-errorcurl ghi rõ hai tùy chọn này không tương thích, vì resume cần file dở dang vẫn phải còn nguyên.
  • Lỗi thường gặp: -O có thể ghi đè tệp mà không báo trước. Nếu bạn tải hàng loạt vào một thư mục dùng chung, hãy dùng --output-dir để giữ mọi thứ gọn trong một chỗ.

Cách tải nhiều tệp và tải hàng loạt bằng cURL

Ví dụ với một tệp là phần dễ nhất. Những quy trình thực tế mà tôi xây dựng — lấy dữ liệu xuất hằng đêm, đồng bộ binary giữa các máy build — đều cần xử lý đồng thời, và đây là chỗ mà phần lớn bài hướng dẫn chỉ... dừng lại. Có ba cách đáng biết, mỗi cách là một nấc phức tạp hơn.

Cách 1: Nhiều URL trong một lệnh cURL

Cách đơn giản nhất là liệt kê các URL:

curl -LO https://example.com/a.zip -LO https://example.com/b.zip -LO https://example.com/c.zip

Cách này hoạt động, nhưng là chạy tuần tự — curl tải xong file này mới sang file tiếp theo. Với 3 file thì ổn, với 300 file thì rất mệt.

Cách 2: Tải song song với --parallel (curl 7.66+)

Từ curl 7.66 trở đi, bạn có thể thêm --parallel (hoặc -Z) để tải nhiều URL cùng lúc:

curl --parallel --parallel-max 5 --remote-name-all \
  https://example.com/a.zip https://example.com/b.zip https://example.com/c.zip

Điều nên biết: giới hạn song song mặc định thực ra là 50, tức là nhiều kết nối đồng thời hơn mức mà đa số máy chủ — hoặc ngay cả mạng của bạn — sẽ cảm ơn. Tôi thường đặt --parallel-max rõ ràng và thận trọng — thường là 4 đến 8 — thay vì tin vào mặc định.

Cách 3: Dùng xargs và vòng lặp Bash để xử lý danh sách URL

Với một danh sách URL lớn nằm trong file text, tôi thường chọn xargs:

cat urls.txt | xargs -n1 -P 8 curl -O -L

Hoặc nếu muốn kiểm soát nhiều hơn từng job riêng lẻ, tôi dùng vòng lặp bash với tiến trình nền:

while read -r url; do
  curl -O -L "$url" &
done < urls.txt
wait

Lệnh wait ở cuối rất quan trọng — nếu không có nó, script sẽ thoát trước khi các lượt tải nền hoàn tất.

Khi nào nên dùng wget hoặc aria2 thay vì cURL

Nói thẳng luôn: cURL không phải lúc nào cũng là công cụ đúng. Nếu bạn cần mirror toàn bộ cây thư mục của một website, wget -r có sẵn chức năng crawl đệ quy theo cách mà cURL vốn không được sinh ra để làm. Nếu bạn cần tải chia đoạn từ nhiều nguồn để tối đa thông lượng cho một file cực lớn, aria2c thực sự nhanh hơn.

Công cụPhù hợp nhất cho
cURLĐộ chính xác, viết script, tải một tệp hoặc số lượng nhỏ, làm việc với API
wgetTải đệ quy/mirror toàn bộ site, lấy hàng loạt tệp tĩnh đơn giản hơn
aria2Tải đa nguồn/chia đoạn, tối đa thông lượng cho file lớn

Điểm mạnh của cURL luôn là độ chính xác và khả năng kết hợp — piping, scripting, linh hoạt giao thức — chứ không phải kiểu crawl brute-force.

Cách tải tệp được bảo vệ bằng cURL: các mẫu xác thực

Nhiều bài hướng dẫn cURL chỉ dừng ở -u user:pass rồi kết thúc. Đó là dấu vết của một thời kỳ Internet cũ. Năm 2026, những thứ tôi thật sự tải về đến từ REST API, dashboard dùng session, và hệ thống CI — và mỗi loại lại cần một kiểu credential khác nhau.

Basic Auth

curl -u username:password -O https://legacy-server.example.com/file.zip

Ổn cho các server FTP kiểu cũ hoặc endpoint HTTP đơn giản. Chỉ cần nhớ mật khẩu có thể xuất hiện trong lịch sử shell và danh sách tiến trình nếu bạn không cẩn thận — tôi sẽ không dùng cách này cho bất kỳ thứ gì nhạy cảm.

Bearer / OAuth Token Auth

Đây là kiểu xác thực thường bị nói thiếu trong nhiều tài liệu, nhưng lại là kiểu tôi dùng nhiều nhất hiện nay:

curl -H "Authorization: Bearer $GITHUB_TOKEN" \
  -LO https://api.github.com/repos/curl/curl/releases/assets/12345

Đó là một mẫu thật để lấy private release asset trên GitHub — chỉ cần thay token và asset ID của bạn vào. REST API và các tài nguyên được bảo vệ bởi OAuth2 gần như đều nói “ngôn ngữ” này.

Xác thực bằng session cookie

Với các web app mà đăng nhập xong sẽ tạo session, hãy lưu cookie jar lúc đăng nhập rồi dùng lại khi tải:

curl -c cookies.txt -d "user=me&pass=secret" https://example.com/login
curl -b cookies.txt -O https://example.com/protected/file.zip

File .netrc cho môi trường script và CI

Đây là cách tôi thích nhất cho mọi thứ chạy không có người giám sát. Tạo file ~/.netrc (hoặc _netrc trên Windows):

machine example.com
login myusername
password mypassword

Khóa quyền truy cập bằng chmod 600 ~/.netrc, rồi dùng nó như sau:

curl --netrc -LO https://example.com/protected-file.zip

Ưu điểm là credential không bao giờ chạm vào lịch sử shell hay mã nguồn script — điều này thật sự quan trọng trong CI/CD, nơi script thường bị ghi log đầy đủ.

Phương thức xác thựcCờ/Tùy chọnPhù hợp nhất cho
Basic auth-u user:passFTP cũ, HTTP đơn giản
Bearer token-H "Authorization: Bearer <token>"REST API, OAuth2
Cookie auth-b cookies.txt (+ -c để lưu)Ứng dụng web dựa trên session
File .netrc--netrc hoặc --netrc-fileCI/CD, môi trường script

Khối tiến trình, mũi tên thử lại và thư mục hoàn tất

Khắc phục các lỗi tải cURL thường gặp

Đây là phần mà tôi thật sự ước giá như có khi mới bắt đầu, vì gần như chẳng ai nói kỹ. “Tại sao tải bằng curl của tôi không chạy?” là một truy vấn rất thật, rất phổ biến, và cực kỳ gây khó chịu — trong khi cách sửa thường chỉ là một dòng lệnh nếu bạn biết nguyên nhân.

Triệu chứngNguyên nhân có thểCách sửa
curl: (60) SSL certificate problemChứng chỉ tự ký hoặc đã hết hạn--cacert <file> hoặc -k (chỉ dùng khi dev)
403 Forbidden / file rỗngMáy chủ chặn user agent mặc định của curl-A "Mozilla/5.0..." hoặc -H "User-Agent: ..."
Tải lại từ 0 với -C -Máy chủ không hỗ trợ RangeKiểm tra bằng curl -I <url> xem có Accept-Ranges: bytes không
Lưu file 0 byteKhông theo redirectThêm cờ -L
curl: (28) Operation timed outMáy chủ chậm hoặc sự cố mạng--connect-timeout 10 --max-time 300 + --retry 3
Lưu trang HTML thay vì fileTrang cần JavaScript để rendercurl không chạy JS — xem phần bên dưới

Lỗi chứng chỉ SSL: nghĩa là gì và sửa thế nào

Lỗi 60 có nghĩa là curl không thể xác minh chứng chỉ SSL của máy chủ — thường vì chứng chỉ tự ký, hết hạn, hoặc được cấp bởi CA mà curl không tin cậy. Nếu bạn kiểm soát máy chủ, hãy trỏ curl tới đúng CA bundle bằng --cacert /path/to/ca.pem. Cờ -k (--insecure) bỏ qua xác minh hoàn toàn, tạm chấp nhận trong môi trường dev cục bộ, nhưng là ý tưởng cực tệ cho bất kỳ thứ gì chạm vào production hoặc dữ liệu người dùng thật.

Lỗi 403 Forbidden và file tải rỗng

Không ít máy chủ chặn các request tự nhận là curl/8.21.0 (chuỗi User-Agent mặc định của curl), vì nghĩ đó là bot hoặc scraper. Cách sửa thường chỉ là giả làm trình duyệt:

curl -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" -LO https://example.com/file.zip

Để kiểm tra thực sự nhận được gì trước khi tải đầy đủ, tôi thường chạy: curl -o /dev/null -s -w "%{http_code}\n" <url>.

Timeout, retry và kết nối chập chờn

Đây là lệnh tôi sẵn sàng xăm lên tay nếu tôi can đảm hơn với việc xăm mình.

Lệnh tải tôi hay dùng nhất trong production script, ghép mọi cờ độ tin cậy lại với nhau:

curl -L -C - --retry 5 --retry-delay 3 --connect-timeout 10 --max-time 600 --fail -O <url>

Tức là theo redirect, tiếp tục tải, thử lại 5 lần với độ trễ 3 giây, timeout kết nối 10 giây, giới hạn tổng thời gian 10 phút, và thất bại rõ ràng nếu HTTP status xấu — gần như mọi thứ tôi đã học được sau nhiều lần trả giá.

cURL trong tự động hóa thực tế: CI/CD pipeline, piping và an toàn script

Piping đầu ra của cURL sang công cụ khác

curl không nhất thiết phải lưu ra đĩa — pipe thẳng sang lệnh khác là một trong những tính năng bị đánh giá thấp nhất của nó:

curl -sL https://example.com/archive.tar.gz | tar xz
curl -s https://api.example.com/data | jq '.results'

Tải rồi giải nén, hoặc tải rồi phân tích, chỉ trong một dòng. Đây là mẫu tôi dùng liên tục cho các lượt lấy dữ liệu ngắn gọn.

Dùng cURL trong GitHub Actions và CI/CD

Một bước GitHub Actions tối giản để tải binary với logic retry và báo lỗi rõ ràng:

- name: Download binary
  run: |
    curl -L --fail --retry 3 --retry-delay 5 \
      -o app-binary "https://example.com/releases/app-binary"

Hãy lưu mọi token như CI secrets và tham chiếu bằng biến môi trường — tuyệt đối đừng hardcode vào script. Và nhớ dùng --fail (hoặc --fail-with-body nếu bạn cần xem phần body lỗi để gỡ lỗi) để một lượt tải hỏng thực sự làm hỏng build, thay vì âm thầm thành công với rác.

Câu hỏi bảo mật về curl | sh

Chuyện này gần như xuất hiện trong mọi diễn đàn nhà phát triển tôi từng đọc, và hoàn toàn có lý do: pipe trực tiếp curl vào sh nghĩa là bạn đang chạy code từ xa mà chưa xem qua, chỉ dựa trên niềm tin rằng máy chủ không bị xâm phạm và kết nối không bị can thiệp. Rủi ro thật sự nằm ở đó — không phải hoang tưởng, mà là một vấn đề supply chain rất thẳng thắn.

Mẫu an toàn hơn là tải về trước, xem script, xác minh checksum hoặc chữ ký GPG nếu có, rồi mới chạy:

curl -sL https://example.com/install.sh -o install.sh
cat install.sh   # thực sự đọc nội dung
sha256sum install.sh   # so với checksum đã công bố nếu có
bash install.sh

Các trình cài đặt nổi tiếng như rustup và Homebrew vẫn dùng mẫu curl | sh, và nhìn chung điều đó được chấp nhận trong những trường hợp cụ thể ấy vì nhà duy trì và kênh phân phối đều rất đáng tin. Tuy vậy, tôi vẫn thà mất thêm 10 giây để xem script còn hơn nhận ra quá muộn rằng mình đã tin nhầm.

Khi cURL không đủ: trang render bằng JS, website chống bot và dữ liệu có cấu trúc

Đây là một kiểu lỗi làm rất nhiều người vấp phải, và thường không phải lỗi của họ: bạn chạy curl -O với một trang trông hoàn toàn bình thường, nhưng thay vì nội dung mong đợi, bạn lại nhận về một khung HTML rỗng, hoặc một trang thử thách của Cloudflare, hoặc thứ gì đó trông như rác. cURL đã làm đúng chức năng của nó — lấy phản hồi HTTP thô — chỉ là nó không thể chạy JavaScript, giải CAPTCHA, hay vượt qua hệ thống nhận diện bot. Đó không phải bug của curl; nó nằm ngoài phạm vi công việc của công cụ này.

Vì sao cURL thất bại với các trang web hiện đại

Nhiều ứng dụng một trang (SPA) hiện đại trả về một khung HTML gần như trống, còn nội dung thật được JavaScript render phía client sau khi trang tải — thứ mà curl không bao giờ thực thi. Bên cạnh đó, các hệ thống như Cloudflare và Akamai chủ động hiển thị trang thử thách cho bất kỳ thứ gì không giống trình duyệt thật, và các request curl lặp lại từ cùng một IP có thể bị giới hạn tốc độ hoặc bị gắn nhãn traffic bot rất nhanh.

Bước tiếp theo: API scraping bằng AI dành cho nhà phát triển

Tôi cho rằng cURL là công cụ đúng cho khoảng 80% trường hợp tải tệp và dữ liệu trên mạng — asset tĩnh, phản hồi API, mọi thứ được phục vụ như tài nguyên HTTP thuần túy. Chính 20% còn lại, tức các trang nặng JavaScript hoặc bị chặn bởi bot, là nơi tôi thấy các nhà phát triển phải vật lộn hàng giờ với header và chuỗi user-agent rồi cuối cùng cũng phải bỏ cuộc để tìm đến một lớp công cụ khác.

Đó chính là khoảng trống mà đội ngũ tôi xây dựng Thunderbit để lấp đầy, bên cạnh tiện ích Chrome mà đa số người dùng đã biết đến. Ở phía dành cho nhà phát triển, Open API của Thunderbit cung cấp POST /distill, trả về Markdown sạch, sẵn cho LLM từ một URL — với phần render trang do dịch vụ xử lý — và POST /extract, trả về JSON có cấu trúc khớp schema khi bạn cần dữ liệu theo trường chứ không chỉ văn bản dễ đọc. Ngoài ra còn có MCP server để các agent trong Claude hoặc Cursor có thể gọi thunderbit_distillthunderbit_extract ngay trong quá trình làm việc, cùng CLI (npx @thunderbit/thunderbit-cli distill <url>) hoạt động khá giống cURL trong terminal. Ví dụ, bạn có thể pipe đầu ra JSON sang jq, như thunderbit distill <url> --format json | jq -r '.data.markdown'; hoặc dùng đầu ra --format markdown cho công cụ xử lý văn bản hay lưu vào file.

Đặt cạnh nhau, sự khác biệt rất rõ. Một request cURL tới trang sản phẩm render bằng JS có thể chỉ trả về một <div id="root"></div> gần như trống. Còn lệnh thunderbit distill tương ứng sẽ trả về nội dung đã render dưới dạng Markdown sạch. Distill tiêu tốn 1 credit cho mỗi URL và Extract là 20 credit cho mỗi URL. Giới hạn hiện tại theo từng endpoint cũng khác nhau: Batch Distill hỗ trợ tối đa 100 URL cho mỗi job, còn Batch Extract nhận tối đa 50 URL với cùng một schema chung. Hãy kiểm tra tài liệu API hiện tại trước khi ước lượng một hàng đợi production.

Nếu bạn mới làm quen với khái niệm này nói chung, bài giải thích của chúng tôi về web scraping thực sự là gì là điểm khởi đầu khá tốt, và hướng dẫn scraping không cần code sẽ đi vào khía cạnh dành cho người không viết code trong cùng một vấn đề này. Để có cái nhìn so sánh rộng hơn về các công cụ trong lĩnh vực này, chúng tôi cũng có bài tổng hợp những AI web scraper tốt nhất đáng để biết.

Tham khảo nhanh: bảng cheat sheet tải tệp bằng cURL

Tác vụLệnh
Tải cơ bảncurl -LO <url>
Tên tệp tùy chỉnhcurl -L -o myfile.zip <url>
Tiếp tục tảicurl -C - -LO <url>
Im lặng nhưng vẫn hiện lỗicurl -sSL -O <url>
Tải song songcurl --parallel --parallel-max 5 -O <url1> -O <url2>
Xác thực bằng bearer tokencurl -H "Authorization: Bearer <token>" -LO <url>
Lệnh tải nên dùng trong scriptcurl -LO --retry 5 --retry-delay 3 --max-time 600 --fail <url>
Pipe sang công cụ giải néncurl -sL <url> | tar xz

Kết luận và các điểm chính cần nhớ

Tải một tệp bằng curl bắt đầu rất đơn giản — curl -O là gần như xong — nhưng kỹ năng thật sự nằm ở các lớp bên dưới: biết khi nào nên thêm -L, khi nào nên tiếp tục thay vì tải lại, kiểu xác thực nào thực sự phù hợp với quy trình của bạn, và phải làm gì ngay khi 403 hoặc một khung HTML rỗng xuất hiện thay vì tệp bạn mong đợi. Tôi đã dựa vào từng mẫu này ở một thời điểm nào đó, thường là ngay sau khi học theo cách rất đau rằng vì sao nó quan trọng.

Đến nay, curl vẫn là công cụ mặc định của tôi cho các lượt tải tệp đơn giản và công việc HTTP có thể script hóa — nhanh, có mặt ở khắp nơi, và kết hợp rất đẹp với phần còn lại của shell pipeline. Nhưng khi bạn gặp một trang render bằng JavaScript hoặc một bức tường chống bot, đó không còn là vấn đề của curl để giải quyết bằng cách thêm vài cờ lệnh nữa; đó là dấu hiệu bạn cần một lớp công cụ khác, và chính ở đó API như của Thunderbit sẽ tiếp quản công việc mà không buộc bạn phải rời khỏi terminal.

Hãy đánh dấu trang cheat sheet, thử lệnh retry-and-resume vào lần tải chập chờn tiếp theo của bạn, và nếu bạn gặp bức tường mà curl chỉ trả về rác, bạn đã biết bước kế tiếp trông như thế nào — trang giá của Thunderbit có bảng credit hiện tại nếu bạn muốn xem việc chuyển cấp đó tốn bao nhiêu, và kênh YouTube của chúng tôi có các video hướng dẫn nếu bạn thích xem hơn là đọc.

Câu hỏi thường gặp về tải tệp bằng cURL

Làm sao để tải tệp bằng cURL và lưu với một tên cụ thể?

Dùng -o rồi đặt tên file bạn muốn: curl -L -o yourname.ext <url>. Thêm -L để chuyển hướng không làm hỏng lượt tải.

Làm sao để tiếp tục một lượt tải cURL bị lỗi?

Chạy curl -C - -LO <url>. Cách này chỉ hoạt động nếu máy chủ hỗ trợ range request — hãy kiểm tra trước bằng curl -I <url> và tìm Accept-Ranges: bytes trong phản hồi.

cURL có thể tải tệp cần đăng nhập không?

Có, theo bốn cách chính: basic auth (-u user:pass), bearer token (-H "Authorization: Bearer <token>"), session dựa trên cookie (-b cookies.txt), hoặc file .netrc cho môi trường script. Xem phần xác thực ở trên để hiểu đầy đủ từng cách và khi nào nên dùng.

Sự khác nhau giữa cURL và wget khi tải tệp là gì?

cURL hỗ trợ nhiều giao thức hơn và thường phù hợp hơn cho scripting, piping, và tải chính xác từng tệp đơn lẻ hoặc số lượng ít. wget được xây dựng cho việc crawl đệ quy và mirror toàn bộ thư mục website, nên là lựa chọn tốt hơn cho việc lấy hàng loạt tệp tĩnh từ site.

Tại sao cURL lại tải trang HTML thay vì file thật?

Thường có hai nguyên nhân: bạn quên cờ -L nên máy chủ đã chuyển hướng sang chỗ khác, hoặc trang đó cần JavaScript để render nội dung thật — thứ mà curl đơn giản là không thể chạy. Trong trường hợp thứ hai, bạn cần một công cụ có khả năng render chứ không phải thêm thêm cờ cho curl.

Tìm hiểu thêm

Ke
Ke
CTO tại Thunderbit | Chuyên gia Khoa học Dữ liệu cấp cao & ML Với gần một thập kỷ kinh nghiệm trong học máy và khoa học dữ liệu, Ke Shen là cựu sinh viên Đại học Columbia và từng là Chuyên gia Khoa học Dữ liệu cấp cao tại Walmart Labs. Sở hữu chuyên môn sâu về Python, R, Java và Thống kê, được đồng nghiệp công nhận, anh chia sẻ những góc nhìn thực chiến về cách đưa các thuật toán AI phức tạp từ lý thuyết vào kiến trúc sẵn sàng cho môi trường sản xuất.
Topics
tải tệp bằng cURLtự động hóa dòng lệnhtruyền tệp ổn định
Mục lục
Thunderbit · Tác nhân dữ liệu web AI

Trích xuất dữ liệu từ bất kỳ trang nào trong 1 lần nhấp

Được hơn 250.000+ người dùng tin tưởng
có gói miễn phí
Từ trang web đến bảng tính
Mô tả điều bạn cần — AI Agent của Thunderbit sẽ scrape và xuất sang Excel, Google Sheets, Airtable hoặc Notion. Bắt đầu miễn phí.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week