UUID Studio

HTTP Header Parser

Structure raw HTTP headers as JSON.

  • 🔒 No data stored or uploaded
  • âš¡ 100% client-side
  • 🆓 Free, no account

Need more than one tool at a time? Open the full Workbench - or press Ctrl+K to jump to any tool.

Create or edit JSON here (syntax colors), then format, validate, or convert - same as MongoDB $binary UUID blobs on the Convert tab once detected.

New document

About HTTP Header Parser

This parses a raw HTTP header block into individual fields, which is what you want when you are reading something captured from curl -v, a proxy log, or a browser's network tab and need to see the fields clearly.

A few structural rules are worth having in mind. Header names are case-insensitive, so Content-Type and content-type are the same field - and HTTP/2 and HTTP/3 require them to be lowercase on the wire, which is why the same request looks different depending on the protocol version. Some fields may appear more than once and are equivalent to a single comma-separated value; Set-Cookie is the notable exception, which must never be folded because its value legitimately contains commas.

The headers that most often need reading carefully are the caching ones. Cache-Control directives interact in ways that are easy to get wrong - no-cache means revalidate rather than do not store, no-store is the one that actually prevents caching, and private means only the browser may cache while public permits shared caches. A response with no explicit caching headers is not necessarily uncached: heuristic caching can still apply.

The other cluster is CORS, where the rules are stricter than they appear. Access-Control-Allow-Origin cannot be * when credentials are involved - it must name the exact origin - and Access-Control-Allow-Credentials must be present too. A wildcard with credentials is rejected by the browser with an error that does not always make the cause obvious.

Parsing runs in your browser and nothing is transmitted, so headers containing a real Authorization value or session cookie stay local.

How to use the HTTP Header Parser

  1. Paste the raw header block - request or response, with or without the status line.
  2. Read the parsed fields, and note any that appear more than once.
  3. For a caching question, look at Cache-Control, ETag, Last-Modified and Vary together; they only make sense as a set.
  4. For a CORS failure, check Allow-Origin against the exact origin and whether credentials are in play.

HTTP Header Parser in code

The same operation this tool performs, in the languages you are most likely to need it.

Capturing headers with curl
# Response headers only
curl -sI https://example.com

# Request and response headers, with the TLS handshake
curl -sv https://example.com -o /dev/null

# Follow redirects and show every hop's headers
curl -sIL https://example.com

# Just the ones you care about
curl -sI https://example.com | grep -iE 'cache-control|etag|vary|content-type'

# Headers as JSON, for scripting
curl -s -o /dev/null -w '%{json}' https://example.com | jq .
Reading headers in JavaScript
const res = await fetch(url);

// Header names are case-insensitive in the Headers API
res.headers.get("content-type");
res.headers.get("Content-Type");     // same thing

// Repeated headers come back comma-joined, EXCEPT Set-Cookie
res.headers.getSetCookie?.();        // array - the special case

for (const [k, v] of res.headers) console.log(k, v);

// In the browser, only a few response headers are readable
// cross-origin unless the server sends:
//   Access-Control-Expose-Headers: X-Total-Count, ETag
// Otherwise res.headers.get("X-Total-Count") is null even though
// the header was sent - a common and confusing symptom.
Caching and CORS quick reference
# Caching
Cache-Control: no-store                 # never cache, anywhere
Cache-Control: no-cache                 # cache but always revalidate
Cache-Control: private, max-age=600     # browser only, 10 minutes
Cache-Control: public, max-age=31536000, immutable   # fingerprinted asset
Vary: Accept-Encoding, Authorization    # what the cache key depends on

# CORS - with credentials, the origin must be explicit
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: ETag, X-Total-Count
# Access-Control-Allow-Origin: *  is REJECTED when credentials are used

# Security
Strict-Transport-Security: max-age=63072000; includeSubDomains
Content-Security-Policy: default-src 'self'
X-Content-Type-Options: nosniff

When you need this

  • Reading a captured header block to see exactly what a server sent.
  • Working out why a response is or is not being cached.
  • Diagnosing a CORS failure from the actual headers rather than the browser message.
  • Checking whether security headers are present and correctly formed.
  • Confirming which content encoding and type a response declared.

Common problems and what causes them

Treating header names as case-sensitive
They are case-insensitive, and HTTP/2 and HTTP/3 require lowercase on the wire. Code that looks for an exact 'Content-Type' can miss 'content-type' from an HTTP/2 response. Normalise before comparing.
Folding Set-Cookie like other repeated headers
Most repeated headers are equivalent to one comma-separated value, but cookie attributes such as Expires contain commas. Joining Set-Cookie headers corrupts them - handle it as a list.
no-cache misread as do-not-store
no-cache means the response may be stored but must be revalidated before reuse. no-store is the directive that actually prevents storage. Using the wrong one is a common cause of unexpectedly cached private data.
Missing Vary on a content-negotiated response
If a response differs by Accept-Encoding, Accept-Language or Authorization and Vary does not say so, a shared cache can serve one user's variant to another. This is a real data-leak mechanism, not just a caching inefficiency.
Wildcard CORS origin with credentials
Access-Control-Allow-Origin: * is rejected by browsers when the request carries credentials. Echo the specific origin (validated against an allowlist) and send Access-Control-Allow-Credentials: true.
Custom response headers invisible to JavaScript
Cross-origin, only a handful of response headers are readable unless the server lists the others in Access-Control-Expose-Headers. The header is sent but reads as null, which looks like the server omitted it.

FAQ

Are HTTP header names case-sensitive?
No. Content-Type and content-type are the same field. HTTP/2 and HTTP/3 additionally require lowercase on the wire, so the same request can look different across protocol versions - normalise before comparing in code.
What is the difference between no-cache and no-store?
no-cache permits storage but requires revalidation before every reuse. no-store forbids storing the response at all. If you are protecting sensitive data, no-store is the one you want.
Why can't my JavaScript read a response header?
Cross-origin requests expose only a small set of response headers by default. The server must list any others in Access-Control-Expose-Headers, otherwise the header is sent but reads as null.
Why does my CORS request fail with a wildcard origin?
Because Access-Control-Allow-Origin: * is not permitted when the request includes credentials. Return the specific requesting origin, validated against an allowlist, together with Access-Control-Allow-Credentials: true.
What does the Vary header do?
It tells caches which request headers the response depends on, so they form the correct cache key. Omitting it on a content-negotiated response lets a cache serve the wrong variant - including one user's authorised response to another.

Related reading