---
title: "Markdown for Agents: Serve Accept: text/markdown"
description: "Serve Markdown to AI agents with Accept: text/markdown and Vary: Accept. Real SeenLens headers, plus Next.js, Nginx and Cloudflare setups."
url: https://seenlens.com/fixes/serve-markdown-to-agents
last_updated: 2026-11-06
---

# Markdown for agents: how to serve Accept: text/markdown

Markdown for agents means the same URL returns Markdown when a client sends Accept: text/markdown, and HTML for browsers. SeenLens reports info when no Markdown version exists. The feature is optional, and no major agent is confirmed to ask for it. Setup takes one to three hours, depending on the stack.

By SeenLens. Last updated: 2026-11-06

## What does the Markdown version check test?

SeenLens tries three routes to a Markdown version of the scanned page. One working route is enough.

1. Content negotiation. SeenLens requests the page with `Accept: text/markdown`. The route works when the answer is 200 with a `text/markdown` content type.
2. A link alternate. The page head holds `<link rel="alternate" type="text/markdown" href="...">`. SeenLens fetches up to three such links. The route works when one returns 200 and is not HTML.
3. A `.md` sibling. SeenLens requests the page path with `.md` added, such as `/pricing.md`, or `/index.md` for the home page. The route works when the answer is 200 and not HTML.

The result is a pass when a route works. If the page uses content negotiation without `Vary: Accept`, the result is a warning, because a shared cache may then serve Markdown to browsers or HTML to agents. When no route works, the result is info. That is the lowest severity, because the feature is optional.

## What does a working response look like?

These are the real response headers of https://seenlens.com/pricing for a request with `Accept: text/markdown`, taken on 2026-11-06. The list is trimmed.

```text
$ curl -sI -H 'Accept: text/markdown' https://seenlens.com/pricing
HTTP/2 200
cache-control: s-maxage=31536000
content-type: text/markdown; charset=utf-8
link: <https://seenlens.com/pricing>; rel="canonical"
vary: Accept
x-content-type-options: nosniff
x-markdown-tokens: 953
```

`content-type` shows Markdown. `vary: Accept` tells caches that the answer depends on the Accept header. `link ... rel="canonical"` points search engines to the HTML URL, so the Markdown copy does not compete with it. `x-markdown-tokens` is an estimated token count for the document. The same URL without the Accept header returns `content-type: text/html; charset=utf-8`.

The body starts with a short front matter block (title, description, url, last updated), then the page as Markdown:

```text
---
title: "Pricing: AI Visibility Report, USD 49 · SeenLens"
url: https://seenlens.com/pricing
last_updated: 2026-11-05
---

# Pricing
```

## Do agents ask for Markdown?

The evidence is early. Cloudflare announced a Markdown for Agents feature on 2026-02-12. It converts HTML to Markdown at the edge when a client sends `Accept: text/markdown`. Google says Google Search does not use llms.txt files, AI text files, special markup or Markdown. SeenLens found no source that confirms which consumer AI agents request Markdown. Serve it for tools and developers who send the header, and expect no ranking or citation effect.

Content negotiation is part of HTTP: RFC 9110 defines the `Accept` request field and the `Vary` response field. See [Markdown content negotiation](https://seenlens.com/glossary/markdown-content-negotiation).

## How do I serve Markdown to agents?

Keep the Markdown equivalent to the HTML. Send `Vary: Accept` on both the Markdown and the HTML answers of a negotiated URL. Add a canonical link header to the Markdown answer.

### Next.js App Router

SeenLens uses a middleware that rewrites a request to an internal Markdown route handler when the client prefers Markdown or the path ends in `.md`. This is a reduced version of it.

```text
import { NextResponse, type NextRequest } from "next/server";

export function middleware(req: NextRequest) {
  const { pathname } = req.nextUrl;
  const accept = req.headers.get("accept") ?? "";
  const wantsMd = pathname.endsWith(".md") || accept.includes("text/markdown");
  if (!wantsMd) return NextResponse.next();

  const base = pathname.replace(/\.md$/, "") || "/";
  const url = req.nextUrl.clone();
  url.pathname = "/md" + (base === "/" ? "/index" : base);
  const res = NextResponse.rewrite(url);
  res.headers.set("Vary", "Accept");
  return res;
}

export const config = { matcher: ["/", "/pricing", "/(.+\\.md)"] };
```

A route handler at `app/md/[...path]/route.ts` returns the Markdown with `Content-Type: text/markdown; charset=utf-8`. Parse the Accept header properly in production code. A header such as `text/html, text/markdown;q=0.1` prefers HTML, and the simple `includes` check above would send Markdown. SeenLens compares the q values.

One gotcha from the SeenLens code: Next.js sets its own `Vary` header on prerendered HTML and drops one set in middleware. Add `Vary: Accept` for the HTML answers at the proxy or CDN.

### Nginx with Markdown files next to the HTML

Build a `.md` file next to each page. When the client asks for Markdown, Nginx rewrites the request to the `.md` file. This is an example to adapt. Test it with `nginx -t` and curl before you reload the server.

```text
map $http_accept $want_md {
    default 0;
    "~*text/markdown" 1;
}

server {
    # ...
    location / {
        add_header Vary Accept always;
        if ($want_md) {
            rewrite ^/$ /index.md last;
            rewrite ^(/.+?)/?$ $1.md last;
        }
        try_files $uri $uri/index.html =404;
    }

    location ~ \.md$ {
        default_type text/markdown;
        charset utf-8;
        add_header Vary Accept always;
    }
}
```

### Cloudflare

Cloudflare's Markdown for Agents converts pages at the edge. Turn it on for the zone from the dashboard Quick Actions. The announcement listed the beta as free for Pro, Business and Enterprise plans, so check current availability.

### WordPress, Shopify and hosted platforms

SeenLens found no first party documentation for a WordPress or Shopify setting that serves Markdown by content negotiation. Two options remain: put Cloudflare in front of the site, or skip this check because it is optional.

### Static sites

Write the Markdown copies at build time, one `.md` file per page, and add a link alternate to each HTML page. The llmstxt.org proposal also describes `rel="alternate"` with `type="text/markdown"`.

```text
<link rel="alternate" type="text/markdown" href="/pricing.md">
```

## How do I verify the fix?

```text
curl -sI -H 'Accept: text/markdown' https://example.com/page
curl -sI https://example.com/page
```

1. The first answer must show 200, a `text/markdown` content type and `Vary: Accept`.
2. The second must still show `text/html`.
3. Scan the page with SeenLens. The evidence line lists the status, content type and `Vary` result.

## When can I skip this?

Skip it if you have no need for Markdown copies. The result is info, which earns half credit on a check with weight 3 in the agent readiness dimension. A site that shows nothing without JavaScript should fix [server rendering](https://seenlens.com/fixes/content-needs-javascript) first, because that affects every crawler.

[Scan your page with SeenLens](https://seenlens.com/)

## Which checks are related?

- [Add llms.txt](https://seenlens.com/fixes/add-llms-txt) covers the index of pages that can point to the Markdown versions.
- [Content needs JavaScript](https://seenlens.com/fixes/content-needs-javascript) covers pages that are empty without scripts.
- [Add a canonical URL](https://seenlens.com/fixes/add-canonical-url) covers the preferred URL of each page.

## Sources

- [Cloudflare: Markdown for Agents](https://blog.cloudflare.com/markdown-for-agents/) (Accept: text/markdown conversion, response headers, plan availability; published 2026-02-12; checked 2026-11-06)
- [RFC 9110: HTTP Semantics](https://www.rfc-editor.org/rfc/rfc9110.html) (Accept in section 12.5.1 and Vary in section 12.5.5; checked 2026-11-06)
- [Google Search Central: Optimizing your website for generative AI features](https://developers.google.com/search/docs/fundamentals/ai-optimization-guide) (Google Search does not use Markdown or AI text files; checked 2026-11-06)
- [llms.txt proposal](https://llmstxt.org/) (.md page versions and rel="alternate" type="text/markdown"; checked 2026-11-06)
- [Next.js docs: route.js](https://nextjs.org/docs/app/api-reference/file-conventions/route) (route handlers; checked 2026-11-06)
