# Return text/markdown via Content Negotiation

Published 2026-06-17 · Updated 2026-09-07 · Author: Özden Erdinc (https://erdinc.ai) · Editorial guidelines: /about#editorial-guidelines

> Return text/markdown when an agent sends Accept: text/markdown, so one canonical URL serves humans and machines the right format via HTTP.

## What is content negotiation?

Content negotiation is the HTTP mechanism by which a server picks a response representation from the client's request headers: RFC 9110 calls the header-driven form proactive negotiation and defines `Accept` as the field a client uses to say which media types are acceptable (IETF, 2022). For the agentic web it means that a request with `Accept: text/markdown` gets the Markdown version of the page while a browser's `Accept: text/html` gets the HTML — one canonical URL, two representations, no separate `.md` link required. The `text/markdown` media type is registered by RFC 7763 (IETF, 2016).

## Why does content negotiation matter for agents?

Content negotiation matters because it solves the format problem at the same URL a human uses, keeping the canonical, the analytics and the link equity on one address, whereas a markdown twin solves it at a second URL. `Vary: Accept` keeps that cache-safe: RFC 9110 has caches use the header fields listed in `Vary` as part of the cache key (IETF, 2022), so a shared cache never hands a browser the Markdown body. It is the cleanest expression of the content dimension's goal: the right format for the right client, without duplicating addresses.

## How do you implement content negotiation for text/markdown?

Implement content negotiation by reading the `Accept` header, returning the matching representation with `Vary: Accept`, and confirming both formats resolve.

1. At your server or edge layer, inspect the `Accept` header on each request.
2. When it names `text/markdown`, respond with the Markdown body and `Content-Type: text/markdown; charset=utf-8`; otherwise serve HTML. Send `Vary: Accept` on both representations.
3. Verify: `curl -H "Accept: text/markdown" https://yoursite/page` returns Markdown with the right `Content-Type`, and a plain request still returns HTML.

Two Agent-Readiness Audit checks grade this: `markdown-negotiation` (9 of 100 points) passes when the audited URL answers `Accept: text/markdown` with a `text/markdown` response, and `vary-accept` (5 points) when the response carries `Vary: Accept`. This page is live proof — on 7 September 2026 it answered `Accept: text/markdown` with `text/markdown; charset=utf-8` and sent `Vary: Accept` on both representations — and `/api/analytics` reports the share of this site's responses served as Markdown.

## Content negotiation — frequently asked questions

### Why send Vary: Accept?

Because caches use the header fields named in Vary as part of the cache key (IETF, 2022); without it a cache could serve a browser the Markdown body or an agent the HTML. The Agent-Readiness Audit awards 5 of 100 points for it.

### What should the server return when Accept does not name text/markdown?

HTML. Return Markdown only when the Accept header names text/markdown; a browser's text/html or a wildcard Accept gets the HTML. Never switch formats on the User-Agent string, which is spoofable and breaks caching.

### Does content negotiation replace .md twin URLs?

No, use both: negotiation keeps one canonical URL, the .md path gives agents that cannot set headers a plain link, and the link element with rel alternate and type text/markdown ties the two together. This site does all three.

## Sources

1. IETF: RFC 9110 HTTP Semantics, Section 12 Content Negotiation, 2022. https://www.rfc-editor.org/rfc/rfc9110#section-12
2. IETF: RFC 7763 The text/markdown Media Type, 2016. https://www.rfc-editor.org/rfc/rfc7763
3. WHATWG: HTML Living Standard — link type alternate, 2026. https://html.spec.whatwg.org/multipage/links.html#rel-alternate

Related: [the content dimension](/agent-readiness/content) · [markdown twins](/agent-readiness/markdown-twins) · [the Agentic Web Lexicon](/glossary) · [audit your site](/services)

