Controlling the HTTP conversation with more precision: sending and overriding request headers, reading and saving response headers, following redirects safely, and managing cookies between requests.

After running your first HTTP requests and being able to read verbose output in episode 3, it's time to take full control of the HTTP conversation. In this episode we'll learn to send headers of our own choosing, read and save response headers, handle redirects, and manage cookies.
If episode 3 was "learning to listen", episode 4 is "learning to make requests with precision". Servers read your identity and intent from headers — by controlling them, you can impersonate a browser, request JSON format, send auth tokens, and keep sessions alive across redirects. This is a skill you'll use every day when testing APIs.
-HRequest headers are usually set by curl by default, but there's almost always a time when you need to add your own — for example requesting JSON format, or sending an API token. The -H option (or --header) makes this possible:
curl -H "Accept: application/json" https://api.example.com/dataThe format is always "Header-Name: Value". To send multiple headers at once, just repeat the -H option — one -H per header:
curl -H "Accept: application/json" \
-H "X-Api-Key: rahasia123" \
-H "User-Agent: belajar-curl/1.0" https://api.example.com/dataTwo important things about -H:
User-Agent is overridden from curl/8.21.0 to belajar-curl/1.0.-H "Header-Name:" (empty value). This is a trick often used to get rid of unwanted built-in headers.Tip
To see which headers actually arrive at the server, use an echo endpoint like httpbin.org/headers. That server returns JSON containing all the headers it received — the fastest way to confirm your headers were really sent as intended. Example: curl -H "Accept: application/json"{:bash} https://httpbin.org/headers.
-i, -D, and -IWe already know -I (HEAD) from episode 3. Now three other ways to see response headers:
| Option | Behavior |
|---|---|
-i (--include) | Shows response headers followed by the body in the same output |
-D file (--dump-header) | Saves response headers to a separate file |
-D - | Saves headers to stdout (separated from the body) |
-I (--head) | Sends a HEAD method — headers only, no body |
Example of -i — headers and body shown together:
curl -i https://example.comAnd -D — headers written to a file while the body still goes to stdout:
curl -D headers.txt https://example.comThe key difference: -i mixes headers with the body in one stream, while -D separates them — the body can still flow to another process without contamination. For API testing, the combination of -D - and piping the body to jq is a very common pattern.
-L and --max-redirsOften the page you request isn't actually at that URL — the server sends a 3xx response along with a Location header pointing to the new address. This is like someone moving house and leaving their forwarding address.
Now, the part that often surprises beginners: by default, curl does NOT follow redirects. It just shows the 3xx response and stops. Try it yourself:
curl -i http://example.comYou'll see the line HTTP/1.1 301 Moved Permanently and the header Location: https://example.com/, then curl stops — the final page is never fetched. To make curl chase redirects, use -L (--location):
curl -L http://example.comNow curl automatically sends a new request to the URL in the Location header, and does so repeatedly if there's a chain of redirects. To limit the number of hops — protecting yourself from a redirect loop — use --max-redirs:
curl -L --max-redirs 5 https://api.example.comWarning
When following redirects, curl can change the POST method to GET for 301, 302, and 303 responses — per standard HTTP behavior. If your API relies on a specific method during redirects, pay attention to the --post301, --post302, and --post303 options that force the method to be preserved.
-b and -cHTTP is fundamentally stateless — each request stands alone. Cookies are the remembering mechanism: the server sends a cookie in the response, and the client sends it back on subsequent requests. Without cookies, the "login" feature wouldn't work.
Curl doesn't store cookies automatically. Two options manage it:
-c file (--cookie-jar) — saves received cookies to a file.-b file (--cookie) — sends cookies from a file along with the request.The flow is like logging in then continuing to work:
curl -c cookies.txt -d "user=armand&pass=1234" https://app.example.com/logincurl -b cookies.txt https://app.example.com/dashboardThe -c then -b pattern with the same file is the most common idiom for keeping a session across requests. You can also write cookies directly as a string, for example -b "session=abc123" — useful when the cookie value is already known.
Note
The names -b and -c are often confused because they're short and consecutive in the alphabet. A trick to remember: -c to save Cookies (saving to a file) and -b to Bring cookies back (sending from a file). Curl -c collects, curl -b brings.
Forgetting -L when facing a redirect. The page seems "unreachable" when it's only a 3xx. Always check with -i whether the incoming response is 3xx + Location.
Writing the header format incorrectly. The format is always "Name: Value" with a colon and a space — not "Name = Value". The server will reject or ignore wrongly formatted headers.
Thinking -i and -I are the same. -i displays headers followed by the body (still GET), -I sends a HEAD method (no body). The context differs.
Forgetting --max-redirs. Uncontrolled redirect chains can end in an infinite loop. Always set a limit when writing scripts.
In this episode 4, you've taken control of the HTTP conversation: sending and overriding request headers with -H, reading and saving response headers with -i and -D, following redirects with -L and --max-redirs, and managing cookies with -b and -c.
Key takeaways:
-H "Name: Value" adds or overrides a header; -H "Name:" removes it.-i combines headers + body; -D separates them to a file; -I is HEAD only.-L; limit hops with --max-redirs.-c saves, -b sends.In the next episode 5, we'll move into the methods that change data on the server: POST, PUT, DELETE & Form Data — sending payloads with -d and --data-urlencode, choosing the method with -X, and uploading files with multipart -F. See you in episode 5!