curl cheatsheet

Comprehensive reference for the URL transfer Swiss-army-knife — Rose Pine theme

Basics

Simplest request

curl https://example.com

Save the response body

curl -o page.html https://example.com
curl -O https://example.com/file.zip  # use remote filename

Silent / quiet

curl -sS https://api.example.com  # silent, but show errors

Follow redirects

curl -L https://example.com

Show only response headers

curl -I https://example.com   # HEAD request
curl -i https://example.com   # GET, include headers in output
curl -D - https://example.com  # dump headers to stdout

HTTP methods

curl -X GET    https://api.example.com/users
curl -X POST   https://api.example.com/users
curl -X PUT    https://api.example.com/users/1
curl -X PATCH  https://api.example.com/users/1
curl -X DELETE https://api.example.com/users/1
curl -X OPTIONS https://api.example.com
Tip: -X is rarely needed — curl infers the method from -d (POST), -T (PUT), -I (HEAD). Don't combine -X POST with -L blindly — redirects may downgrade.

HTTP version

curl --http1.1      https://example.com
curl --http2        https://example.com
curl --http2-prior-knowledge https://example.com
curl --http3        https://example.com  # requires HTTP/3 build

Headers

Send a header

curl -H "Accept: application/json" https://api.example.com
curl -H "X-Request-Id: abc123" \
     -H "User-Agent: my-client/1.0" \
     https://api.example.com

Remove a default header

curl -H "Accept:" https://api.example.com  # empty value removes it

Replace a header with empty value

curl -H "X-Trace;" https://api.example.com  # trailing ;  → empty value

User-Agent / Referer shortcuts

curl -A "Mozilla/5.0"  https://example.com
curl -e "https://google.com" https://example.com

Request body

URL-encoded form (application/x-www-form-urlencoded)

curl -d "user=alice&pass=secret" https://example.com/login
curl --data-urlencode "q=hello world" https://example.com

JSON body

curl -H "Content-Type: application/json" \
     -d '{"name":"alice","age":30}' \
     https://api.example.com/users

# curl 7.82+ shorthand:
curl --json '{"name":"alice"}' https://api.example.com/users
Tip: --json sets Content-Type and Accept to application/json automatically.

Body from a file

curl -d "@payload.json" \
     -H "Content-Type: application/json" \
     https://api.example.com

curl --data-binary "@file.bin" https://example.com  # preserve newlines

Multipart form (multipart/form-data)

curl -F "name=alice" \
     -F "avatar=@./me.png" \
     -F "[email protected];type=application/json" \
     https://example.com/upload

Query string params (URL-encoded)

curl -G \
     --data-urlencode "q=hello world" \
     --data-urlencode "page=1" \
     https://example.com/search
# → GET /search?q=hello%20world&page=1

Authentication

Basic

curl -u "alice:secret" https://api.example.com
curl -u "alice" https://api.example.com  # prompts for password

Bearer token

curl -H "Authorization: Bearer $TOKEN" https://api.example.com
curl --oauth2-bearer "$TOKEN" https://api.example.com

Digest, NTLM, Negotiate

curl --digest    -u "user:pass" https://example.com
curl --ntlm      -u "user:pass" https://example.com
curl --negotiate -u ":"          https://example.com  # Kerberos / SPNEGO

AWS SigV4

curl --aws-sigv4 "aws:amz:us-east-1:s3" \
     -u "$AWS_ACCESS_KEY:$AWS_SECRET_KEY" \
     https://my-bucket.s3.us-east-1.amazonaws.com/key
Caution: Passwords on the CLI leak into shell history and ps. Prefer -u user with a password prompt, a .netrc file, or --config.

.netrc

curl --netrc         https://api.example.com
curl --netrc-file ~/.netrc-prod https://api.example.com

Download & upload

Resume an interrupted download

curl -C - -O https://example.com/big.iso

Limit transfer rate

curl --limit-rate 200K -O https://example.com/big.iso

Range / partial fetch

curl -r 0-1023 -o first-1kb.bin https://example.com/file

Upload with PUT

curl -T ./local.txt https://example.com/remote.txt
curl -T ./local.txt sftp://user@host/path/

Make missing parent directories (FTP/SFTP)

curl --ftp-create-dirs -T file ftp://host/new/dir/

Cookies & sessions

Send cookies

curl -b "sid=abc123" https://example.com
curl -b cookies.txt https://example.com

Save received cookies (cookie jar)

curl -c cookies.txt https://example.com/login

Round-trip a session

curl -c jar.txt -d "user=a&pass=b" https://example.com/login
curl -b jar.txt -c jar.txt https://example.com/dashboard

TLS / certificates

Skip verification (dev only!)

curl -k https://self-signed.local
curl --insecure https://self-signed.local

Custom CA bundle

curl --cacert corp-ca.pem https://internal.corp
curl --capath /etc/ssl/certs https://example.com

Client certificates (mTLS)

curl --cert client.crt --key client.key https://mtls.example.com
curl --cert client.p12:password --cert-type P12 https://example.com

Pinning

curl --pinnedpubkey "sha256//AAAA....=" https://example.com

TLS version

curl --tlsv1.2 --tls-max 1.3 https://example.com

Show negotiated cipher / cert details

curl -vI https://example.com 2>&1 | grep -E "SSL|TLS|subject|issuer"

Proxy & network

HTTP/HTTPS proxy

curl -x http://proxy:8080 https://example.com
curl --proxy-user "u:p" -x http://proxy:8080 https://example.com

SOCKS5

curl --socks5          localhost:1080 https://example.com
curl --socks5-hostname localhost:1080 https://example.com  # DNS via proxy

Force IPv4 / IPv6

curl -4 https://example.com
curl -6 https://example.com

Resolve hostname to fixed IP

curl --resolve example.com:443:1.2.3.4 https://example.com
curl --connect-to example.com:443:newhost:443 https://example.com

Bind to interface / source IP

curl --interface eth0 https://example.com
curl --interface 10.0.0.5 https://example.com

Connect to Unix socket

curl --unix-socket /var/run/docker.sock http://localhost/containers/json

Redirects & retries

curl -L https://example.com
curl -L --max-redirs 5 https://example.com
curl -L --location-trusted https://example.com  # resend auth on redirect

Retries (network errors / 5xx)

curl --retry 5 \
     --retry-delay 2 \
     --retry-max-time 60 \
     --retry-all-errors \
     https://api.example.com

Timeouts

curl --connect-timeout 5 \
     --max-time 30 \
     https://example.com

Fail-fast on HTTP errors

curl -f https://example.com            # exit 22 on 4xx/5xx, hide body
curl --fail-with-body https://example.com  # same, but keep body

Output & timing

Get just the HTTP status code

curl -o /dev/null -s -w "%{http_code}\n" https://example.com

Full timing breakdown

curl -o /dev/null -s -w "\
dns:      %{time_namelookup}s\n\
connect:  %{time_connect}s\n\
tls:      %{time_appconnect}s\n\
ttfb:     %{time_starttransfer}s\n\
total:    %{time_total}s\n\
size:     %{size_download} bytes\n\
status:   %{http_code}\n" https://example.com

Useful -w variables

VariableMeaning
%{http_code}response status
%{url_effective}final URL after redirects
%{redirect_url}next URL when redirecting
%{remote_ip}resolved peer IP
%{ssl_verify_result}0 = ok
%{size_download}bytes received
%{speed_download}bytes/sec
%{json}all timing fields as JSON (7.70+)

Debugging

curl -v  https://example.com  # verbose
curl -vv https://example.com  # even more
curl --trace       trace.log https://example.com
curl --trace-ascii trace.log https://example.com
curl --trace-time  -v https://example.com  # prepend timestamps

Show DNS resolution path

curl --trace-config all -v https://example.com

Show curl version & protocols

curl --version
curl-config --features
Pro tip: Browser DevTools → right-click any request → Copy as cURL. Replays the exact request from your terminal — invaluable for debugging API issues.

Parallel & multi-URL

Multiple URLs in one invocation

curl https://example.com/1 https://example.com/2

Parallel (curl 7.66+)

curl -Z --parallel-max 10 \
     https://example.com/[1-100].json \
     -o "out/#1.json"

URL globbing

curl https://example.com/file[1-5].txt -O
curl https://example.com/{red,green,blue}.png -O
curl https://example.com/page[1-100:2].html -O  # step 2

Disable globbing (URL has literal brackets)

curl -g "https://example.com/[literal]"

Config files & env

~/.curlrc (auto-loaded)

# Lines are long-option-name = value
user-agent = "my-cli/1.0"
connect-timeout = 10
retry = 3
silent

Per-call config

curl -K request.curl

request.curl:

url = "https://api.example.com/users"
request = "POST"
header = "Content-Type: application/json"
data = '{"name":"alice"}'

Useful env vars

VarEffect
HTTP_PROXY / HTTPS_PROXYper-scheme proxy
NO_PROXYcomma-sep hosts to bypass
CURL_HOMEoverride ~/.curlrc dir
CURL_SSL_BACKENDe.g. openssl, secure-transport
SSLKEYLOGFILEdump TLS keys for Wireshark

Other protocols

FTP / FTPS

curl -u "user:pass" ftp://ftp.example.com/dir/
curl -u "user:pass" -T file.zip ftp://ftp.example.com/uploads/
curl --ssl-reqd ftp://ftp.example.com  # require TLS

SFTP / SCP

curl -u "user:" --key ~/.ssh/id_ed25519 sftp://host/path/
curl -u "user:" scp://host:22/etc/hostname

SMTP (send email)

curl --ssl-reqd \
     --url      smtps://smtp.example.com:465 \
     --user     "[email protected]:pw" \
     --mail-from [email protected] \
     --mail-rcpt [email protected] \
     --upload-file message.eml

IMAP

curl -u "alice:pw" imaps://imap.example.com/INBOX      # list
curl -u "alice:pw" "imaps://imap.example.com/INBOX;UID=42" # fetch

WebSocket (curl 7.86+)

curl --include \
     -H "Sec-WebSocket-Version: 13" \
     wss://echo.example.com

MQTT, DICT, LDAP, TFTP, GOPHER

curl dict://dict.org/d:curl
curl mqtt://broker.example.com/topic
curl ldap://ldap.example.com/dc=example,dc=com

Real-world recipes

JSON POST + jq pipeline

curl -sS --json '{"q":"curl"}' https://api.example.com/search | jq '.hits[].title'

Token-aware API call

TOKEN="$(cat ~/.config/myapp/token)"
curl -sS --fail-with-body \
     -H "Authorization: Bearer $TOKEN" \
     -H "Accept: application/json" \
     https://api.example.com/me

Test endpoint health in a script

code=$(curl -o /dev/null -s -w "%{http_code}" --max-time 5 https://api.example.com/health)
if [ "$code" != "200" ]; then
  echo "unhealthy: $code" >&2
  exit 1
fi

Mirror a static site

curl -O https://example.com/index.html
# for real mirroring use wget; curl has no recursive mode

Test redirect chain

curl -sIL -o /dev/null -w "%{http_code} → %{url_effective}\n" \
     https://bit.ly/abc

Reproduce a flaky request

for i in {1..50}; do
  curl -o /dev/null -s -w "%{http_code} %{time_total}s\n" \
       https://api.example.com/v1/widgets
done | sort | uniq -c

Capture TLS keys for Wireshark

SSLKEYLOGFILE=/tmp/keys.log curl https://example.com

OAuth2 client_credentials grant

curl -sS -X POST https://auth.example.com/oauth/token \
     -u "$CLIENT_ID:$CLIENT_SECRET" \
     -d "grant_type=client_credentials" \
     -d "scope=read:widgets" | jq -r .access_token

GitHub API: list your repos

curl -sS \
     -H "Accept: application/vnd.github+json" \
     -H "Authorization: Bearer $GH_TOKEN" \
     https://api.github.com/user/repos?per_page=100