HTTP headers
Content negotiation, auth, compression and security headers — the metadata that controls real behaviour.
Important request headers
| Header | Purpose |
|---|---|
Host | Virtual host routing — mandatory in HTTP/1.1 |
Accept | Response formats the client can handle |
Content-Type | Media type of the body being sent |
Authorization | Credentials (Bearer token, Basic) |
If-None-Match | Conditional request using an ETag |
User-Agent | Client identification |
Referer | Previous page (spelled wrong in the original spec, forever) |
Important response headers
| Header | Purpose |
|---|---|
Content-Type | What the body is — including charset |
Content-Length/Transfer-Encoding | Body size or chunking |
Cache-Control | Freshness rules |
ETag | Version fingerprint for conditional requests |
Set-Cookie | Store a cookie (may appear several times) |
Location | Target for 3xx and 201 responses |
Vary | Which request headers affect the response |
💡
Vary is easy to forget and expensive to get wrong: any cache key difference must be declared there, or one user's content can be served to another.Security headers worth setting
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), camera=()
X-Frame-Options: DENY (or CSP frame-ancestors)⚠️
HSTS is cached by browsers for its whole
max-age. Start with a short value (5 minutes) and increase it once you are certain HTTPS works everywhere — otherwise you can lock yourself out.FAQ
Why is my JSON being downloaded instead of parsed?
Missing or wrong
Content-Type. It must be application/json; charset=utf-8.Header names case-sensitive?
No — HTTP/1.1 names are case-insensitive; HTTP/2 requires lowercase on the wire. Libraries normalize this for you.
Related
Caching and conditional requests HTTP status codes
Last refreshed 2026-09-17.