HTTP Headers Parser

Turn raw HTTP request or response headers into a clean, readable name/value list.

HTTP Headers Parser: Check CORS, CSP, HSTS, ETag and Auth Headers

Paste headers copied from browser DevTools, `curl -v`, a proxy or a log, with or without the first request or status line. The parser returns JSON with three things: the start line, such as `GET /api/users HTTP/1.1` or `HTTP/2 200`; every header in its original order and spelling; and a lookup object with lowercase names, where headers that appear more than once, such as `Set-Cookie`, are collected into an array. Headers often contain cookies and tokens, so they are parsed in your browser and not sent anywhere.

How headers are structured

An HTTP/1.1 message is a start line, one Name: value header per line, then an empty line and the body. The parser splits each line at the first colon only, so Host: example.com:8080 keeps its port in the value, and it trims the spaces around each value. Names are case-insensitive under RFC 9110, which is why the lookup object uses lowercase keys while the list of entries keeps every name exactly as you pasted it: handy when you suspect a proxy of rewriting X-Request-ID as x-request-id.

GET /api/users HTTP/1.1
Host: example.com
Accept: application/json
Authorization: Bearer eyJhbGciOi...
X-Request-ID: req_123

When a header appears several times, RFC 9110 lets a recipient combine the values into one comma-separated list, with one important exception: Set-Cookie values must be kept separate, because cookie values can contain commas. The parser never merges; it collects repeated headers into an array so you can see each one.

CORS headers

Cross-origin requests from a browser succeed only if the server's response allows the page's origin. The headers to look for in a response:

Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Max-Age: 600
Vary: Origin

The most common CORS error comes from combining Access-Control-Allow-Origin: * with cookies or an Authorization header: for credentialed requests, the browser requires the exact origin and Access-Control-Allow-Credentials: true. Requests with custom headers or methods other than GET, HEAD and simple POST trigger a preflight OPTIONS request first, and that response needs the allow headers too. Vary: Origin stops caches from serving one origin's response to another.

Security headers

Strict-Transport-Security (HSTS), for example max-age=31536000; includeSubDomains, tells browsers to use HTTPS only for the given number of seconds, one year here. A browser that has seen the header will not fall back to plain HTTP until max-age runs out, so roll it out with a small value such as max-age=300 and raise it once every subdomain really serves HTTPS. Content-Security-Policy restricts where scripts, styles, images and frames may load from and is the strongest defence against cross-site scripting. X-Content-Type-Options: nosniff stops browsers guessing content types. Referrer-Policy controls how much of the current URL is sent in the Referer header, which keeps its historical misspelling from the 1990s. Framing is controlled by the frame-ancestors directive of CSP, or the older X-Frame-Options.

A CSP is much easier to read once it is on its own line: in default-src 'self'; script-src 'self' https://cdn.example.com the directives are separated by semicolons and the allowed sources by spaces. Paste a site's response headers to check which security headers are present at all. A missing CSP or HSTS header on a login page is worth fixing; a CSP containing unsafe-inline for scripts gives much weaker protection than it appears to.

Caching headers

Cache-Control decides whether and for how long browsers and CDNs may reuse a response: no-store never caches, no-cache caches but revalidates every time, max-age=3600 reuses for an hour, and public or private says whether shared caches may store it. ETag and Last-Modified let the browser revalidate cheaply: it sends If-None-Match or If-Modified-Since, and the server answers 304 Not Modified without a body if nothing changed. An ETag such as "33a64df5" is strong; one prefixed with W/ is weak and only promises equivalent content, not identical bytes. Do not be surprised if W/ appears only on compressed responses: nginx downgrades a strong ETag to a weak one when its gzip filter changes the body.

Conflicting caching headers are a frequent cause of "I deployed but users still see the old version". Look for a long max-age on HTML pages, or a CDN adding its own Age and caching headers on top of your application's.

Authorization and cookies

The Authorization header carries credentials: Bearer followed by a token, usually a JWT, or Basic followed by Base64 of username:password. Authorization: Basic dXNlcjpwYXNz is nothing more than user:pass encoded, which anyone can decode, so Basic authentication is only acceptable over HTTPS. A 401 Unauthorized response includes WWW-Authenticate, naming the scheme the server expects. Cookies travel in Cookie on requests and are set with Set-Cookie on responses; check each Set-Cookie for Secure, HttpOnly and SameSite attributes.

Large cookies are the usual cause of 431 Request Header Fields Too Large or 400 Bad Request errors from nginx and other servers, which limit the total header size. If a site breaks only for some users, compare the size of their Cookie header.

Getting headers to paste

curl -sI https://example.com                  # response headers only (HEAD request)
curl -sv https://example.com -o /dev/null     # request (>) and response (<) headers
# Browser: DevTools > Network > select a request > Headers > Raw

Lines from curl -v start with > or <; remove those markers before pasting. Before sharing parsed headers in a ticket or chat, delete Authorization, Cookie, Set-Cookie and any API-key headers: they are live credentials.

Frequently asked questions

How do I parse HTTP headers?

Paste the raw headers, optionally with the request or status line. The parser shows the start line, each header in order, and a lookup object with lowercase names where repeated headers become arrays.

Are HTTP header names case-sensitive?

No. Content-Type and content-type name the same header, which is why the parser keys its lookup object by lowercase names. Values are another matter: a Bearer token or an ETag must match byte for byte.

Why do I get a CORS error even though Access-Control-Allow-Origin is set?

With cookies or an Authorization header, * is not allowed: the server must return the exact origin plus Access-Control-Allow-Credentials: true. Preflight OPTIONS responses need the headers too.

What does HSTS do?

Strict-Transport-Security tells browsers to connect to the site over HTTPS only, for the number of seconds in max-age, preventing downgrade to plain HTTP.

What causes Request Header Fields Too Large?

The request headers exceed the server's limit, most often because of large or numerous cookies. Clearing the site's cookies or reducing their size fixes it.

Are my headers uploaded?

No. Parsing happens in your browser, so cookies and tokens in the headers are not sent anywhere.