HTTP Cheatsheet

Headers Reference

Use this HTTP reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Header syntax rules

Field names are case insensitive (HTTP/2 and /3 require them lowercase on the wire). Values are ASCII, and non-ASCII needs RFC 8187 encoding (filename*=UTF-8''na%C3%AFve.pdf).

RuleDetail
Repeated fieldscombine into a comma-separated list, except Set-Cookie
Set-Cookienever combined, send one header per cookie
Quality values;q=0 to ;q=1, three decimals max, default 1
X- prefixdeprecated by RFC 6648, do not mint new X- names
Trailersallowed after a chunked body, declared with Trailer
Sizeno spec limit, but servers cap the block at 4-16 KB in practice

Request headers by purpose

Routing and identity

HeaderValueNotes
Hostapi.example.comrequired in 1.1, becomes :authority
User-Agentproduct tokensdo not gate features on it
Refererthe originating URLmisspelled since 1996, controlled by Referrer-Policy
Originhttps://app.example.comscheme, host, port only, no path, sent on CORS and all POSTs
Forwardedfor=1.2.3.4;proto=https;host=xRFC 7239 standard form
X-Forwarded-Forclient, proxy1, proxy2de facto, trust only the hops you control
X-Forwarded-Protohttpshow the app knows the edge terminated TLS

Content of the request body

HeaderValue
Content-Typeapplication/json; charset=utf-8
Content-Lengthbyte count of the body
Content-Encodinggzip, if you compressed the request body
Transfer-Encodingchunked
Expect100-continue, ask before uploading a large body

What the client will accept

HeaderValue
Acceptapplication/json, text/plain;q=0.9, */*;q=0.1
Accept-Encodingbr, gzip, zstd, deflate
Accept-Languageen-US, en;q=0.9, es;q=0.5
Accept-Charsetobsolete, UTF-8 is assumed

Conditionals and caching

HeaderValuePairs with
If-None-Match"9c1f2a" or *ETag, yields 304
If-Modified-SinceHTTP dateLast-Modified, yields 304
If-Match"9c1f2a"optimistic locking, yields 412
If-Unmodified-SinceHTTP dateyields 412
If-Rangeetag or dateconditional range request
Cache-Controlno-cache, max-age=0forces revalidation
Rangebytes=0-1023yields 206

Auth and state

HeaderValue
AuthorizationBearer <token>, Basic <base64>
Proxy-Authorizationcredentials for the proxy
Cookiea=1; b=2, all cookies in one header
DNT / Sec-GPCprivacy signals, largely ignored

Browser-set fetch metadata (Sec- prefixed, unforgeable by scripts)

HeaderValuesTells the server
Sec-Fetch-Sitesame-origin, same-site, cross-site, nonewhere the request came from
Sec-Fetch-Modenavigate, cors, no-cors, same-originthe fetch mode used
Sec-Fetch-Destdocument, image, script, emptywhat it will be used as
Sec-Fetch-User?1a real user gesture triggered it

Response headers by purpose

Describing the payload

HeaderValueNotes
Content-Typetext/html; charset=utf-8always set charset for text
Content-Lengthbytesomitted when chunked or compressed on the fly
Content-Encodingbr, gzip, zstdmust add Vary: Accept-Encoding
Content-Languageen-US—
Content-Dispositionattachment; filename="q3.pdf"forces a download
Content-Locationthe canonical URL of this payload—
Content-Rangebytes 0-1023/146515with 206

Caching and validation

HeaderValue
Cache-Controlpublic, max-age=31536000, immutable
ETag"9c1f2a" strong, W/"9c1f2a" weak
Last-ModifiedTue, 15 Sep 2026 10:04:11 GMT
ExpiresHTTP date, legacy, Cache-Control wins
Ageseconds this response has sat in a cache
VaryAccept-Encoding, Accept-Language

Control and negotiation

HeaderValueSent with
Locationnew or created URL201 and all 3xx
AllowGET, POST, OPTIONS405 and OPTIONS
Retry-Afterseconds or an HTTP date429, 503, 301
WWW-AuthenticateBearer realm="api", error="invalid_token"401
Accept-Rangesbytes or noneadvertises range support
Alt-Svch3=":443"; ma=86400advertises HTTP/3
Upgradewebsocket101
Serverproduct token, better omitted or generic—
Datewhen the response was generatedrequired
Link</style.css>; rel=preload; as=stylepreload, pagination rel=next

Cookies and CORS

HeaderValue
Set-Cookiesid=abc; Path=/; Secure; HttpOnly; SameSite=Lax
Access-Control-Allow-Originone origin or *
Access-Control-Allow-Credentialstrue
Access-Control-Allow-MethodsGET, POST, PATCH
Access-Control-Allow-Headerscontent-type, authorization
Access-Control-Expose-Headerswhich response headers JS may read
Access-Control-Max-Agepreflight cache seconds

Conditional requests in practice

# first request, capture the validator
curl -sI https://example.com/app.js | grep -i etag
# ETag: "9c1f2a"

# second request, revalidate
curl -sI -H 'if-none-match: "9c1f2a"' https://example.com/app.js
# HTTP/1.1 304 Not Modified, no body transferred

# optimistic concurrency: only write if nobody else did
curl -X PUT https://api.example.com/orders/8814 \
  -H 'if-match: "9c1f2a"' -H 'content-type: application/json' \
  -d '{"qty":5}'
# 412 Precondition Failed if the resource changed since

ETag is the stronger validator and works for any content. Last-Modified has one-second resolution, so it cannot express two changes in the same second. Send both when you can, and prefer ETag when they conflict.

Vary, proxies, and the cache poisoning trap

Vary lists the request headers that participate in the cache key. Get it wrong and a shared cache serves one user's variant to everyone.

Response varies byRequired Vary
compressionAccept-Encoding
languageAccept-Language
media typeAccept
mobile vs desktop markupUser-Agent (very low hit rate, avoid)
the logged-in userdo not cache publicly at all, use private

Any request header that changes the response but is not in Vary (or is not part of the cache key at the CDN) is a cache poisoning vector. The safe posture is to keep public responses independent of unkeyed headers, and mark anything user-specific Cache-Control: private, no-store.

curl -sI https://example.com/ | grep -iE 'vary|cache-control|age|etag'
curl -sI -H 'accept-encoding: br' https://example.com/ | grep -i content-encoding
curl -s -D - -o /dev/null --compressed https://example.com/