# What content negotiation is

One URL, many representations. The server picks which bytes to send based on the client's `Accept` header.

Content negotiation is a mechanism defined in HTTP that lets a single URL
serve different representations of the same resource, and lets the server
pick which one to send based on what the client asked for.

The classic example is language: one URL `/about`, and the server returns
English, French, or German based on `Accept-Language`. The same machinery
applies to media types via `Accept` — which is how a single URL can serve
HTML to a browser and Markdown to an agent.

## The request side

Every HTTP request can carry an `Accept` header listing the media types
the client can handle, ranked by preference:

```http
GET /article HTTP/1.1
Host: example.com
Accept: text/markdown, text/html;q=0.8
```

That says: *I prefer Markdown; I'll take HTML at 80% preference if you
can't do Markdown.* The `q` value is a quality factor from 0 to 1. No `q`
means `q=1` (maximum preference).

## The response side

The server picks the representation that best matches, sets
`Content-Type` to describe what it actually sent, and sets `Vary: Accept`
so downstream caches know the response depends on the request's Accept
header:

```http
HTTP/1.1 200 OK
Content-Type: text/markdown; charset=utf-8
Vary: Accept

# How content negotiation works

One URL, many representations…
```

If the server cannot satisfy the request — it doesn't have any of the
types the client will accept — it returns
[`406 Not Acceptable`](/guides/returning-406).

## Why it matters now

Browsers and LLM agents want fundamentally different things from the
same URL. Browsers want HTML with navigation, CSS, and scripts. Agents
want the text, clean, without the chrome. Content negotiation is the
only mechanism that lets the canonical URL serve both, without
fragmenting the site into parallel URLs.

## What it's *not*

- It's not `.md` sibling files at parallel URLs. Sibling files are
  fine to ship &mdash; they're a separate URL, not the canonical one
  serving two representations. On their own, they leave the canonical
  URL returning HTML to any agent that asks. If you ship siblings,
  advertise them via a `Link: rel="alternate"` header
  ([RFC 8288](/reference)) so agents can discover them. And if you
  want the canonical URL itself to serve Markdown when requested,
  implement the `Accept` header. You can do both.
- It's not about the *content* being different — it's the same content,
  in a different format.

## References

- [MDN — Content negotiation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Content_negotiation) — canonical overview, the companion to this guide.
- [RFC 9110 §12.5.1 — Proactive Negotiation](https://www.rfc-editor.org/rfc/rfc9110#name-proactive-negotiation) — the normative spec.