HTTP Header Reference
Searchable reference of the HTTP request and response headers that matter for security, caching and proxying, with recommended values.
Result
Headers
| Header | Direction | Example value | Notes |
|---|---|---|---|
| Strict-Transport-Security | Response | max-age=31536000; includeSubDomains | Forces HTTPS for the specified period. Test includeSubDomains carefully - it applies to every subdomain. |
| Content-Security-Policy | Response | default-src 'self' | The strongest defence against XSS. Start in Report-Only mode. |
| X-Content-Type-Options | Response | nosniff | Stops the browser guessing content types. Always set it. |
| X-Frame-Options | Response | SAMEORIGIN | Legacy clickjacking protection; superseded by CSP frame-ancestors. |
| Referrer-Policy | Response | strict-origin-when-cross-origin | Limits URL leakage to third parties. |
| Permissions-Policy | Response | geolocation=(), camera=() | Disables browser features the site does not use. |
| Cache-Control | Both | public, max-age=31536000, immutable | The primary caching control. immutable suits fingerprinted assets. |
| ETag | Response | W/"abc123" | Validator for conditional requests; pairs with If-None-Match. |
| Vary | Response | Accept-Encoding | Tells caches which request headers change the response. Omitting it causes wrong cache hits. |
| Content-Encoding | Response | br, gzip | Compression applied to the body. |
| Transfer-Encoding | Response | chunked | Streaming without a known length. Mismatches with Content-Length enable request smuggling. |
| Content-Length | Both | 1234 | Body size in bytes. |
| Host | Request | example.com | Required in HTTP/1.1; selects the virtual host. |
| Authorization | Request | Bearer eyJ... | Credentials. Only ever over TLS. |
| Cookie | Request | session=abc | Client state. Watch total header size limits. |
| Set-Cookie | Response | id=x; Secure; HttpOnly; SameSite=Lax | Always set Secure and HttpOnly; SameSite mitigates CSRF. |
| X-Forwarded-For | Request | 203.0.113.9, 10.0.0.1 | Client chain through proxies. Trust only the hops you control. |
| X-Forwarded-Proto | Request | https | Original scheme behind a terminating proxy - required for correct redirects. |
| X-Real-IP | Request | 203.0.113.9 | nginx convention for the immediate client address. |
| Forwarded | Request | for=203.0.113.9; proto=https | The standardised (RFC 7239) replacement for the X-Forwarded-* family. |
| Access-Control-Allow-Origin | Response | https://app.example.com | CORS. Never combine a wildcard with credentials. |
| Retry-After | Response | 120 | Accompanies 429 and 503 to tell clients when to retry. |
| Alt-Svc | Response | h3=":443"; ma=86400 | Advertises HTTP/3 availability. |
| Upgrade-Insecure-Requests | Request | 1 | Client prefers HTTPS variants of subresources. |
| Server | Response | nginx | Software identification - minimise or remove it. |
| Expect-CT | Response | max-age=0 | Deprecated; Certificate Transparency is now enforced by browsers directly. |
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Content-Security-Policy "default-src 'self'" always;About HTTP Header Reference
Headers carry most of HTTP's behaviour: caching, security policy, content negotiation and the proxy chain. This is the working set, with the values worth defaulting to and the traps that follow from getting them wrong.
Trusting the forwarded chain
X-Forwarded-For is a list, appended to by each proxy, and a client can pre-populate it with anything it likes. The only trustworthy entries are those added by proxies you control, counting backwards from your own edge. Configure your application with the number of trusted hops (nginx set_real_ip_from, Express trust proxy) rather than reading the leftmost value, which is attacker-controlled. Getting this wrong turns rate limiting and IP allow-lists into decoration.
The Vary header, and why caches misbehave
If a response differs based on a request header - Accept-Encoding, Accept-Language, Authorization - the cache must be told with Vary. Omit it and a shared cache will happily serve a gzipped response to a client that cannot decompress, or one user's personalised page to another. It is the single most common cause of "the CDN is serving the wrong content".
Common use cases
- Building a baseline security header set for a new site.
- Diagnosing a caching problem at a CDN or reverse proxy.
- Working out which forwarded header your proxy chain actually sets.
Edge cases and gotchas
- Access-Control-Allow-Origin: * cannot be combined with credentials - browsers reject the combination.
- Trust X-Forwarded-For only from proxies you control; clients can forge it.