HTTP header

On this page 7

An HTTP header is a name-value field sent alongside an HTTP request or response that carries metadata about the message: what format the body has, how it may be cached, who is asking, which credentials apply and how the connection should behave. Among Internet protocols, headers are the main extension mechanism of HTTP, because new behavior can be added by defining a new field without changing the protocol itself.

Headers are defined in RFC 9110 (HTTP semantics), with framing rules in RFC 9112 for HTTP/1.1, RFC 9113 for HTTP/2 and RFC 9114 for HTTP/3. Field names are case-insensitive, and a single message may carry dozens of them.

How HTTP headers are structured and transmitted

In HTTP/1.1, headers are plain text lines that follow the request line or status line, each written as Name: value and terminated by CRLF. An empty line marks the end of the header section, after which the optional body begins. A typical request carries Host, User-Agent, Accept and often Cookie.

HTTP/2 and HTTP/3 keep the same semantics but change the wire format. Field names are sent in lowercase, and the request line is replaced by pseudo-header fields such as :method, :path, :scheme and :authority. Header blocks are compressed with HPACK in HTTP/2 and QPACK in HTTP/3, which store repeated fields in a shared table and send only short references.

VersionEncodingField name case
HTTP/1.1Plain text linesAny case, compared case-insensitively
HTTP/2Binary frames with HPACKLowercase required
HTTP/3QUIC streams with QPACKLowercase required
Header handling across HTTP versions

Some fields may appear several times; their values are then combined into a comma-separated list. The notable exception is Set-Cookie, which must remain separate because cookie values can contain commas. Fields that follow the body in chunked or framed messages are called trailers.

Main categories of HTTP headers

Headers are usually grouped by what part of the exchange they describe. The grouping is informal, but it helps when reading or debugging a message.

CategoryRepresentative fieldsPurpose
Request contextHost, User-Agent, RefererIdentify target and client
Content negotiationAccept, Accept-Language, Accept-EncodingAsk for a preferred representation
RepresentationContent-Type, Content-Length, Content-EncodingDescribe the body
CachingCache-Control, ETag, Last-Modified, VaryControl storage and revalidation
AuthenticationAuthorization, WWW-AuthenticateCarry and request credentials
Security policyStrict-Transport-Security, Content-Security-PolicyInstruct the browser to restrict behavior
Cross-origin accessOrigin, Access-Control-Allow-OriginGovern requests between sites
Categories and representative fields

Some fields only make sense in one direction. Host is mandatory in every HTTP/1.1 request, while Server, Location and Set-Cookie appear in responses. A redirect status code such as 301 or 302 is meaningless without a Location header naming the new URL.

Headers compared with other parts of an HTTP message

An HTTP message has three layers of information: the start line, the headers and the body. Placing data in the wrong layer is a frequent design mistake in web APIs.

PartTypical contentVisible in logs and proxies
Start lineHTTP method, path, status codeAlmost always
HeadersMetadata, credentials, caching rulesOften, depending on configuration
BodyThe resource or submitted dataRarely
Query stringParameters of the URLAlmost always
Where information belongs in a message

Credentials belong in the Authorization header rather than the URL, because query strings end up in browser history, server logs and Referer values. Conversely, data that identifies the resource belongs in the path, since many caches use the URL, not custom headers, as the primary cache key.

Practical limits and configuration choices

The specification sets no fixed size limit, but servers and proxies do. Common defaults allow about 8 KB to 16 KB for a single field and roughly 32 KB to 64 KB for the whole header section; exceeding them produces a 431 or 400 status code. Oversized cookies are the most frequent cause.

Custom headers were once marked with an X- prefix, such as X-Forwarded-For. That convention was deprecated by RFC 6648, and new fields should use descriptive names without the prefix; the standardized Forwarded header now covers the proxy case.

Intermediaries treat fields differently depending on their scope. End-to-end headers such as Content-Type or Cache-Control must be forwarded unchanged to the final recipient. Hop-by-hop headers such as Connection, Keep-Alive, Transfer-Encoding and Upgrade apply only to a single connection, and every proxy removes them before passing the message on. HTTP/2 and HTTP/3 forbid connection-specific fields altogether, so a server that still emits them can trigger protocol errors in strict clients.

The order of different fields carries no meaning in the specification, yet repeated fields with the same name must keep their relative order, because combining them changes the resulting list. Applications should therefore read headers through a library that normalizes names and handles repetition correctly.

  • Send security headers such as HSTS and Content-Security-Policy from every HTML response.
  • Use Vary whenever a response changes with Accept-Encoding, Accept-Language or cookies.
  • Remove version-revealing fields such as detailed Server or X-Powered-By values.
  • Never trust client-supplied forwarding headers unless a known proxy sets them.

Common pitfalls with HTTP headers

Header bugs are often invisible in a browser and appear only behind a CDN, a load balancer or a strict client. The table summarizes frequent symptoms and their causes.

SymptomLikely causeFix
Wrong language or format served from cacheMissing Vary fieldAdd Vary for the negotiated header
Request rejected with 431Cookies too largeTrim cookies, move state server-side
Spoofed client IP in logsTrusting X-Forwarded-For blindlyAccept it only from trusted proxies
Response splittingUnescaped CR or LF in a header valueValidate and encode values
Cross-origin call blockedMissing or wrong CORS response fieldsReturn correct Access-Control headers
Header-related problems

In simple terms

When a browser asks a server for a page, the request is like a parcel with a label stuck on the outside. HTTP headers are the lines on that label: who is sending it, what language the reader prefers, and whether a stored copy is acceptable.

The server answers with its own label. It says what kind of content is inside, how long it may be kept and which security rules the browser must follow. The content itself travels separately, in the body.

A practical example

A news site serves articles in English and German from the same URL, choosing the language from the browser’s Accept-Language header. After a CDN is added in front of the site, German readers begin to see English pages. The engineers inspect the responses and find that no Vary header is sent, so the CDN stores one copy per URL and serves it to everyone.

They add Vary: Accept-Language and set Cache-Control: public, max-age=300 on article pages. The CDN now keeps separate cached copies per language, the mix-up disappears within five minutes, and the origin load stays low because each language version is still cached at the edge.