HTTP Headers Reference

HTTP headers are key-value metadata carried in requests and responses. This table lists the most common request and response headers with kind and notes for quick lookup while debugging APIs.

How It Works

HTTP headers are key-value pairs in requests and responses that carry auth, caching, content negotiation and security metadata, independent of the body. Request headers (User-Agent, Authorization, Accept) say what the caller wants; response headers (Content-Type, Set-Cookie, Cache-Control) describe what the server returned.

Security headers matter most: CSP limits loadable resources to blunt XSS, HSTS forces HTTPS, CORS headers govern cross-origin access. Tuning headers hardens the app without touching business code.

When to Use This Table

This table is for looking up the precise meaning of an HTTP header. It covers content negotiation, cache control, language negotiation, authentication, CORS and security headers with their kind and meaning. It is the reference when debugging an API or reading framework documentation.

When not to consult it: you are tuning CDN and reverse proxy behaviour. Headers may be rewritten, reordered or stripped along the transport path, and Nginx and CDNs often disagree with the standard, so those problems require inspecting real responses rather than a header list.

Rule of thumb: first establish whether the header is a request or a response header — the same name means different things on each side (Content-Type describes the body in both, while Accept only appears in requests). Getting the direction right prevents a whole class of confusion.

Mind how CORS headers interlock: Access-Control-Allow-Origin only appears in responses, and a preflight must satisfy stricter conditions than the actual request. Many cases of CORS POST failing while GET works come down to a failed preflight.

Boundaries and Common Pitfalls

  • A failed CORS preflight is the usual cause of cross-origin POST failing while GET works

    A cross-origin request with custom headers, a non-simple method or a non-simple Content-Type triggers an OPTIONS preflight first. The server must return Access-Control-Allow-Methods, Access-Control-Allow-Headers and Access-Control-Allow-Origin; if any is missing the browser refuses, and the only symptom is in the browser console while server logs look clean. Debug by sending OPTIONS manually with curl to inspect the response headers, then confirm Allow-Headers covers every custom header actually used.

  • A wrong Cache-Control causes updates not to show, or leaks private data

    It fails in both directions: static assets without max-age or a version token keep users on stale builds and cost hours of debugging; and a response carrying user data wrongly marked public, max-age=3600 lets a CDN share one copy across users — serving one user content to another. The latter is a security incident, not a UX annoyance. The rules: content-hashed filenames with immutable long caching, HTML with no-cache to force revalidation, and private or no-store for anything user-specific.

  • Accept-Encoding pitfalls come from inconsistent server implementations

    The flow is that the client declares support via Accept-Encoding (gzip, br) and the server picks one and echoes it in Content-Encoding. Three problems recur: the server compresses unconditionally and ignores Accept-Encoding, handing compressed data to clients that cannot read it; both gzip and br are declared and returned, leaving the client unable to choose; and already-compressed images or video get recompressed, burning CPU for no size win. The correct approach negotiates and sets Vary: Accept-Encoding, otherwise a cache will serve the compressed variant to clients that cannot decode it.

How This Relates to Neighbours

For status code semantics such as the difference between 502 and 504, use the in-site HTTP status codes page; this one is about header fields.

For method semantics such as idempotency and body rules, use the in-site HTTP methods page, which complements but differs in focus.

Header compression and connection reuse differences across HTTP/2 and HTTP/3 are protocol implementation details, out of scope here.

If the goal is debugging odd browser behaviour, read the actual response headers in the Network panel rather than inferring from a list — proxies may rewrite them.

Practical Snippet

Key points: (1) most cross-origin POST failures trace to a failed preflight — the first debugging action is a manual OPTIONS request checking all three Allow headers, and confirming Allow-Headers covers every custom header in use; (2) static assets want content-hashed filenames with immutable caching while HTML should use no-cache for revalidation rather than no-store; (3) any user-specific response must be private or no-store — marking it public is a security incident; (4) compression must be negotiated via Accept-Encoding with a Vary header, or a cache will serve the compressed variant to clients that cannot decode it.

# ① 手动发预检,验证 CORS(最实用的调试动作)
curl -i -X OPTIONS 'https://api.example.com/orders'   -H 'Origin: https://app.example.com'   -H 'Access-Control-Request-Method: POST'   -H 'Access-Control-Request-Headers: content-type,x-request-id'
# 必须同时看到:Access-Control-Allow-Origin / -Methods / -Headers
# 缺任一项 ⇒ 浏览器直接拒绝,且服务端日志看不到异常

# ② 查看实际响应头
curl -sSI https://example.com/ | grep -iE 'cache-control|vary|etag|content-encoding'
# Age: 120  ⇒ 命中了缓存(解释「改了却没生效」)

# ③ 压缩协商:客户端声明,服务端选一种
curl -sSI -H 'Accept-Encoding: gzip, br' https://example.com/a.json   | grep -i 'content-encoding'          # 回 gzip 或 br,**不能两个都返回**
# ⚠️ 服务端必须带 Vary: Accept-Encoding,否则缓存串味

# ④ 内容哈希 + immutable(静态资源)
# app.9f2c1a.js  +  Cache-Control: public, max-age=31536000, immutable

# 5 HTML 用 no-cache 强制校验(而不是 no-store 浪费带宽)
curl -sSI https://example.com/ | grep -i cache-control
# Cache-Control: no-cache          ← 每次带 If-None-Match 校验
curl -sS -H 'If-None-Match: "abc"' https://example.com/ -o /dev/null -w '%{http_code}
'
# 304 = 未变化(省带宽)  200 = 变了

# 6 含用户数据的响应必须 private(绝不能 public)
curl -sSI https://example.com/api/me | grep -i cache-control
# Cache-Control: private, no-store   ← 绝不能让 CDN 共享

Practical Notes

  • Set-Cookie may repeat but must never be folded into one lineIt is one of the few headers that is repeatable yet not combinable: sending several cookies in a single comma-separated line makes the browser treat it as one malformed cookie. Emit one Set-Cookie header per cookie.
  • Content-Length together with Transfer-Encoding is a protocol errorHaving both makes message framing ambiguous, which is the basis of request smuggling. If you stream with chunked encoding, omit Content-Length; gateways typically answer such requests with 400.
  • A missing Vary entry is the usual cause of "cache serving the wrong content"If a response varies with Accept-Language or Origin but Vary does not say so, CDNs and browsers may hand a Chinese response to an English reader. Always list the varying request headers when returning localized or negotiated content.

Data Sources

  • RFC 9110 (semantics)
  • RFC 9111 (caching)
  • RFC 6265 (cookies)
  • IANA Message Headers Registry

Codes, names and definitions above come from public specifications; we claim no originality over the specification data itself. The arrangement, Chinese annotations and practical notes on this page are written by us.

HeaderKindMeaning
AcceptRequestMedia types the client can handle (e.g. application/json, text/html)
Accept-EncodingRequestAcceptable compression (gzip, br, deflate)
Accept-LanguageRequestPreferred natural languages and weights (e.g. zh-CN,en;q=0.8)
AuthorizationRequestAuth credential, e.g. Bearer <token> or Basic <base64>
Cache-ControlGeneralCache directives (no-cache, max-age=3600, private)
CookieRequestCookies set by server via Set-Cookie
Content-TypeGeneralMedia type of request or response body (e.g. application/json; charset=utf-8)
HostRequestTarget host and port, required by HTTP/1.1
OriginRequestSource origin for cross-origin requests, used in CORS
RefererRequestURL of the page making the request (spelled Referer)
User-AgentRequestClient software identifier (browser / crawler / lib name & version)
If-None-MatchRequestConditional request; carries last ETag for cache validation
If-Modified-SinceRequestConditional request; return only if modified after this time
Access-Control-Allow-OriginResponseCORS allowed origin (* or specific)
Content-LengthResponseByte length of the response body
Content-EncodingResponseCompression applied to response body (gzip, br)
Set-CookieResponseServer issues cookie, may set HttpOnly/Secure/SameSite
ETagResponseVersion identifier of the resource for cache validation
Last-ModifiedResponseLast modification time of the resource
LocationResponseTarget URL for 3xx redirect
ExpiresResponseAbsolute expiry time (superseded by Cache-Control)
ServerResponseServer software name and version
WWW-AuthenticateResponseAuth challenge on 401 (e.g. Basic)
Retry-AfterResponseSuggested retry delay in seconds on 503/429
Strict-Transport-SecurityResponseHSTS, force HTTPS for future requests
ConnectionGeneralConnection management (keep-alive or close)
DateGeneralMessage generation date-time (GMT)

Frequently Asked Questions

What is the difference between request and response headers?

Request headers are sent by the client (Accept, Authorization, Cookie) telling the server what it wants and who it is. Response headers come from the server (Content-Type, Set-Cookie, Cache-Control) describing what was returned and how to handle it. Some headers like Content-Type and Cache-Control appear on both sides.

What are common Cache-Control directives?

no-store (never cache), no-cache (revalidate), max-age=seconds (freshness lifetime), public/private (proxy-cacheable), must-revalidate (revalidate after expiry).

Which headers relate to CORS?

On the request side Origin; on the response side Access-Control-Allow-Origin (allowed origin), Access-Control-Allow-Methods, Access-Control-Allow-Headers, and Access-Control-Allow-Credentials.

How do ETag and Last-Modified work with caching?

Both are validators. The client stores the ETag/Last-Modified from the first response and sends If-None-Match/If-Modified-Since on later requests; if unchanged the server returns 304 Not Modified and the client reuses the cache, saving bandwidth.