| Host | req | Which virtual host the client wants. Mandatory in HTTP/1.1; how one IP serves many sites. |
| Authorization | req | Credentials: Basic base64(user:pass), or Bearer . Never log this header. |
| User-Agent | req | Client self-identification. Parse for analytics, never for access control. |
| Accept / Accept-Encoding | req | Content negotiation: formats and compressions the client understands (gzip, br, zstd). |
| Cookie / Set-Cookie | both | Session state. Set-Cookie flags matter: Secure, HttpOnly, SameSite defend against theft and CSRF. |
| X-Forwarded-For | req | Client IP chain appended by each proxy. Trivially spoofable by the client, trust only the entry your own proxy appended. |
| X-Forwarded-Proto / X-Real-IP | req | Original scheme and client IP as seen by your edge proxy. Apps behind TLS-terminating proxies need these to build correct URLs. |
| Forwarded | req | RFC 7239 standardised replacement for the X-Forwarded-* family. Adoption still partial. |
| Cache-Control | both | The caching contract: no-store, no-cache, max-age, s-maxage, private/public, immutable. The most misunderstood header in HTTP. |
| ETag / If-None-Match | both | Validator pair enabling 304 Not Modified. Beware: default nginx/Apache ETags differ per server, breaking caching behind load balancers. |
| Last-Modified / If-Modified-Since | both | Timestamp-based validation; weaker than ETags (1-second resolution). |
| Expires | res | Legacy absolute expiry; Cache-Control max-age wins when both present. |
| Vary | res | Which request headers the cached response depends on (e.g. Accept-Encoding). Wrong Vary = users served each other's content. |
| Location | res | Target of a 3xx redirect (or URL of a 201-created resource). |
| Content-Type | res | MIME type + charset. Wrong type breaks browsers subtly; X-Content-Type-Options: nosniff makes them believe you. |
| Content-Length / Transfer-Encoding | both | Body size, or chunked streaming. Conflicts between the two are the root of request-smuggling attacks. |
| Content-Disposition | res | attachment; filename=… forces download instead of inline rendering. |
| Strict-Transport-Security | res | HSTS: browsers refuse plain HTTP for max-age seconds. Test with a short age before setting a year; includeSubDomains is a commitment. |
| Content-Security-Policy | res | Whitelist of script/style/img sources, the strongest XSS mitigation. Deploy with Content-Security-Policy-Report-Only first. |
| X-Frame-Options | res | DENY / SAMEORIGIN against clickjacking. Superseded by CSP frame-ancestors but still worth sending. |
| X-Content-Type-Options | res | nosniff, disables MIME guessing. No reason not to send it everywhere. |
| Referrer-Policy | res | How much of the current URL leaks in the Referer header of outbound requests. strict-origin-when-cross-origin is the sane default. |
| Access-Control-Allow-Origin | res | CORS: which origins may read this response from JavaScript. * is fine for public data, forbidden with credentials. |
| Access-Control-Allow-Methods / -Headers | res | CORS preflight answers: permitted methods and custom headers for the OPTIONS check. |
| Retry-After | res | Seconds (or date) to wait, sent with 429 and 503. Well-behaved clients honour it; your rate limiter should send it. |
| WWW-Authenticate | res | Sent with 401 to describe the expected auth scheme (Basic realm=…, Bearer). |
| Server | res | Software self-identification. Common hardening step: suppress the version (server_tokens off). |
| Connection / Keep-Alive | both | Hop-by-hop connection management (HTTP/1.1). Must not be forwarded by proxies. |
| Upgrade | req | Protocol switch request, how WebSocket handshakes begin (Upgrade: websocket). |
| Range / Content-Range | both | Partial content: resumed downloads and video seeking (206 responses). |