Lệnh curl: cách dùng tùy chọn, yêu cầu POST và tải tệp
Lệnh curl là công cụ gửi yêu cầu tới một địa chỉ web từ terminal và in phản hồi ra đúng như nhận được. Chỉ với một dòng lệnh, bạn có thể kiểm tra nội dung trang, header và mã trạng thái. Khi chúng tôi gửi yêu cầu curl từ máy chủ AlmaLinux 9 tới một trang WordPress, địa chỉ http trả về phản hồi 301 chỉ sang địa chỉ https, còn yêu cầu REST API không xác thực bị từ chối với 401.
1️⃣ Cách dùng cơ bản lệnh curl và nội dung phản hồi
Đặt một địa chỉ sau curl thì curl gửi yêu cầu GET tới địa chỉ đó và in nội dung phản hồi ra màn hình. Khi chúng tôi yêu cầu tệp robots.txt do WordPress tạo, nội dung tệp ba dòng hiện ra đúng như vậy.
curl https://example.com/robots.txtUser-agent: *
Disallow: /wp-admin/
Allow: /wp-admin/admin-ajax.phpBạn dễ mong thấy trang giống như khi gõ địa chỉ vào trình duyệt, nhưng thứ curl in ra là HTML thô mà máy chủ gửi. curl không chạy script và không yêu cầu riêng hình ảnh hay CSS. HTML của trang dài, nên với địa chỉ trang web, chúng tôi chuyển đầu ra qua pipe sang head và chỉ xem vài dòng đầu.
curl -s https://example.com/ | head -n 2<!DOCTYPE html>
<html lang="ko-KR">Thêm -s sẽ ẩn thanh tiến trình vốn lẫn vào màn hình khi chuyển đầu ra qua pipe. HTML nhận được chỉ từ địa chỉ trang chủ là 96.679 byte. Kích thước này không gồm tệp hình ảnh và script.
2️⃣ Kiểm tra header bằng curl -I và theo chuyển hướng bằng -L
Chỉ nhìn nội dung thì không biết yêu cầu có thành công hay không, nên bạn kiểm tra riêng mã trạng thái và header bằng -I. -I gửi yêu cầu HEAD và chỉ in header của phản hồi, không có nội dung. Giống như xem phiếu gửi hàng mà không mở hộp.
curl -I https://example.com/HTTP/2 200
server: nginx/1.28.0
date: Wed, 28 Oct 2026 05:29:23 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
last-modified: Tue, 27 Oct 2026 21:12:18 GMT
cache-control: max-age=0
expires: Wed, 28 Oct 2026 05:29:23 GMT
accept-ranges: none
alt-svc: h3=":443"; ma=86400[HTTP/2 200] ở dòng đầu là mã trạng thái. Bên dưới là loại máy chủ, loại nội dung và các header liên quan đến bộ nhớ đệm. Nếu gửi cùng yêu cầu tới địa chỉ http, bạn nhận 301 kèm địa chỉ https cần chuyển tới trong header [Location].
curl -I http://example.com/HTTP/1.1 301 Moved Permanently
Server: nginx/1.28.0
Date: Wed, 28 Oct 2026 05:27:51 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://example.com/Khi yêu cầu địa chỉ http không kèm tùy chọn, curl không gửi lại yêu cầu tới địa chỉ trong [Location] mà chỉ in 7 dòng nội dung của phản hồi 301 rồi kết thúc.
curl http://example.com/<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.28.0</center>
</body>
</html>Thêm -L thì curl gửi lại yêu cầu tới địa chỉ trong [Location]. Kết hợp với -I thành -IL, header của phản hồi 301 sẽ được theo sau lần lượt bởi header của phản hồi 200.
curl -IL http://example.com/HTTP/1.1 301 Moved Permanently
Server: nginx/1.28.0
Date: Wed, 28 Oct 2026 05:29:23 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://example.com/
HTTP/2 200
server: nginx/1.28.0
date: Wed, 28 Oct 2026 05:29:23 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
last-modified: Tue, 27 Oct 2026 21:12:18 GMT
cache-control: max-age=0
expires: Wed, 28 Oct 2026 05:29:23 GMT
accept-ranges: none
alt-svc: h3=":443"; ma=86400Trong sơ đồ dưới đây, bạn có thể so sánh từng bước số lần gửi yêu cầu và những gì hiện trên màn hình với mỗi tùy chọn.
3️⃣ Tải tệp bằng lệnh curl (-o, -O)
-O lưu tệp vào thư mục hiện tại với tên tệp cuối cùng trong địa chỉ. Trong lúc lưu, màn hình hiện thanh tiến trình thay cho nội dung.
curl -O https://example.com/wp-includes/images/w-logo-blue.png % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 3113 100 3113 0 0 178k 0 --:--:-- --:--:-- --:--:-- 190kls -l w-logo-blue.png-rw-r--r-- 1 root root 3113 Oct 28 14:29 w-logo-blue.pngSau khi tải, [Total] và [Received] trên thanh tiến trình đều là 3113, và kích thước tệp kiểm tra bằng ls -l cũng khớp: 3.113 byte.
Muốn tự đặt tên tệp, bạn viết tên tệp sau -o. Dưới đây là kết quả lưu địa chỉ trang chủ thành home.html.
curl -o home.html https://example.com/ % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 96679 0 96679 0 0 4291k 0 --:--:-- --:--:-- --:--:-- 4291kls -l home.html-rw-r--r-- 1 root root 96679 Oct 28 14:29 home.html-O dùng nguyên tên tệp ở cuối địa chỉ, nên không hợp với địa chỉ trang kết thúc bằng dấu gạch chéo. Thêm -O vào địa chỉ trang chủ thì curl không tìm được tên tệp và kết thúc với lỗi bên dưới.
curl -O https://example.com/curl: Remote file name has no length!
curl: (23) Failed writing received data to disk/application4️⃣ Yêu cầu POST với curl và gửi dữ liệu JSON
Muốn gửi dữ liệu kèm một yêu cầu trước giờ chỉ đọc, bạn dùng -d, và thêm -H để nêu định dạng dữ liệu. -d gửi dữ liệu viết phía sau làm nội dung POST. Nếu không chỉ định gì thêm, [Content-Type] là [application/x-www-form-urlencoded].
Khi dùng -d, phương thức yêu cầu chuyển thành POST, nên bạn có thể bỏ [-X POST]. Tài liệu chính thức cũng giải thích rằng thường không cần -X.
Khi gửi JSON, dùng -H để đổi [Content-Type] thành [application/json]. Dưới đây là kết quả gửi yêu cầu tạo bài viết tới REST API của WordPress mà không xác thực.
curl -s -X POST -H 'Content-Type: application/json' -d '{"title":"curl test"}' https://example.com/wp-json/wp/v2/posts{"code":"rest_authentication_error","message":"\uc8c4\uc1a1\ud569\ub2c8\ub2e4. REST API \uc694\uccad\uc744 \ud560 \uc218 \uc788\ub294 \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.","data":{"status":401}}Trang mà chúng tôi gửi yêu cầu chặn các yêu cầu REST API từ người chưa đăng nhập nên code trả về [rest_authentication_error] và trạng thái là 401. Cũng vì thiết lập đó, yêu cầu GET danh sách bài viết ở cùng địa chỉ cũng trả về 401. Giá trị message là câu báo lỗi viết bằng ngôn ngữ của trang, được chuyển sang dạng Unicode của JSON.
Muốn chỉ xem mã trạng thái, bỏ nội dung bằng [-o /dev/null] và chỉ in http_code bằng -w.
curl -s -o /dev/null -w '%{http_code}\n' -X POST -H 'Content-Type: application/json' -d '{"title":"curl test"}' https://example.com/wp-json/wp/v2/posts4015️⃣ Đo thời gian phản hồi bằng lệnh curl (-w)
Khi phản hồi chậm, người ta dễ chỉ nhìn total, nhưng muốn biết thời gian tốn ở khâu kết nối hay khâu xử lý của máy chủ thì phải in riêng thời gian từng giai đoạn. -w in các giá trị đo theo định dạng bạn chỉ định sau khi yêu cầu kết thúc. Giá trị được điền vào các chỗ [%{tên biến}] trong định dạng.
Bỏ nội dung bằng [-o /dev/null] và ẩn thanh tiến trình bằng -s.
curl -o /dev/null -s -w 'code: %{http_code}\nconnect: %{time_connect}\ntls: %{time_appconnect}\nttfb: %{time_starttransfer}\ntotal: %{time_total}\n' https://example.com/code: 200
connect: 0.001507
tls: 0.017728
ttfb: 0.021912
total: 0.022825connect là kết nối TCP, tls là quá trình bắt tay TLS, ttfb là thời gian tới ngay trước khi byte đầu tiên được gửi, còn total là thời gian tới khi truyền xong. Cả bốn giá trị đều là số giây cộng dồn từ lúc bắt đầu yêu cầu.
Vì máy chủ chạy curl và trang nhận yêu cầu nằm trên cùng một máy chủ, kết nối chỉ mất 0,0015 giây, bắt tay TLS xong lúc 0,0177 giây và byte đầu tiên tới lúc 0,0219 giây. Từ lúc bắt tay TLS xong tới khi byte đầu tiên tới mất khoảng 0,004 giây. Tài liệu chính thức giải thích rằng giai đoạn này gồm cả thời gian máy chủ tạo kết quả.
Khi chạy cùng lệnh thêm ba lần, total nằm trong khoảng 0,0219 đến 0,0226 giây.
🔲 Trình mô phỏng lệnh curl
Trong trình mô phỏng dưới đây, bạn có thể tự gõ các lệnh đã xem và kiểm tra đầu ra thay đổi thế nào với mỗi tùy chọn.
🔢 FAQ & nội dung đề xuất






ℹ️ Thông báo tiếp thị liên kết
Nội dung trên trang này có chứa liên kết affiliate (tiếp thị liên kết). Khi khách truy cập mua sản phẩm hoặc dịch vụ qua các liên kết này, trang sẽ nhận hoa hồng từ bên bán. Trong quá trình đó, số tiền người mua phải trả (sẽ giảm khi có chương trình khuyến mãi ↓) không hề tăng lên. Giá, khuyến mãi và tình trạng hàng được đăng theo thời điểm viết bài và có thể khác với thực tế, vì vậy hãy kiểm tra lại lần cuối với bên bán trước khi mua. Việc chọn và đánh giá sản phẩm dựa trên tiêu chí riêng của trang; việc có nhận hoa hồng hay không không ảnh hưởng đến thứ tự giới thiệu hay nội dung đánh giá.

