curl Cheat Sheet
curl -LO https://example.com/file.tar.gz # download, keep remote name
curl -I https://example.com # response headers only
curl -sS https://api.example.com/v1/items | jq # quiet, but still show errors
curl --json '{"name":"x"}' https://api.example.com/v1/items # POST JSON
curl -H "Authorization: Bearer $TOKEN" https://api.example.com/v1/me
curl -v https://example.com -o /dev/null # debug the connection and TLS
Syntax: curl [options] URL.... By default curl does a GET and writes the body to standard output, with a progress meter on standard error when output is redirected. It is preinstalled on Ubuntu, Fedora and most other distros; otherwise install the curl package with apt, dnf, pacman or zypper. Check your version with curl --version, since a few options below need a recent release.
Downloading
| Command | What it does |
|---|---|
curl -O URL | Save under the remote file name |
curl -o name.ext URL | Save under a name you choose |
curl -L URL | Follow redirects (301, 302, 307, 308) |
curl -LOJ URL | Use the file name from the server's Content-Disposition header |
curl -C - -LO URL | Resume an interrupted download |
curl --limit-rate 2M -LO URL | Limit speed to 2 MB/s |
curl -LO URL1 -LO URL2 | Several downloads in one command (-Z for parallel) |
curl -LO 'https://host/img[01-20].jpg' | URL globbing: ranges and {a,b,c} lists |
curl -f -LO URL | Fail (exit 22) on HTTP 4xx/5xx instead of saving the error page |
curl -# -LO URL | Simple progress bar |
curl --create-dirs -o dl/a/b.txt URL | Create missing directories for the output file |
Requests, headers and data
| Command | What it does |
|---|---|
curl -X DELETE URL | Use another HTTP method (PUT, PATCH, DELETE) |
curl -H 'Accept: application/json' URL | Add or override a request header |
curl -A 'Mozilla/5.0' URL | Set the User-Agent |
curl -e https://ref.example URL | Set the Referer |
curl -d 'a=1&b=2' URL | POST URL-encoded form data |
curl --data-urlencode 'q=hello world' URL | POST with the value URL-encoded for you |
curl -G --data-urlencode 'q=linux' URL | Put the data in the query string of a GET instead |
curl --json @body.json URL | POST JSON from a file, sets Content-Type and Accept (curl 7.82+) |
curl -H 'Content-Type: application/json' -d '{"a":1}' URL | POST JSON on older curl versions |
curl -F '[email protected]' -F 'title=Hi' URL | multipart/form-data upload, like an HTML form |
curl -T file.txt URL | Upload a file with PUT (also works for FTP/SFTP) |
curl --variable %TOKEN --expand-header 'Authorization: Bearer {{TOKEN}}' URL | Insert an environment variable into an option without exposing it in ps (curl 8.3+) |
Authentication and cookies
| Command | What it does |
|---|---|
curl -u alice URL | HTTP Basic auth, prompt for the password |
curl -u alice:secret URL | Password on the command line (visible in history and ps) |
curl -n URL | Read credentials from ~/.netrc |
curl -H "Authorization: Bearer $TOKEN" URL | Bearer token (OAuth, most REST APIs) |
curl --oauth2-bearer "$TOKEN" URL | Same, built-in option |
curl -b 'session=abc' URL | Send a cookie |
curl -c jar.txt -b jar.txt URL | Save and reuse cookies across requests |
curl --cert client.pem --key client.key URL | TLS client certificate (mutual TLS) |
Output, debugging and timing
| Command | What it does |
|---|---|
curl -I URL | HEAD request: headers only |
curl -i URL | Include response headers before the body |
curl -v URL | Verbose: DNS, connection, TLS handshake, request and response headers |
curl --trace-ascii - URL | Full dump of everything sent and received |
curl -s URL | Silent: no progress meter or errors |
curl -sS URL | Silent but still print errors (best for scripts) |
curl -o /dev/null -s -w '%{http_code}\n' URL | Print only the status code |
curl -o /dev/null -s -w '%{time_namelookup} %{time_connect} %{time_starttransfer} %{time_total}\n' URL | Where the time goes: DNS, TCP, first byte, total |
curl -D headers.txt -o body.html URL | Save headers and body to separate files |
curl -w '%{json}' -o /dev/null -s URL | jq | All transfer variables as JSON |
Connections, TLS, proxies and retries
| Command | What it does |
|---|---|
curl --connect-timeout 5 -m 30 URL | 5 s to connect, 30 s for the whole transfer |
curl --retry 5 --retry-delay 2 --retry-all-errors URL | Retry transient failures |
curl -4 URL / curl -6 URL | Force IPv4 or IPv6 |
curl --resolve example.com:443:203.0.113.10 https://example.com | Send to a specific IP without editing /etc/hosts (test a new server) |
curl --connect-to example.com:443:new.example.net:443 https://example.com | Same idea, by host name |
curl -x http://proxy:3128 URL | Use an HTTP proxy (also honours https_proxy env vars) |
curl --socks5-hostname localhost:1080 URL | Use a SOCKS5 proxy, for example ssh -D 1080 |
curl --cacert ca.pem URL | Trust a private CA for this request |
curl --http2 / --http3 | Request a protocol version (HTTP/3 needs a build with it) |
curl --compressed URL | Ask for gzip/brotli/zstd and decompress automatically |
curl -k URL | Skip certificate verification. Testing only. |
Common recipes
Check a list of URLs and print status code and total time:
while read -r u; do
curl -o /dev/null -sS -w "%{http_code} %{time_total}s $u\n" --max-time 10 "$u"
done < urls.txt
Show a site's certificate dates and issuer (the SSL expiry check script automates this):
curl -vsI https://example.com 2>&1 | grep -E 'expire date|start date|issuer|subject:'
Call a JSON API, fail on HTTP errors and extract a field:
curl -fsS -H "Authorization: Bearer $TOKEN" https://api.example.com/v1/user | jq -r '.login'
Test a new server before switching DNS:
curl -sI --resolve www.example.com:443:203.0.113.10 https://www.example.com | head -5
Find your public IP address:
curl -s https://ifconfig.me; echo
Query a local API on a Unix socket (Docker):
curl -s --unix-socket /var/run/docker.sock http://localhost/version | jq .Version
Download and verify before running an installer, instead of piping to a shell:
curl -fsSLo install.sh https://example.com/install.sh
less install.sh # read it
sha256sum install.sh # compare with the published checksum
bash install.sh
Gotchas
- No redirects by default. Without
-Lyou save a tiny HTML redirect page instead of the file. - HTTP errors exit 0. A 404 or 500 is a successful transfer to curl. Use
-f(or--fail-with-body) in scripts. -dswitches to POST. Adding-X POSTas well is redundant, and-X GET -d ...sends a body with GET, which many servers ignore. Use-Gfor query strings.- Shell quoting. Use single quotes around JSON so the shell leaves
$and"alone; use double quotes only when you need a variable expanded, or put the body in a file with-d @file. curl | sudo bashruns code you have not read as root. Download, inspect, and prefer a distro package or an official repository.- Name resolution failures.
curl: (6) Could not resolve hostis a DNS problem on your side; see Temporary failure in name resolution. - Secrets on the command line are visible to other users in
ps. Use-u userwithout the password,~/.netrc, or-H @headers.txt.
The full manual is at curl.se/docs/manpage.html and Everything curl.
Frequently asked questions
How do I download a file with curl?
Use curl -LO URL to save it under its remote name, or curl -L -o name.iso URL to choose the name. -L follows redirects, which most download links use.
How do I send JSON with curl?
On curl 7.82 or newer use curl --json '{"key":"value"}' URL. On older versions use -H 'Content-Type: application/json' -d '{...}'. Read the body from a file with -d @body.json.
How do I see the response headers?
curl -I URL sends a HEAD request and prints only the headers. curl -i URL prints headers and body, and curl -v URL also shows the request and TLS handshake.
Is curl -k safe?
Only for a quick test against your own server. -k disables certificate checks, so anyone in the middle can read and change the traffic. Fix the certificate or point curl at the right CA with --cacert.
What is the difference between curl and wget?
curl writes to standard output and supports many protocols and request types, so it suits APIs and scripts. wget saves to a file by default and can mirror websites recursively, so it suits bulk downloads.
Spotted a mistake or a command that no longer works? Send a correction — pages are re-checked when reports come in.