· 5 min read
How to Read HTTP Response Headers Properly
Heshan Fernando
Co-founder & COO
Someone has pasted forty lines of raw response headers into a ticket with the note “does this look right to you?” Somewhere in there is the reason a page is being cached when it shouldn’t be, or serving the wrong content type, or getting blocked by a browser. But it’s forty lines of unsorted key-value pairs, half of them vendor-specific, and reading it top to bottom is not an efficient way to find the one that matters.
Headers are the metadata layer of every HTTP request, and they explain a surprising share of “the site is behaving strangely” problems.
What response headers actually do
Every HTTP response carries a status line and a set of headers before the body. The headers tell the browser how to treat what follows.
They fall into a handful of functional groups. Content headers — Content-Type, Content-Encoding, Content-Length — describe what the body is and how it’s encoded. Caching headers — Cache-Control, ETag, Last-Modified, Expires — control how long it can be reused and by whom. Security headers — Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options — restrict what the browser will allow the page to do. Routing and infrastructure headers tell you which CDN, load balancer, or cache tier handled the request.
Reading them in groups rather than in order is the single biggest improvement you can make to header debugging. Most problems live in exactly one group, and knowing which group narrows the search immediately.
Why people get stuck here
- Sheer volume. A response behind a CDN can carry thirty headers, most of which are irrelevant to your question.
- Vendor-specific noise. Infrastructure headers vary by provider and often aren’t documented anywhere you can reach.
- Caching is genuinely subtle.
Cache-Controldirectives interact, andno-cachedoesn’t mean what most people assume it means. - Case and formatting. Header names are case-insensitive, which is fine until you’re grepping for one.
- Confusing request and response headers. They’re different sets, and pasting one while debugging the other is a common time sink.
| Group | Key Headers | Debug Question |
|---|---|---|
| Content | Content-Type, Content-Encoding | Is the browser interpreting the body correctly? |
| Caching | Cache-Control, ETag | Why is this stale, or why isn’t it cached? |
| Security | CSP, HSTS, X-Frame-Options | Is a policy blocking something? |
| Infrastructure | CDN and proxy headers | Which layer served this response? |
What a good header audit looks like
Grouped, not alphabetical
Sorting by name puts Cache-Control next to Content-Type, which are unrelated. Grouping by function puts the headers that interact next to each other.
Directives broken out
Cache-Control: public, max-age=3600, stale-while-revalidate=86400 is three separate decisions in one line. An audit that splits them out makes the interaction visible.
Flags what’s missing
Absent security headers are often the finding. An audit that only shows present headers can’t tell you that X-Content-Type-Options was never set.
Runs locally
Headers can include session identifiers, internal hostnames, and infrastructure details you’d rather not paste into someone else’s server.
Common mistakes to avoid
- Assuming
no-cachemeans don’t cache. It means revalidate before reuse.no-storeis the one that means don’t store it. - Setting both
ExpiresandCache-Control.Cache-Controlwins in modern browsers; keeping both around just confuses whoever reads it next. - Reading headers from a cached response. Force a fresh request, or you’re auditing what your browser remembered.
- Ignoring the status code. A 304 carries a very different header set from a 200, and the difference is usually the point.
- Pasting production headers into a public forum. Strip session tokens and internal hostnames first.
How to do it with HTTP Headers Parser
Online Tool Store’s HTTP Headers Parser turns raw response headers into a readable audit in your browser — nothing is uploaded, so production headers stay local.
- Capture the raw headers from your browser’s network panel or a command-line request, making sure it’s a fresh, uncached response.
- Paste the block into the parser exactly as captured, including the status line.
- Read the group relevant to your problem first rather than working top to bottom.
- For caching issues, look at every
Cache-Controldirective together — they interact and the combination matters. - Note which expected security headers are absent, not just which are present.
- Compare against the headers from a page that behaves correctly; the diff is usually the answer.
The Security Headers Explainer, the HTTP Status Code Reference, and the Redirect Chain Explainer cover the neighbouring questions.
Frequently asked questions
What’s the difference between no-cache and no-store?
no-cache allows the response to be stored but requires revalidation with the server before it’s reused. no-store forbids storing it at all. If you’re trying to keep sensitive content out of caches, no-store is the one you want.
Why do I see so many headers I don’t recognise?
Responses served through a CDN, load balancer, or application platform usually pick up provider-specific headers at each hop. They’re mostly diagnostic and safe to ignore unless you’re debugging that specific layer.
Are my headers sent anywhere when I use the parser?
No. It runs entirely in your browser, so headers containing session tokens or internal hostnames are parsed on your own machine.
Final thought
Group the headers by function and read only the group your problem lives in. Most header debugging is a five-line problem hiding in a forty-line paste.