Skip to main content

How to Read HTTP Headers: A Practical Field Guide to Request and Response Lines

Learn to read HTTP request and response headers by hand. What Content-Type, Cache-Control, Authorization, Set-Cookie, and CORS lines mean, plus how to debug an API from its headers.

Published By Li Lei
#http #headers #api #debugging #web

How to Read HTTP Headers: A Practical Field Guide to Request and Response Lines

Every HTTP request and response carries a block of metadata above the body, and most of the time you never look at it. Then an API returns a 401 with no explanation, a download opens as garbled text in the browser, or a cross-origin call gets blocked, and suddenly those header lines are the only place the answer lives. Once you can read them, a lot of "it just doesn't work" problems turn into a single wrong line you can point at.

This is a guide to reading that metadata by hand: what the common headers mean, how request headers differ from response headers, and how to debug a service from its headers alone.

Headers are just key: value lines

A header block is plain text. After the first line, every line is one header written as a name, a colon, and a value:

Content-Type: application/json
Cache-Control: no-store
Set-Cookie: session=abc123; HttpOnly; Secure

That first line is the exception. On a request it is the request line, like GET /users/42 HTTP/1.1, naming the method, the path, and the protocol version. On a response it is the status line, like HTTP/1.1 200 OK, giving the version and the result code. Everything after it follows the same Name: value shape.

Two details trip people up. First, you split on the first colon only. A Location: https://host:8443/x value contains colons of its own, and a Date has them in the time, so chopping on every colon mangles the value. Second, a name can legitimately repeat. Set-Cookie is the headline case: a server sends one line per cookie, and those lines must stay separate rather than being folded into a comma list the way most headers can be.

Request headers vs response headers

The same block format serves two directions, and the headers you expect differ.

Request headers describe what the client wants and who it is. Host names the target site. Accept says which formats the client can handle (Accept: application/json). Authorization carries credentials, usually a bearer token. Cookie sends back whatever the server stored earlier. User-Agent identifies the client. Origin appears on cross-origin calls and is what CORS checks against.

Response headers describe the body the server is sending back and how to treat it. Content-Type declares the format. Content-Length gives the size. Cache-Control sets caching rules. Set-Cookie stores state on the client. Strict-Transport-Security, Content-Security-Policy, and the CORS Access-Control-* family harden the response.

A few headers, like Content-Type, show up on both sides and simply mean "the format of the body in this message" in each direction. Knowing which way a block flows tells you which headers should be there and which are missing.

The five headers worth memorizing

These carry most of the weight in day-to-day debugging.

  • Content-Type tells the receiver the format of the body. text/html; charset=utf-8 is a web page; application/json is an API payload. The charset part says which encoding to decode the bytes with. If a JSON API forgets to send application/json, some clients mis-parse the body; serve a download as text/plain and the browser shows it inline instead of saving it.
  • Cache-Control sets caching with a comma-separated list of directives. max-age=3600 lets a cache keep the response an hour, no-store forbids caching, private keeps it out of a shared CDN, and must-revalidate forces a freshness check on expiry. Static assets often use public, max-age=31536000, immutable.
  • Authorization carries credentials on the request, most often Authorization: Bearer <token>. A missing or stale value here is the usual cause of a 401.
  • Set-Cookie stores state on the client. Each cookie is its own line with flags like HttpOnly (no JavaScript access), Secure (HTTPS only), and SameSite (cross-site policy). Read those flags carefully, because they decide whether the cookie is safe.
  • The CORS family governs cross-origin access. Access-Control-Allow-Origin names which origins may read the response, -Allow-Methods lists the permitted verbs, and -Allow-Headers lists the custom headers a request may send. A wildcard * will not work alongside credentials.

A worked example

Here is a small response block. Read it line by line and the story is plain:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Cache-Control: private, max-age=0, no-cache
Set-Cookie: sid=9f2a; HttpOnly; Secure; SameSite=Lax
Access-Control-Allow-Origin: https://app.example.com
X-Content-Type-Options: nosniff

Line one is the status line: the request succeeded with 200 OK. The body is JSON in UTF-8, so a client should parse it as JSON, not text. Cache-Control: private, max-age=0, no-cache means a CDN must not cache this and the browser must revalidate before reusing it, which is correct for a per-user response. The Set-Cookie sets a session id that JavaScript cannot read (HttpOnly), that travels only over HTTPS (Secure), and that is restricted on cross-site navigation (SameSite=Lax). The CORS line allows exactly one origin to read the response, and X-Content-Type-Options: nosniff stops the browser from second-guessing the declared type. Six lines, and you now know the format, the caching policy, the session handling, and the cross-origin rules.

Debugging an API by its headers

I keep curl -i in my muscle memory because it dumps the status line and every response header above the body, and most failures are visible right there. When an endpoint returns 401, I run it, paste the block, and check three things: did the server send WWW-Authenticate, is Content-Type actually application/json rather than an HTML error page, and did anything reset the session cookie. Nine times out of ten the wrong line is staring back at me, and I have stopped guessing about the request body entirely.

For a security pass, curl -I against a staging URL shows whether Strict-Transport-Security, Content-Security-Policy, X-Frame-Options, and X-Content-Type-Options are present. A blank where one of those should be is your pre-launch checklist. For a blocked cross-origin call, paste the OPTIONS preflight response and read the Access-Control-Allow-Origin, -Methods, and -Headers rows side by side; the mismatch is almost always obvious once they sit next to each other.

Reading a wrapped terminal dump by eye is where this gets slow, especially when a long value folds across lines. Pasting the block into the HTTP Header Parser lays each header on its own row, splits on the first colon only, keeps repeated Set-Cookie lines intact, and badges the security-relevant ones, so the missing or wrong header jumps out. When the body itself is the puzzle, run the JSON through the JSON Formatter to pretty-print and validate it. Both run entirely in the browser, so a token in an Authorization line never leaves your tab.

Wrapping up

HTTP headers are not a mystery format. They are key: value lines above a body, with one start line on top that says either what was requested or how it turned out. Learn what Content-Type, Cache-Control, Authorization, Set-Cookie, and the CORS headers each control, learn to tell a request block from a response block, and most API problems shrink to a single line you can read and fix.


Made by Toolora · Updated 2026-06-13