Toolmingo
Guides7 min read

curl Cheat Sheet: Every Flag You Actually Need

A complete curl cheat sheet — GET/POST/PUT/DELETE requests, headers, auth, file upload, download, timeouts, verbose output, and more. Copy-ready curl commands.

curl is in every developer's daily toolkit — for testing APIs, debugging HTTP, downloading files, and automating requests. This reference covers the flags you actually use.

Quick reference

Flag What it does
-X METHOD Set HTTP method (GET/POST/PUT/DELETE/PATCH)
-H "Header: value" Add a request header
-d "data" Send request body
--data-raw "data" Send raw body (no escaping)
-u user:pass Basic auth
-b "name=val" Send cookie
-c cookies.txt Save cookies to file
-o file Save response to file
-O Save with server filename
-L Follow redirects
-I HEAD request (headers only)
-i Show response headers + body
-v Verbose — show full request/response
-s Silent (no progress meter)
-w "%{http_code}" Print specific info after request
--max-time 10 Timeout in seconds
-k Skip SSL certificate verification
--compressed Request gzip + decompress response
--http2 Force HTTP/2
-x http://proxy:8080 Use proxy

GET requests

# Basic GET
curl https://api.example.com/users

# Pretty-print JSON (pipe to jq)
curl -s https://api.example.com/users | jq .

# Show only HTTP status code
curl -s -o /dev/null -w "%{http_code}" https://example.com

# Check if site is up (200 OK)
curl -sI https://example.com | head -1

# Follow redirects
curl -L https://bit.ly/some-short-link

# GET with query parameters
curl "https://api.example.com/search?q=hello+world&page=1"

POST requests

# POST JSON body
curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "email": "alice@example.com"}'

# POST form data (application/x-www-form-urlencoded)
curl -X POST https://example.com/login \
  -d "username=alice&password=secret"

# POST form data — shorthand (curl infers POST + form content-type)
curl -F "username=alice" -F "password=secret" https://example.com/login

# POST with a JSON file
curl -X POST https://api.example.com/import \
  -H "Content-Type: application/json" \
  -d @payload.json

PUT / PATCH / DELETE

# PUT — replace resource
curl -X PUT https://api.example.com/users/42 \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "email": "alice@example.com"}'

# PATCH — partial update
curl -X PATCH https://api.example.com/users/42 \
  -H "Content-Type: application/json" \
  -d '{"email": "newemail@example.com"}'

# DELETE
curl -X DELETE https://api.example.com/users/42

Headers

# Add a custom header
curl -H "X-Custom-Header: myvalue" https://api.example.com

# Multiple headers
curl \
  -H "Accept: application/json" \
  -H "X-Request-ID: abc123" \
  https://api.example.com/data

# Remove a header curl sends by default (e.g., User-Agent)
curl -H "User-Agent:" https://api.example.com

# Set custom User-Agent
curl -A "MyApp/1.0" https://api.example.com

Authentication

# Bearer token (JWT / OAuth)
curl -H "Authorization: Bearer eyJhbGci..." https://api.example.com/me

# Basic auth
curl -u alice:secretpassword https://api.example.com/admin

# Basic auth — prompt for password (don't put it in shell history)
curl -u alice https://api.example.com/admin

# API key in header
curl -H "X-API-Key: your-api-key" https://api.example.com/data

# API key in query string
curl "https://api.example.com/data?api_key=your-api-key"

# Digest auth
curl --digest -u alice:password https://api.example.com/secure

File upload

# Upload a file as multipart/form-data
curl -X POST https://api.example.com/upload \
  -F "file=@/path/to/file.jpg"

# Upload with custom field name and MIME type
curl -X POST https://api.example.com/upload \
  -F "photo=@avatar.png;type=image/png"

# Upload multiple files
curl -X POST https://api.example.com/upload \
  -F "files=@photo1.jpg" \
  -F "files=@photo2.jpg"

# PUT a raw file (binary upload)
curl -X PUT https://api.example.com/image \
  -H "Content-Type: image/jpeg" \
  --data-binary @avatar.jpg

Download files

# Download and save with given filename
curl -o downloaded.zip https://example.com/archive.zip

# Download and keep the server filename
curl -O https://example.com/archive.zip

# Download multiple files
curl -O https://example.com/file1.txt -O https://example.com/file2.txt

# Download with progress bar (default, just remove -s)
curl -O https://example.com/large-file.iso

# Resume interrupted download
curl -C - -O https://example.com/large-file.iso

# Download only if modified since date
curl -z "Mon, 01 Jan 2025 00:00:00 GMT" -O https://example.com/data.csv

Cookies

# Send a cookie
curl -b "session=abc123; theme=dark" https://example.com

# Save cookies from response to file
curl -c cookies.txt https://example.com/login -d "user=alice&pass=secret"

# Send cookies from file (for subsequent requests)
curl -b cookies.txt https://example.com/dashboard

# Session: save + send cookies (login then use session)
curl -c cookies.txt -b cookies.txt \
  -X POST https://example.com/login \
  -d "user=alice&pass=secret"
curl -c cookies.txt -b cookies.txt https://example.com/dashboard

Output and debugging

# Verbose — see full headers, TLS handshake, redirects
curl -v https://api.example.com/data

# Only response headers (HEAD request)
curl -I https://example.com

# Show response headers then body
curl -i https://api.example.com/data

# Silent mode (no progress, no errors)
curl -s https://api.example.com/data

# Silent with errors still shown
curl -sS https://api.example.com/data

# Write-out: print timing/status info
curl -s -o /dev/null -w "Status: %{http_code}\nTime: %{time_total}s\nSize: %{size_download} bytes\n" https://example.com

# Trace — full byte-level dump (extreme debug)
curl --trace-ascii - https://example.com

Useful -w variables

Variable What it prints
%{http_code} HTTP status code (200, 404…)
%{time_total} Total request time (seconds)
%{time_connect} Time to establish TCP connection
%{time_starttransfer} Time to first byte (TTFB)
%{size_download} Downloaded bytes
%{speed_download} Average download speed
%{url_effective} Final URL after redirects

Timeouts and retries

# Max total time for entire request (seconds)
curl --max-time 10 https://api.example.com/slow

# Connection timeout only
curl --connect-timeout 5 https://api.example.com

# Retry on transient errors (500, network failure)
curl --retry 3 https://api.example.com/data

# Retry with delay between attempts (seconds)
curl --retry 3 --retry-delay 2 https://api.example.com/data

# Retry on any HTTP error (4xx/5xx)
curl --retry 3 --retry-all-errors https://api.example.com/data

SSL / TLS

# Skip SSL certificate verification (dev/self-signed only — never in production)
curl -k https://localhost:8443/api

# Use specific CA bundle
curl --cacert /path/to/ca-bundle.crt https://api.example.com

# Client certificate authentication (mTLS)
curl --cert client.crt --key client.key https://api.example.com/secure

# Show certificate info
curl -v --head https://example.com 2>&1 | grep -A5 "Server certificate"

# Force TLS version
curl --tls-max 1.2 https://legacy.example.com

Proxy

# HTTP proxy
curl -x http://proxy.company.com:8080 https://api.example.com

# SOCKS5 proxy (e.g., SSH tunnel)
curl --socks5 127.0.0.1:1080 https://api.example.com

# Proxy with auth
curl -x http://user:pass@proxy.company.com:8080 https://api.example.com

# Bypass proxy for specific hosts
curl --noproxy "internal.company.com" -x http://proxy:8080 https://external.com

Parallel / multiple requests

# Run multiple URLs sequentially
curl https://api.example.com/a https://api.example.com/b

# Parallel (--parallel flag, curl 7.66+)
curl --parallel \
  https://api.example.com/a \
  https://api.example.com/b \
  https://api.example.com/c

# URL globbing — request /item/1 through /item/10
curl https://api.example.com/item/[1-10]

# URL list from a file
xargs -a urls.txt curl -s -o /dev/null -w "%{http_code} %{url_effective}\n"

Config files

For flags you use on every request, put them in ~/.curlrc:

# ~/.curlrc
silent
show-error
location          # follow redirects
max-time = 30
compressed        # request gzip

Or use a per-project config:

curl --config project.curlrc https://api.example.com/data

Common patterns

Health check script

#!/bin/bash
STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://api.example.com/health)
if [ "$STATUS" != "200" ]; then
  echo "Health check failed: $STATUS"
  exit 1
fi
echo "OK: $STATUS"

API request with JSON and auth

# Store base URL and token in variables
BASE="https://api.example.com"
TOKEN="eyJhbGci..."

# GET
curl -s -H "Authorization: Bearer $TOKEN" "$BASE/users" | jq .

# POST
curl -s -X POST "$BASE/users" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Bob"}' | jq .

Measure response time

curl -s -o /dev/null -w "
    DNS:         %{time_namelookup}s
    Connect:     %{time_connect}s
    TLS:         %{time_appconnect}s
    TTFB:        %{time_starttransfer}s
    Total:       %{time_total}s
    Size:        %{size_download} bytes
" https://example.com

Loop over IDs

for ID in 1 2 3 4 5; do
  curl -s "https://api.example.com/users/$ID" | jq '.name'
done

6 common mistakes

Mistake Problem Fix
Forgetting quotes around URL with ? Shell expands ? as glob Always quote URLs: curl "https://api.com?q=hello"
-d with GET request curl changes method to POST automatically Add -G flag for GET with body params, or use --data-urlencode
-k in scripts/CI Skips SSL validation — security risk Use a proper CA bundle instead
--max-time vs --connect-timeout Max-time covers full request; connect-timeout only TCP Set both for production scripts
Not using -s in scripts Progress meter corrupts piped output Always add -s (silent) when piping to jq etc.
Credentials in command line Shell history saves them Use env vars: -H "Authorization: Bearer $TOKEN"

FAQ

How do I send JSON with curl?

curl -X POST https://api.example.com/data \
  -H "Content-Type: application/json" \
  -d '{"key": "value"}'

Both -H "Content-Type: application/json" and -d are required. curl doesn't automatically set Content-Type when using -d.

How do I see what curl actually sent?

Use -v (verbose). It prints request headers prefixed with > and response headers with <. Use --trace-ascii - for the full byte dump.

What's the difference between -o and -O?

-o filename saves to the filename you specify. -O saves using the filename from the URL path. Use -O when the URL ends with the filename you want; use -o when you want to name it yourself.

How do I make curl follow redirects?

Add -L. By default curl stops at the first redirect. -L follows up to 30 redirects (configurable with --max-redirs).

How do I use curl with a proxy?

curl -x http://proxy:8080 https://target.com
# Or set environment variable
export https_proxy=http://proxy:8080
curl https://target.com

How do I test a local API running on localhost?

curl http://localhost:3000/api/users
# For HTTPS with self-signed cert
curl -k https://localhost:8443/api/users

Related tools

Keep reading

All Toolmingotools are free & run in your browser

No sign-up, no upload, no watermark. Your files never leave your device.

Browse all tools