Knowledge
The complete guide to the curl command
#CommandLine
A complete guide to the curl command: downloads, following redirects, headers, methods, data, auth, verbose output, and uploading files.
Published by Mark van Eijk on June 23, 2026 · 3 minute read
- What curl is
- The basic GET request
- Downloading files
- Following redirects
- Sending headers
- Choosing the HTTP method
- Sending data
- Authentication
- Inspecting responses
- The -k flag, and why to avoid it
- Uploading files
- Wrapping up
What curl is
curl is the Swiss Army knife for talking to anything over a URL from your terminal. HTTP, HTTPS, FTP, and more. I reach for it constantly: testing an API, downloading a file, checking what headers a server returns, debugging a redirect. It's installed by default on macOS and almost every Linux distro. This guide is the reference I wish I'd had when I started.
The basic GET request
With no flags at all, curl fetches a URL and prints the body to your terminal:
curl https://example.com
That's a plain GET request. For working with JSON APIs specifically (sending data, parsing responses), I've got a focused walkthrough in curl POST and GET API requests. This guide covers the whole toolbox.
Downloading files
To save the response instead of printing it, use -o (lowercase) with a filename, or -O (uppercase) to keep the remote filename:
curl -o latest.tar.gz https://example.com/releases/v2.tar.gz
curl -O https://example.com/releases/v2.tar.gz
Add -# for a progress bar, or -s to silence the progress meter entirely (handy in scripts).
Following redirects
By default, curl does not follow redirects. If a URL returns a 301 or 302, you'll just see the redirect response, not the final page. Add -L to follow it:
curl -L https://example.com
This trips people up constantly when a download "comes back empty". It's almost always a redirect that curl didn't follow. When in doubt, add -L.
Sending headers
Use -H to add request headers. You can repeat it as many times as you need:
curl -H "Accept: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
https://api.example.com/user
Choosing the HTTP method
-X sets the method. GET is the default, so you mostly need this for POST, PUT, DELETE, and friends:
curl -X DELETE https://api.example.com/posts/42
Note that when you send data with -d (next section), curl switches to POST automatically, so you don't always need -X POST.
Sending data
-d sends a request body. This implies POST and a form content type:
curl -d "name=ada&role=admin" https://api.example.com/users
For JSON, set the header explicitly and pass a JSON string:
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name": "Ada", "role": "admin"}'
To read the body from a file instead of inlining it, use @:
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d @payload.json
Authentication
For HTTP basic auth, -u takes user:password:
curl -u admin:secret https://api.example.com/private
Leave the password off (-u admin) and curl prompts for it, which keeps it out of your shell history. Token-based APIs usually want a header instead, via the Authorization header shown earlier.
Inspecting responses
To see only the response headers, use -I (a HEAD request):
curl -I https://example.com
When something's behaving strangely, -v (verbose) shows the full exchange: the request line, every header sent and received, and the TLS handshake:
curl -v https://example.com
This is my go-to for debugging anything HTTP. If you want the body and the headers together without full verbosity, use -i instead.
The -k flag, and why to avoid it
-k (or --insecure) tells curl to skip TLS certificate verification:
curl -k https://self-signed.local # avoid in production
It's tempting when you hit a certificate error, but it disables the protection that stops man-in-the-middle attacks. Use it only against your own local services with self-signed certs. If you're getting an SSL error against a real site, fix the certificate trust instead. The curl error 60 SSL certificate guide explains how.
Uploading files
To upload a file as a multipart form (like a browser form upload), use -F:
curl -F "file=@photo.jpg" https://api.example.com/upload
To upload raw file contents as the body (common for PUT to object storage), use -T:
curl -T backup.tar.gz https://storage.example.com/bucket/backup.tar.gz
Wrapping up
Most real curl commands are just a few of these flags stacked together: a method, a couple of headers, some data, and -L. Once those are muscle memory, curl handles almost any "I need to hit this URL" situation you'll run into.
Subscribe to our newsletter
Do you want to receive regular updates with fresh and exclusive content to learn more about web development, hosting, security and performance? Subscribe now!
Related articles
Argument list too long (Bash: /bin/rm)
A complete guide to the curl command: downloads, following redirects, headers, methods, data, auth, verbose output, and uploading files.
How to install Composer packages locally
A complete guide to the curl command: downloads, following redirects, headers, methods, data, auth, verbose output, and uploading files.