Content Negotiation
Content negotiation lets clients request a representation by media type, language, or encoding through Accept headers, and the server selects and labels the response.
Definition
Content negotiation is the HTTP mechanism by which a client states preferences with Accept, Accept-Language, and Accept-Encoding, and the server chooses one representation, returning 406 when no acceptable option exists.
Context and scope
Use it when one resource has multiple representations, such as JSON and XML, several languages, or compressed and uncompressed bodies, and clients differ in what they can handle.
Common misconceptions
- It only covers languages; media type, charset, and encoding are negotiated too
- The Accept header forces a representation; the server may return another acceptable type and labels it via Content-Type
- Negotiation has no caching cost; responses vary by headers, which requires Vary
Anti-patterns
- Ignoring Vary so shared caches serve the wrong representation
- Using Accept for API versioning without documenting fallback behavior
- Returning 500 instead of 406 when no representation matches
Related concepts
Related examples
Authoritative source
https://www.rfc-editor.org/rfc/rfc9110#name-content-negotiation
How it works
A request can carry several preference headers. Accept lists media types, Accept-Language lists languages, and Accept-Encoding lists compression schemes. Each entry may include a quality value from 0 to 1, so the server can rank options. The server picks the best available representation, returns it with a matching Content-Type or Content-Language, and adds Vary so caches key on the request headers that influenced the choice.
GET /docs/guide HTTP/1.1
Accept: text/html;q=1.0, application/json;q=0.8
Accept-Language: fr-CA, en;q=0.7
Accept-Encoding: br, gzip
If nothing is acceptable, the correct response is 406 Not Acceptable. A server may also ignore preferences and return its default, but it must then label the representation honestly.
When to use it
Negotiation fits content platforms, internationalized sites, and APIs that support multiple media types or versions. It keeps one URL per resource while allowing clients to choose a format, which is useful for accessibility, bandwidth, and localization.
Trade-offs
Every negotiated dimension multiplies cache variants. A Vary: Accept, Accept-Language, Accept-Encoding header can fragment a CDN cache badly; normalizing headers or using separate URLs is often more efficient. Quality values are easy to misread, and few clients send precise preferences. Debugging requires inspecting request headers, not just paths.
Example and misconceptions
A frequent mistake is assuming Accept is a demand. If a client asks for XML and the server only has JSON, returning JSON with Content-Type: application/json is legitimate only when the client did not forbid it; otherwise 406 is correct. Another mistake is changing language via Accept-Language while caching one variant for everyone.
Related concepts: HTTP Caching, API Versioning, and Cache Invalidation.