Curl Cheatsheet

Some helpful curl commands

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/nulldiscard 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 and redirect_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. 👍

References (2)

  1. Manpage 
  2. Ec.haxx.se 

Related