curl
is a versatile command‑line tool (and
libcurl library) for transferring
data with URLs across 24+ protocols—including
HTTP(S), FTP(S), SFTP, SCP, SMTP, POP3, IMAP, MQTT, GOPHER,
and more. It is open‑source, cross‑platform, script‑friendly,
and trusted in production environments from embedded devices to
cloud servers. The project began in 1997 and continues to
publish feature‑rich releases several times a year.
Note: The latest stable
version is 8.13.0
(released 2 April 2025),
introducing --upload-flags
,
extended --url
file support, and several TLS
improvements.
$ curl [options] <URL>
The minimal invocation fetches the resource at <URL>
and streams the response body to stdout
.
Common modifiers:
-o <file>
write output to a file-O
save with remote name-L
follow redirects (libcurl internally sets CURLOPT_FOLLOWLOCATION
)-I
show only the response headers (HTTP HEAD)-h
/ --help
quick option list--manual
open the full man page in your pagerTip: Combine flags concisely:
-LO
will follow redirects and write with the remote filename.
Use -X
or its long form --request
to
specify the verb:
# GET (default)
curl https://api.example.com/users
# POST JSON (using the modern --json helper)
curl --json '{"name":"Ada"}' https://api.example.com/users
# PUT a file
curl -T avatar.png -X PUT https://api.example.com/users/42/avatar
# DELETE
curl -X DELETE https://api.example.com/users/42
--json implicitly sets
-H "Content-Type: application/json"
and
--data
; it was added in version 7.82.0.
curl --data "user=ada&token=123" https://example.com/login
curl -F "file=@report.pdf" -F "comment=FYI" https://example.com/upload
# Plain text
curl --data-binary @message.txt https://hooks.example.com/ingest
# JSON (short form shown earlier)
curl -H "Content-Type: application/json" \
--data '{"x":1,"y":2}' https://api.example.com/points
Note: Use --data-raw
to
send data exactly as given, without extra URL‑encoding. The switch
was introduced in 8.0.0 to supersede --data
quirks.
curl -H "Accept: application/xml" \
-H "X-Token: $TOKEN" \
https://api.example.com/feed
# Store cookies after first request
curl -c cookies.txt https://shop.example.com
# Reuse cookies later
curl -b cookies.txt https://shop.example.com/cart
-u <user:pass>
HTTP Basic / Digest / NTLM / Negotiate--oauth2-bearer <token>
--aws-sigv4 <scope>
(signs headers for AWS APIs)--bearer <token>
alias for OAuth2 Bearer in 8.9+--cert <file>
+ --key <file>
mTLS--proxy-user <u:p>
authenticate to proxy separately
cURL builds can use OpenSSL, WolfSSL, GnuTLS, Schannel, or
Rustls. Recent releases added first‑class TLS 1.3 early data
support via --tls-earlydata
(8.11.0) and extended
cipher suite selection with --ciphers
(8.13.0).
# Insecure (skip CA validation) — for testing only!
curl -k https://self‑signed.badssl.com/
# Specify CA bundle
curl --cacert /etc/ssl/certs/my-ca.pem https://secure.example.com
# Mirror an entire site structure
curl --remote-name --remote-time --output-dir ./site \
--create-dirs --continue-at - --parallel \
--url https://example.com/{index.html,assets/*.css}
Tip: Combine --continue-at -
with --parallel
(added in 7.66) for fast,
resumable batch downloads.
# Cancel if connection > 5 s or transfer > 2 min
curl --connect-timeout 5 --max-time 120 https://large.example.com
# Cap download to 1 MiB/s
curl --limit-rate 1M -O https://example.com/huge.iso
# HTTP proxy
curl -x http://proxy.local:8080 https://example.org
# SOCKS5 with DNS tunnelling
curl --socks5-hostname 127.0.0.1:9050 https://check.torproject.org
# Human‑readable progress and headers
curl -v https://api.example.com
# Full byte‑level trace
curl --trace-ascii debug.log https://api.example.com/data
For scripts, use --write-out with
variables such as %{http_code}
and
%{size_download}
to capture metrics.
# Parallel download via command file
printf '%s\n' "https://a.com" "https://b.com" > list.txt
curl --parallel --url file://list.txt
Version 8.13 extends --url
so the parameter can
be a file that lists URLs—no -K
/@
indirection needed.
#!/usr/bin/env bash
set -euo pipefail
API=https://api.example.com
DATA=$(curl -s "$API/token")
curl --fail --retry 3 --retry-all-errors \
-H "Authorization: Bearer $DATA" \
-o result.json "$API/report"
Note: In
bash
/zsh
you may enable curl
completion by copying
scripts/zsh.pl
from the source tree.
#include <curl/curl.h>
int main(void){
CURL *easy = curl_easy_init();
if(!easy) return 1;
curl_easy_setopt(easy, CURLOPT_URL, "https://example.com");
curl_easy_setopt(easy, CURLOPT_FOLLOWLOCATION, 1L);
CURLcode rc = curl_easy_perform(easy);
if(rc != CURLE_OK) fprintf(stderr, "%s\n", curl_easy_strerror(rc));
curl_easy_cleanup(easy);
}
Bindings exist for C++, Python (pycurl
),
PHP (curl
extension), Go (cgo
),
Rust (curl-rust
), Swift
(CCurl
), and many other languages.
--pinnedpubkey
to
mitigate MITM when talking to known hosts.--fail-with-body
(7.76+) to surface
response bodies even on HTTP 4xx/5xx.--retry
, --retry-all-errors
,
and --retry-delay
for network‑flaky
automation.--compressed
to request gzip/brotli
and save bandwidth..curlrc
file or via
-K config.txt
.--cacert
) or disable
HTTP/2 (--http1.1
).--connect-timeout
and check proxies /
firewalls.-I -L -v
; loop? check
cookies.less
or converting line
endings; use -O
and compare checksums.man curl
page (online copy)