Cheat Sheet

curl Command Cheat Sheet

curl moves data over HTTP and a few dozen other protocols from the command line, and is already installed on almost every Linux, macOS, and Windows 10 or later machine. This sheet covers the flags you use daily for APIs, downloads, and finding out why a request fails.

Last updated August 29, 2026

GET Requests

CommandWhat it does
GET and print the body
Follow redirects
Silent: no progress meter
Silent, but still print errors
Fail with exit code 22 on HTTP 4xx and 5xx instead of printing the error page
The combination scripts want
Ask for JSON
Set the User-Agent
Set the Referer
Send a cookie
Save cookies from the response to a file
Send cookies from that file on the next call
Ask for gzip and decode it
Pretty-print JSON with jq
Several URLs in one command

POST and JSON

implies POST and sets , so JSON needs the header.

curl -X POST https://api.example.com/items \
  -H "Content-Type: application/json" \
  -d '{"name":"widget","qty":1}'
CommandWhat it does
Form POST (what an HTML form sends)
JSON body from a file
curl 7.82 and newer: sets Content-Type and Accept for you
Same, from a file
PUT
PATCH
DELETE
POST with an empty body
Send a value starting with without reading a file
Send bytes exactly as they are ( strips newlines)

Headers

CommandWhat it does
Add a header
Several headers: repeat
Test a virtual host before DNS points at it
Pin a hostname to an IP; keeps TLS and SNI correct, unlike the Host trick
Remove a default header (name with an empty value)
Send a header with an empty value (trailing semicolon)
Headers from a file, one per line (curl 7.55 and newer)
Fetch compressed without decoding

Authentication

CommandWhat it does
Bearer token
Same, shorter
Basic auth
Basic auth, prompt for the password so it stays out of history
API key in a header
API key as a query parameter (quote the URL)
Digest auth
NTLM, for IIS and Windows proxies
Credentials from ()
Client certificate (mutual TLS)

Downloads

CommandWhat it does
Save with the file name from the URL
Save under a name you choose
Follow redirects, then save (GitHub release assets)
Use the name from the header
Resume a partial download
Progress bar instead of the meter
Several files
Numeric range
Create the target directories
Throttle to 1 MB/s
Only download if newer than the local copy
Discard the body (timing, status checks)
The install-script pattern; read the script first

Uploads

CommandWhat it does
multipart/form-data upload, what a browser file field sends
Set the MIME type and add a text field
Upload under a different name
PUT the file as the raw request body
Trailing slash: PUT to the URL plus the file name
Several files
FTP upload
SFTP upload (curl built with libssh2; lists sftp if so)
Raw bytes in a POST

Response Headers and Status Codes

CommandWhat it does
HEAD request: headers only
Headers followed by the body
Headers of a real GET, for servers that treat HEAD differently
Save the headers to a file
Just the status code
Final code and URL after redirects
Total time in seconds
Which address it actually connected to
Bytes received
Read the format from a file

Where the time goes:

curl -s -o /dev/null -w "dns %{time_namelookup}s  connect %{time_connect}s  tls %{time_appconnect}s  first byte %{time_starttransfer}s  total %{time_total}s  code %{http_code}\n" https://example.com

Verbose and Debugging

CommandWhat it does
Show the request (), response headers (), and connection and TLS details ()
Verbose without the body in the way
Only the headers from the verbose output
Everything on the wire, including bodies
Same, to a file with timestamps
Exit 22 on HTTP errors but still print the body (curl 7.76 and newer)
Force HTTP/1.1 (, for the others)
Force IPv4 ( for IPv6)
Version, TLS backend, and supported protocols
Print the exit code and error text (curl 7.75 and newer)

Certificates and -k

CommandWhat it does
Skip certificate verification (); for testing, not for scripts
Trust a private CA and keep verification on
Use a directory of CA certificates
Certificate chain, issuer, and dates in the lines
0 means the chain verified
Require a stapled OCSP response
Minimum TLS 1.2 ( caps it, for testing old servers)
Windows only: skip the revocation check that fails behind some proxies
Mutual TLS with a private CA

Exit code 60 means the chain did not verify. The SSL checker shows what the server is sending, including a missing intermediate, and the certificate decoder reads a you already have.

Proxies

CommandWhat it does
HTTP proxy
Proxy with credentials ( also works)
SOCKS5 proxy that also resolves DNS; pairs with from the SSH cheat sheet
SOCKS5 with local DNS
Ignore the proxy environment variables
Tunnel through the proxy with CONNECT ()
Environment variables curl honours (, too)

prints when one of those variables is set, which explains many mystery failures.

Query Parameters

CommandWhat it does
Quote URLs with , or the shell backgrounds the command
Encode a value and send it as a query string
Build a query string from pairs instead of a POST body
Same as , curl 7.87 and newer
URL-encode a POST field
URL-encode a file's contents into a field
Brace expansion fetches three URLs
Turn globbing off so and are sent literally

Timeouts and Retries

CommandWhat it does
Give up on connecting after 5 seconds
Cap the whole transfer at 10 seconds (exit code 28)
Retry transient failures (timeouts, 5xx) up to 3 times
Wait 2 seconds between retries instead of backing off
Retry on every error, including connection refused
Treat connection refused as transient
Abort if slower than 1000 bytes/s for 30 seconds
TCP keepalive probe interval ( turns it off)
No output buffering; use for server-sent events and streaming logs

Connectivity Checks

CommandWhat it does
Is the site answering
Is a TCP port open: look for (Ctrl+C to leave)
Quick port probe over HTTP; an SSH banner or means the port is open
Which IP the name resolved to
Test a new server before changing DNS
Send from a specific local address or interface
Your public IPv4 address
Headers and status without the body

For a port you cannot reach from your machine, the SSH port checker tests it from outside your network.

Exit Codes

CodeMeaningUsual cause
SuccessThe transfer finished; HTTP 500 still counts unless you used
Unsupported protocolTypo like , or a build without that protocol
Malformed URLUnquoted spaces or brackets
Could not resolve proxyBad or proxy environment variable
Could not resolve hostDNS is down, the name is wrong, or there is no network
Failed to connectPort closed, service down, or a firewall refused it
Partial fileThe connection dropped mid-download; retry with
HTTP errorA 4xx or 5xx with
Write errorDisk full, or no permission on the path
Read errorThe , , or file is missing or unreadable
Timeout or hit, often a silent firewall
TLS handshake failedHTTPS to an HTTP port, protocol or cipher mismatch, Windows revocation check
Too many redirectsA redirect loop with ( caps it)
Empty replyThe server closed the connection without responding
Send failureConnection dropped while uploading
Receive failureConnection reset by the server, proxy, or load balancer
Certificate not verifiedSelf-signed, expired, private CA, missing intermediate, wrong clock
CA bundle problemBad path or a missing system CA store

shows the code right after curl exits. Codes are documented in under EXIT CODES.

Windows and PowerShell

SituationDo this
Windows PowerShell 5.1 is an alias for ; type to get real curl
PowerShell 7The alias is gone; runs curl.exe
cmd.exe is real curl on Windows 10 1803 and later
JSON in cmd.exeNo single quotes:
JSON in PowerShell 7.3 and newer works as in bash
JSON in older PowerShellInner quotes get stripped; write
Line continuation in cmd.exe, a backtick in PowerShell, not
Certificate errors (exit 35 or 60)Windows curl uses Schannel and the Windows certificate store; if the revocation check fails behind a proxy
Git BashShips its own curl with OpenSSL and its own CA bundle, so results can differ from cmd.exe

Gotchas

  • already means POST. Adding is harmless alone, but with forces POST on the redirect target too, where curl would normally switch to GET.
  • sends HEAD, and some servers answer HEAD with 405 or different headers. shows the headers of a real GET.
  • Quote every URL that contains , , , , or . Unquoted, the shell backgrounds the command at and curl globs the brackets.
  • strips newlines from the file. sends it byte for byte.
  • makes the error go away, not the problem. Find the cause with the SSL checker and fix the chain or add .
  • is visible in shell history and . Use to be prompted, or with a .
  • overwrites an existing file without asking, and lets the server choose the file name.
  • A that works in the terminal but not in cron or CI is usually missing a proxy variable, a , or the CA bundle the shell had.

curl Cheat Sheet FAQ

How do I get just the HTTP status code from curl?
curl -s -o /dev/null -w "%{http_code}\n" URL prints the code and nothing else: -s hides the progress meter, -o /dev/null throws away the body, and -w prints the variable after the transfer. Add -L if the URL redirects, or you will see 301 instead of the final code. In a script, compare it like any string: [ "$(curl -s -o /dev/null -w '%{http_code}' URL)" = 200 ]. If you want curl itself to fail on a bad code, use -f, which turns 4xx and 5xx into exit code 22; --fail-with-body (curl 7.76 and newer) does the same but still shows the error page.
How do I test whether a port is open with curl?
curl -v --max-time 3 telnet://host:22 tries a plain TCP connection: Connected to host means the port is open (press Ctrl+C to leave), Connection refused means something answered but nothing is listening, and a timeout with exit code 28 usually means a firewall is dropping packets. It works for any TCP port, not just HTTP, which makes it a stand-in for nc or telnet on machines that have neither. For HTTP ports, curl -sS -o /dev/null -w "%{http_code}" URL tells you more, because it also proves the service behind the port is answering.
Why does curl -H fail in PowerShell on Windows?
In Windows PowerShell 5.1, curl is an alias for Invoke-WebRequest, a cmdlet with different parameters, so -H, -d, and -X produce errors about ambiguous or unknown parameters. Type curl.exe instead and the real curl runs. PowerShell 7 removed the alias, and cmd.exe never had it, so curl works as expected there. Quoting is the other trap: cmd.exe has no single quotes, so JSON goes in double quotes with the inner ones escaped as \", and PowerShell older than 7.3 strips embedded double quotes from arguments to native programs, so use '{\"a\":1}' there.
What do curl exit codes 6, 7, 28, 35, 56, and 60 mean?
6 is DNS: the hostname did not resolve, so check spelling and your resolver. 7 is TCP: nothing accepted the connection, so the port is closed, the service is down, or a firewall refused it. 28 is a timeout from --max-time or --connect-timeout, which often means a firewall silently dropping packets. 35 is a TLS handshake failure, typically HTTPS to a plain HTTP port, a protocol or cipher mismatch, or on Windows a revocation check that could not run (--ssl-no-revoke). 56 means the connection was cut mid-transfer, usually a reset by a proxy, load balancer, or the server. 60 means the certificate did not verify: self-signed, expired, a private CA curl does not know, a missing intermediate, or a wrong system clock.
How do I make curl ignore SSL certificate errors, and should I?
curl -k URL (long form --insecure) skips certificate verification and connects anyway. Use it to confirm the rest of the request works, then remove it. For a private CA, curl --cacert ca.pem URL trusts that CA without giving up verification, and CURL_CA_BUNDLE=ca.pem in the environment does the same for every call. Before reaching for -k at all, find out why verification failed: curl -vI URL prints the certificate's issuer and dates in the lines marked with an asterisk, and the SSL checker linked on this page shows whether the server is sending its intermediate certificate, which is the usual cause on a freshly configured server.

Related cheat sheets