Curl Cheatsheet
Introduction
Curl is an invaluable tool for anyone who needs to debug webapps fequently. Given it’s vast amount of options, it is easy to miss some of it’s simplest yet powerful uses.
Listing here some options that I use everyday. Use the topics below to navigate direct to what you are looking for.
I’ll keep updating it as and when I discover something new! 🤘
Inspect
Response headers
The simplest way to do that is by using the -I
option -
1$ curl -I https://httpbin.org/ip
2
3HTTP/2 200
4date: Thu, 12 Nov 2019 19:08:13 GMT
5content-type: application/json
6content-length: 32
7server: gunicorn/19.9.0
8access-control-allow-origin: *
9access-control-allow-credentials: true
The above works in most cases, but if your webapp/endpoint doesn’t support the HEAD
method or behaves differently to it compared to the usual GET
method, this will dissappoint you.
To inspect the headers with a GET
method, following options can be helpful.
Simplest option is to use -i
(don’t confuse it with -I
described above), this includes response headers with the response body
1$ curl -D - https://httpbin.org/ip -s -o /dev/null
2HTTP/2 200
3date: Wed, 28 Aug 2024 13:24:44 GMT
4content-type: application/json
5content-length: 32
6server: gunicorn/19.9.0
7access-control-allow-origin: *
8access-control-allow-credentials: true
9
10{
11 "origin": "x.x.x.x"
12}
A slightly more verbose way of doing the same thing is using the -D
flag
1$ curl -D - https://httpbin.org/ip -s -o /dev/null
2
3HTTP/2 200
4date: Thu, 12 Nov 2019 19:10:39 GMT
5content-type: application/json
6content-length: 32
7server: gunicorn/19.9.0
8access-control-allow-origin: *
9access-control-allow-credentials: true
OK, this works 👍 but there are a lot of options. What do they mean?
-D
dump the headers to a file.-
dump it to stdin instead of a file.-s
suppress the progress update (like the following), helps to keep the output clean.1% Total % Received % Xferd Average Speed Time Time Time Current 2 Dload Upload Total Spent Left Speed 30 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0HTTP/2 200
-o
send any output to file-o /dev/null
discard the response completely.
Request headers
Use -v
to inspect request headers. Check the request headers on the lines starting with >
1$ curl -v https://httpbin.org/ip -s -o /dev/null
2
3* Trying 3.211.1.78:443...
4* Connected to httpbin.org (3.211.1.78) port 443 (#0)
5* Using HTTP2, server supports multi-use
6* Connection state changed (HTTP/2 confirmed)
7* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
8} [5 bytes data]
9* Using Stream ID: 1 (easy handle 0x1da3b7de150)
10} [5 bytes data]
11> GET /ip HTTP/2
12> Host: httpbin.org
13> user-agent: curl/7.73.0
14> accept: */*
Redirects
Redirects are implemented for a variety of reasons. Redirect responses return a 30X
response code and a location
header which tells the requestor where to go next. The following request gives us these specific fields while filtering out the rest.
1$ curl https://httpbin.org/status/302 -w "%{response_code} %{redirect_url}" -s -o /dev/null
2302 https://httpbin.org/redirect/1
OK, this is nice 👌 but what does -w
do?
-w
is write-out option and takes a number of variables. These variables need to be enclosed in a%{ }
block. I have used 2 here.response_code
andredirect_url
which are, sort of, self explanatory. Full list of supported variables is here.
What if you want to inspect redirects for multiple pages? Easy, follow the linux philosophy and stack your commands. Add the urls in a list and run a one liner loop. Let’s also format the output a bit while we are at it.
https://httpbin.org/status/301
https://httpbin.org/status/302
https://httpbin.org/status/307
1$ while read url; do curl $url -w " %{response_code} | $url --> %{redirect_url} \n" -s -o /dev/null; done < urls.txt
2
3301 | https://httpbin.org/status/301 --> https://httpbin.org/redirect/1
4302 | https://httpbin.org/status/302 --> https://httpbin.org/redirect/1
5307 | https://httpbin.org/status/307 --> https://httpbin.org/redirect/1
Customize Requests
Inspecting requests is not all that curl is capable of. You can customize the outgoing requests to your heart’s liking. Adding a few common scenarios below.
Authorization
To pass authentication headers to an API, simply add the required header using -H
1$ curl "https://httpbin.org/headers" -H "Authorization: bearer secrettoken"
2
3{
4 "headers": {
5 "Accept": "*/*",
6 "Authorization": "bearer secrettoken",
7 "Host": "httpbin.org",
8 "User-Agent": "curl/8.7.1",
9 "X-Amzn-Trace-Id": "Root=1-66cf0a02-7f81812758215deb6aba0be3"
10 }
11}
Note: You can also read the auth header from a file as well, see example below in Custom headers section.
Modify User-Agent
By default, curl uses a user-agent request header like, user-agent: curl/7.73.0
If you need to send a custom user-agent, simply use the -A
option. Check the User-Agent
key value in the returned json response.
1$ curl https://httpbin.org/headers -A "bob-the-builder"
2
3{
4 "headers": {
5 "Accept": "*/*",
6 "Host": "httpbin.org",
7 "User-Agent": "bob-the-builder",
8 "X-Amzn-Trace-Id": "Root=1-5fadb05b-490211b54febef30592912b5"
9 }
10}
Custom headers
To send custom headers with a request, you can use the -H
option. Check the headers
section in the returned json response.
1$ curl https://httpbin.org/headers -H "CustomHeader1: value1" -H "CustomHeader2: value2"
2
3{
4 "headers": {
5 "Accept": "*/*",
6 "Customheader1": "value1",
7 "Customheader2": "value2",
8 "Host": "httpbin.org",
9 "User-Agent": "curl/7.73.0",
10 "X-Amzn-Trace-Id": "Root=1-5fadb190-26af70e1691093c76d180401"
11 }
12}
Headers can also be read from a file, like shown below. We pass the auth header and content type header from a file headers.txt
1$ cat headers.txt
2Authorization: bearer secrettoken
3Content-Type: application/json
1$ curl "https://httpbin.org/headers" -H "@headers.txt"
2
3{
4 "headers": {
5 "Accept": "*/*",
6 "Authorization": "bearer secrettoken",
7 "Content-Type": "application/json",
8 "Host": "httpbin.org",
9 "User-Agent": "curl/8.7.1",
10 "X-Amzn-Trace-Id": "Root=1-66cf0b27-3e65ca6a3dc1e4db5f2008d8"
11 }
12}
Cookies
To send cookies with a request, you can use the -b
option. Cookies can either be provided inline, or read from a file.
Check the cookies
field in the json response below.
Send the cookie values inline
1$ curl https://httpbin.org/cookies -b "country=GB; language=EN; debug=1"
2
3{
4 "cookies": {
5 "country": "GB",
6 "debug": "1",
7 "language": "EN"
8 }
9}
Send the cookie values from a file
1$ curl https://httpbin.org/cookies -b cookies.txt
2
3{
4 "cookies": {
5 "country": "GB",
6 "debug": "2",
7 "language": "EN",
8 "source": "file"
9 }
10}
Note The cookie.txt
file needs to be in the following format for curl to read and parse the cookies
1httpbin.org FALSE / FALSE 0 country GB
2httpbin.org FALSE / FALSE 0 language EN
3httpbin.org FALSE / FALSE 0 source file
4httpbin.org FALSE / FALSE 0 debug 2
Reuse cookies
To save cookies received in a response, you can use the -c
option. Cookies can then be easily used in subsequent requests using the -b
option described above.
1$ curl https://httpbin.org/cookies/set/locale/en_GB -c cookies.txt
2
3<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
4<title>Redirecting...</title>
5<h1>Redirecting...</h1>
6<p>You should be redirected automatically to target URL: <a href="/cookies">/cookies</a>. If not click the link.
Let’s inspect the file, if cookie is saved. The contents of the file -
1# Netscape HTTP Cookie File
2# https://curl.haxx.se/docs/http-cookies.html
3# This file was generated by libcurl! Edit at your own risk.
4
5httpbin.org FALSE / FALSE 0 locale en_GB
Chaining the above steps, we can make a request like this. -L
causes curl to continue following the redirect.
1$ curl https://httpbin.org/cookies/set/locale/en_GB -c cookies.txt -b cookies.txt -L
2
3{
4 "cookies": {
5 "locale": "en_GB"
6 }
7}
POST data
The option to use in this case is -d
. When you use this option, Content-Type: application/x-www-form-urlencoded
request header is automatically set, so you don’t need to specify it explicitly. You can specify the data to be posted immediately after this flag. A sample request and response is added below. Check the response json’s form
field.
1$ curl "https://httpbin.org/post" -d "firstname=John&lastname=Doe"
2
3{
4 "args": {},
5 "data": "",
6 "files": {},
7 "form": {
8 "firstname": "John",
9 "lastname": "Doe"
10 },
11 "headers": {
12 "Accept": "*/*",
13 "Content-Length": "27",
14 "Content-Type": "application/x-www-form-urlencoded",
15 "Host": "httpbin.org",
16 "User-Agent": "curl",
17 "X-Amzn-Trace-Id": "Root=1-60ec27f5-4d461f2d3bbf20ed16291ed3"
18 },
19 "json": null,
20 "url": "https://httpbin.org/post"
21}
You could also hide the data you are submitting from the command line or history by reading it off a file like so -
1$ curl "https://httpbin.org/post" -d "@sensitive-data.txt"
POST multifield form
It’s quite straightforward to submit a multifield form using curl
. The option to use is -F
. You can add as many fields as required by adding multiple -F
flags. When you use this option, the Content-Type: multipart/form-data
request header is automatically set, so you don’t need to specify it explicitly.
Here is one such request and response -
1$ curl -F "firstname=John" -F "lastname=Doe" "https://httpbin.org/post"
2
3{
4 "args": {},
5 "data": "",
6 "files": {},
7 "form": {
8 "firstname": "John",
9 "lastname": "Doe"
10 },
11 "headers": {
12 "Accept": "*/*",
13 "Content-Length": "248",
14 "Content-Type": "multipart/form-data; boundary=------------------------e41227aceee312a6",
15 "Host": "httpbin.org",
16 "User-Agent": "curl",
17 "X-Amzn-Trace-Id": "Root=1-60ec23d7-3a82be0162af35456010c778"
18 },
19 "json": null,
20 "url": "https://httpbin.org/post"
21}
File upload
Similar to using the multifield form above, you can also upload a file using the -F
flag. The only thing to be aware of is the filepath should be prefixed with a @
char. Check the field files
in the response json.
1$ curl -F "firstname=John" -F "lastname=Doe" "https://httpbin.org/post" -F "file=@file.txt"
2
3{
4 "args": {},
5 "data": "",
6 "files": {
7 "file": "This is a test file\n"
8 },
9 "form": {
10 "firstname": "John",
11 "lastname": "Doe"
12 },
13 "headers": {
14 "Accept": "*/*",
15 "Content-Length": "408",
16 "Content-Type": "multipart/form-data; boundary=-----afd9220cdc8dae3d",
17 "Host": "httpbin.org",
18 "User-Agent": "curl",
19 "X-Amzn-Trace-Id": "Root=1-60ec24b5"
20 },
21 "json": null,
22 "url": "https://httpbin.org/post"
23}
Conclusion
While this list is just a start, I hope it helps you use curl more effectively. As promised, I will try to keep this updated, so that over time, it may eventually become a lot more exhaustive. 👍