Headers and representations
Content negotiation
See how Accept headers let a client express preferences and how a server selects an available representation of a resource.
One URL can have more than one representation. The same resource might be available as HTML, JSON, or a compressed variant. The client states its preferences with Accept headers:
Accept: text/html, application/json;q=0.8
Accept-Language: en, it;q=0.7
Accept-Encoding: br, gzip
The server picks a supported option. Quality values such as q=0.8 rank one format below another. Accept-Encoding tells the server which compression the client understands.
Let’s try it. Ask for JSON first:
curl -I -H 'Accept: application/json' https://flaviocopes.com/
This site returns HTML regardless, because it does not negotiate format on that URL. An API endpoint would behave differently:
curl -I -H 'Accept: application/json' https://httpbin.org/json
You should get content-type: application/json. The server matched your preference.
The server is not required to support every requested representation. An API may always return JSON. A site may use distinct URLs like /en/docs and /it/docs instead of negotiating language on one path.
When a response changes according to a request header, caches need to know. A response header such as Vary: Accept-Encoding tells a cache to keep separate copies for different compression preferences. Without Vary, a cache might serve a gzip body to a client that asked for uncompressed content.
Be careful when debugging negotiation. curl sends different default Accept headers than a browser. Compare both in the Network panel and in the terminal to see why you get different Content-Type or Content-Encoding values.
Language negotiation works the same way. A browser might send Accept-Language: en-US,en;q=0.9,it;q=0.8. The server picks the best match from the formats it supports, or falls back to a default locale. Distinct URLs per language sidestep negotiation entirely, which many content sites prefer because URLs stay shareable and cache-friendly.
Try this: send two curl requests to the same API URL, one with Accept: application/json and one with Accept: text/html. Note whether the server returns different status codes, bodies, or Content-Type values.
Quick check
Result
You got of right.
Lesson completed