HTTP headers

Content negotiation, auth, compression and security headers — the metadata that controls real behaviour.

Important request headers

HeaderPurpose
HostVirtual host routing — mandatory in HTTP/1.1
AcceptResponse formats the client can handle
Content-TypeMedia type of the body being sent
AuthorizationCredentials (Bearer token, Basic)
If-None-MatchConditional request using an ETag
User-AgentClient identification
RefererPrevious page (spelled wrong in the original spec, forever)

Important response headers

HeaderPurpose
Content-TypeWhat the body is — including charset
Content-Length/Transfer-EncodingBody size or chunking
Cache-ControlFreshness rules
ETagVersion fingerprint for conditional requests
Set-CookieStore a cookie (may appear several times)
LocationTarget for 3xx and 201 responses
VaryWhich 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.

Caching and conditional requests HTTP status codes

Last refreshed 2026-09-17.