curl / wget Cheatsheet - Command-line File Download & HTTP Requests

For engineers who call APIs, download files, and debug HTTP purely from the shell. Though often paired, curl and wget have different roles: curl is an HTTP client that suits API calls with methods/headers/cookies, while wget leans toward file fetching with clean resume and recursive mirroring. By the end you can pick the right tool per task, resume large downloads with wget -c, trace API issues with curl -v/-w, and handle proxies and auth.

Web Services·34 commands·Last updated 2026-08-02
curlwgetDownloadhttpCLI

Basic Requests 6

curl https://api.test
curl: print response body to stdout
curl -O https://x/file.zip
curl: save with original name (-O uppercase)
curl -o out.html https://x
curl: save to given filename
wget https://x/file.zip
wget: download with original name by default
wget -O out.html https://x
wget: save to given filename
curl -I https://x
curl: fetch headers only (HEAD)

HTTP Method 5

curl -X POST https://x
curl: specify request method
curl -d 'a=1&b=2' https://x
curl: POST form data (x-www-form-urlencoded by default)
curl -d @body.json https://x
curl: read request body from file
curl -H 'Content-Type: application/json' -d '{"a":1}' https://x
curl: POST JSON
curl -T file.zip https://x/upload
curl: upload file (PUT)

Headers & Cookies 5

curl -H 'Authorization: Bearer TOKEN' https://x
curl: custom header
curl -b cookie.txt https://x
curl: send cookies (from file)
curl -c cookie.txt https://x
curl: store Set-Cookie to file
wget --header="Auth: TOKEN" https://x
wget: custom header
wget --save-cookies c.txt --keep-session-cookies https://x
wget: save session cookies

Download & Resume 5

curl -C - -O https://x/big.iso
curl: resume download
wget -c https://x/big.iso
wget: resume download (-c)
wget -r -np -l 2 https://x/dir/
wget: recursive download (depth-limited)
curl -L https://x
curl: follow redirects (-L)
wget --mirror -p --convert-links https://x
wget: mirror site and localize links

Auth & Proxy 4

curl -u user:pass https://x
curl: basic auth
curl -x http://proxy:8080 https://x
curl: via HTTP proxy
wget -e use_proxy=yes -e http_proxy=http://proxy:8080 https://x
wget: via proxy
curl -k https://x
curl: skip TLS cert check (insecure)

Debug 5

curl -v https://x
curl: verbose (request/response headers)
curl -s -o /dev/null -w "%{http_code}" https://x
curl: print HTTP status only
curl -w "@curl-format.txt" https://x
curl: print timings via format file
wget -S https://x
wget: print response headers
wget --debug https://x
wget: debug mode

curl vs wget 4

Upload files
curl strong (PUT/POST any body); wget weak
Mirror whole site
wget strong (--mirror); curl needs manual scripts
Default output
curl to stdout; wget to disk
Ease of use
wget ready for download; curl more flexible for APIs

Command Examples

Constructing a proper JSON POST request

curl -H 'Content-Type: application/json' -d '{"a":1}' https://x

For larger payloads use curl -d @body.json to read from a file, which avoids command-length limits and quoting pitfalls. The echoed field confirms the server parsed JSON rather than treating the body as a form.

Output

{"ok":true,"received":{"a":1}}

Status code only, with the body discarded

curl -s -o /dev/null -w "%{http_code}" https://x

Handy inside health checks and redirect loops. -o /dev/null is the part people forget — without it the body floods the terminal. The -w string can be widened to add content_type, size_download or time_total.

Output

204

Inspect the handshake: what curl -v reveals about a redirect chain

curl -v https://x

Seeing the 301 here means curl stopped at the first hop: it does not follow redirects unless you add -L. wget follows by default, which is exactly why curl seems to stall where wget succeeds.

Output

*   Trying 93.184.216.34:443...
* Connected to x (93.184.216.34) port 443
> GET / HTTP/2
> Host: x
> User-Agent: curl/8.5.0
> Accept: */*
< HTTP/2 301
< location: https://www.x/
* Connection #0 to host x left intact

Resuming a transfer and crawling a directory, two ways

curl -C - -O https://x/big.iso wget -c https://x/big.iso wget -r -np -l 2 https://x/dir/

The dash in -C - is not optional — it means resume from the current local file size — and -O must be uppercase to reuse the server filename. In the crawl, -np skips parent directory listings and -l 2 caps depth so you do not drag the whole site down.

Common Pitfalls

  • curl -k disables TLS certificate verification. Use it only against self-signed or debug endpoints; baking it into a script or CI job hands the connection to any intermediary in readable and writable form.
  • The cookie file written by curl -c and read by curl -b holds a complete session credential. Keep it out of version control and do not leave it lying around on a shared machine.
  • Credentials passed via curl -u user:pass or an Authorization header end up in your shell history. When the value is sensitive, move it into a config file or read it from the environment instead.
  • curl does not follow redirects by default, so any endpoint that redirects needs -L or you will end up reading a 301/302 body instead of the real content.
  • wget --mirror copies an entire site and with unbounded recursion can pull gigabytes. Always cap depth with -l when pointing at a host that belongs to someone else, and check their terms first.

Tips

  • For large files use resume: curl -C - -O or wget -c, so a dropped connection does not restart.
  • curl does not follow redirects by default — add -L; wget follows by default.
  • To grab just the status code for health checks: curl -s -o /dev/null -w "%{http_code}".
  • When POSTing JSON you must send -H "Content-Type: application/json", or the server parses it as form data.

FAQ

How do I choose between curl and wget — is it about the scenario or personal taste?

There is a real division of labour. curl is an HTTP client built to construct arbitrary requests: custom methods, arbitrary headers, arbitrary bodies, file uploads and formatted timing output all live there, so API work and debugging default to curl. wget is oriented toward fetching files — resumable transfers and recursive mirroring work out of the box, where wget -c resumes a large download and wget --mirror copies a whole site in a single line, tasks that take custom scripting in curl. The rule of thumb: constructing a request means curl, pulling down a batch of files means wget.

A large download was interrupted. How do I resume it with curl and with wget?

For wget it is wget -c, which issues a Range request and skips the part already on disk. With curl the equivalent is curl -C - -O, and every piece of that matters: -C - resumes from the current local file size, and -O keeps the server-provided filename. Both depend on the server honouring Range correctly, and against a server without range support you simply start over — so prefer download sources that support it for large files.

A curl JSON request comes back 415 or with unmappable parameters. What is usually missing?

Almost always the Content-Type header. curl -d sends application/x-www-form-urlencoded by default, so the server parses the payload as a form and ends up with a string it cannot map onto fields; adding -H "Content-Type: application/json" switches it to JSON parsing. Also remember curl -d implicitly makes the request a POST, so override it with -X when you need a different method, and add -L because curl does not follow redirects on its own.

I only want to know whether an endpoint is alive, and the body is huge. How do I get just the status code?

Use curl -s -o /dev/null -w "%{http_code}": -s silences the progress meter, -o /dev/null discards the body, and -w emits the fields named in your format string, leaving a single status code on screen. To learn more, widen the -w string to include content_type, size_download or time_total and get status, type and timing from one request. If typing the format string gets tedious, keep a curl-format.txt and reference it with curl -w "@curl-format.txt".

When debugging a connection, should I read curl -v or wget -S?

They operate at different levels. curl -v prints the full request and response exchange — the request line, request headers, the connection and TLS negotiation progress, then the response headers — so TLS negotiation and redirect chains are all visible, which tells you exactly what the client sent and the server returned. wget -S prints only response headers, which is cleaner for a quick status-code and header check. When the real question is why something is slow or failing, curl -v carries far more because it also shows the client-side waiting.

Official References

Each command links to its official documentation below, so you can verify the latest usage and read deeper.

Maintained by LaoHand

Publicly updated on Aug 2, 2026, continuously proofread against official docs.

Contact Us

Wrong command or description? Send us corrections, business inquiries or product feedback by email.

Contact Us