curl Cheatsheet
Basics
Use this curl reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Shape of a curl command
curl [options] [URL...]. Options may come before or after the URL, and the
default method is GET with the body written to stdout.
curl https://api.example.com/users # GET, body to stdout curl -s https://api.example.com/users # no progress meter curl -sS https://api.example.com/users # quiet, but still show errors curl -i https://api.example.com/users # headers + body curl -I https://api.example.com/users # headers only (HEAD)
Multiple URLs in one invocation reuse the connection. --next (or -:) starts a
fresh option set for the URL that follows it, which is how you send two different
requests in one process.
curl -s https://a.example.com/ -: -X POST -d x=1 https://b.example.com/The flag table
Short and long form together, because both get searched. This is the set that covers almost every real invocation.
| Flag | Long form | Does |
|---|---|---|
-X | --request <m> | Set the method (GET, POST, PUT, DELETE, ...) |
-H | --header <h> | Add a request header, repeatable |
-d | --data <s> | POST body, @file reads a file, newlines stripped |
| — | --data-raw <s> | Same, but a leading @ is literal |
| — | --data-binary <s> | Send bytes exactly, no newline stripping |
| — | --data-urlencode <s> | Percent-encode before sending |
| — | --json <s> | Body plus Content-Type and Accept: application/json |
-F | --form <n=v> | multipart/form-data field, @file uploads |
-G | --get | Move -d data into the query string, use GET |
-T | --upload-file <f> | PUT a file |
-u | --user <u:p> | Basic auth credentials |
| — | --oauth2-bearer <t> | Authorization: Bearer <t> |
-b | --cookie <s|f> | Send cookies from a string or a file |
-c | --cookie-jar <f> | Write received cookies to a file |
-e | --referer <url> | Set Referer |
-A | --user-agent <s> | Set User-Agent |
-L | --location | Follow redirects |
| — | --max-redirs <n> | Cap redirect hops, -1 for unlimited |
| — | --retry <n> | Retry transient failures |
| — | --retry-all-errors | Retry on any error, not just transient ones |
-k | --insecure | Skip TLS verification |
| — | --cacert <f> | Verify against this CA bundle |
-E | --cert <f[:pw]> | Client certificate |
| — | --key <f> | Client private key |
| — | --tlsv1.2 | Minimum TLS version |
| — | --resolve <h:p:ip> | Fake DNS for one host and port |
-x | --proxy <url> | Route through a proxy |
-o | --output <f> | Write body to a file |
-O | --remote-name | Write body to the URL's basename |
-s | --silent | No progress meter, no error text |
-S | --show-error | Re-enable error text under -s |
-f | --fail | Exit 22 on HTTP ≥ 400, discard the body |
-i | --include | Prepend response headers to the output |
-I | --head | HEAD request, headers only |
-v | --verbose | Protocol trace on stderr |
| — | --trace-ascii <f> | Full readable trace including bodies |
-w | --write-out <fmt> | Print a template after the transfer |
| — | --connect-timeout <s> | Cap the connect phase |
| — | --max-time <s> | Cap the whole transfer |
| — | --compressed | Request and transparently decode gzip/br |
| — | --http2 | Negotiate HTTP/2 |
| — | --http3 | Use HTTP/3 over QUIC |
| — | --unix-socket <p> | Talk to a Unix domain socket |
URL globbing
curl expands {} and [] in URLs unless you pass -g / --globoff. Handy for
batches, surprising when a URL legitimately contains a brace.
curl -O "https://ex.com/img[001-010].png" # 10 downloads curl "https://ex.com/{users,orgs,repos}" # 3 requests curl -g "https://ex.com/search?q=a[0]" # globbing off, literal
#1 and #2 in an -o template refer to the first and second glob, which is
how you name the outputs.
curl "https://ex.com/{a,b}/img[1-3].png" -o "#1-#2.png"
.curlrc
A per-user default option file. One option per line, long form, no leading
dashes needed, # comments. Search order is $CURL_HOME/.curlrc, then
$XDG_CONFIG_HOME/curlrc, then $HOME/.curlrc.
# ~/.curlrc silent show-error location compressed connect-timeout = 10 max-time = 60 user-agent = "curl-local"
Load a different file with -K file / --config file, and skip .curlrc
entirely with -q as the first argument.
A
.curlrcthat setsinsecureorsilentis a classic debugging trap, because every later curl on that machine behaves differently from the command you pasted into a ticket. Reproduce withcurl -qwhen a result looks wrong.
Exit codes
curl exits 0 on a completed transfer even when the server answered 404. Use
-f if a bad status should fail the script.
| Code | Meaning |
|---|---|
| 0 | Success |
| 3 | Malformed URL |
| 6 | Could not resolve host |
| 7 | Failed to connect |
| 22 | HTTP error ≥ 400, requires -f |
| 28 | Timeout (--connect-timeout or --max-time) |
| 35 | TLS handshake failure |
| 47 | Too many redirects |
| 52 | Empty reply from server |
| 60 | Peer certificate could not be verified |
curl -fsS https://api.example.com/health || echo "health check failed: $?"
--fail-with-body is the variant that still prints the error body, which is
usually what you want against a JSON API that explains itself in the 4xx.