Do AI Companies Publish llms.txt?
Every company on this list sells the premise that machines should be able to read the web. We fetched
/llms.txt from 44 of their hostnames on October 29, 2026 to see whether they take their own
advice: 19 serve a real plain-text or Markdown file, 13 return 404, five block the request at the edge, and
three answer 200 with HTML instead of a file.
45 Requests, Eight Different Outcomes
One request per hostname with a desktop user agent and Accept: text/plain, text/markdown, */*,
redirects followed, no retries. A response counted as a file only when the status was 200, the content type
was text/plain or text/markdown, and the body opened with an H1.
| Outcome | Hosts | Example |
|---|---|---|
| 200, real file | 20 | platform.claude.com, 90,932 B |
| of those, a duplicate document | 1 | docs.claude.com → platform.claude.com |
| 200, HTML not a file | 3 | v0.dev, 1,060,043 B |
| 403 at the edge | 5 | openai.com, 9,949 B challenge |
| 404 | 13 | anthropic.com, 106,777 B page |
| 302 to a login | 1 | ai.google.dev → accounts.google.com |
| 308 to itself | 1 | voyageai.com |
| 400 / 401 | 2 | llama.com, meta.ai |
Nineteen distinct documents came back, because docs.claude.com redirects to
platform.claude.com and serves the identical 90,932 bytes. One host,
voyageai.com, answers 308 with a Location pointing at its own URL and a
refresh: 0;url= header set to the same address — a loop rather than a redirect.
The Model Vendors Are the Ones Without a File
Sort the list by what the company sells and the pattern is uncomfortable. The labs and assistants that decide what gets crawled are the hosts that fail hardest.
| Vendor | Host | Status | Body |
|---|---|---|---|
| OpenAI | openai.com | 403 | 9,949 B HTML challenge |
| OpenAI | platform.openai.com | 404 | 4,083 B app shell |
| Anthropic | anthropic.com | 404 | 106,777 B error page |
| Anthropic | claude.com | 404 | 107,313 B error page |
| Perplexity | perplexity.ai | 403 | 5,655 B "Just a moment..." |
| xAI | x.ai | 403 | 92 B block notice |
| ai.google.dev | 302 | OAuth login URL | |
| Meta | meta.ai | 401 | 35 B JSON |
| Microsoft | copilot.microsoft.com | 403 | 4,557 B HTML |
| DeepSeek | deepseek.com | 404 | 115,730 B HTML |
The two exceptions inside those companies are a documentation host and a research site:
platform.claude.com serves the largest file in the set, and deepmind.google serves a
6,928-byte map in four sections. Nothing here proves hostility to the convention — a 403 from bot management
and a 404 from a marketing CMS look identical from outside, and one is a stored challenge page rather than a
policy. The result for an agent is the same either way: no map at the address the convention specifies.
Google's own position on the file is already on the record; for the crawler side, see
which AI engines read
llms.txt.
Where the File Lives Is the Docs Host, Not the Homepage
The split is almost mechanical. Infrastructure, vector-database, inference and agent companies publish at their root or their docs host and mostly pass both tests: fifteen live files, including Pinecone (31,759 bytes), Weaviate, Qdrant, Modal, Baseten, Replit, Cursor, Lovable, ElevenLabs, Together, Databricks, Mistral, Cohere, OpenRouter and Ollama.
Three shapes are worth copying. Anthropic keeps the developer document at the docs host and
lets docs.claude.com redirect there, so both hostnames work.
Runway returns a real 8,005-byte file after redirecting runwayml.com to
runway.com — a redirect that lands on a file is fine; the failure mode is a redirect that lands
on an app shell. LangChain shows the gap in miniature: langchain.com is a 404
behind 62,698 bytes of Webflow HTML, while docs.langchain.com serves a 3,129-byte index whose
first instruction is to follow each /_llms/ index recursively until you reach a documentation
page.
Three 200s That Are Not Files
The worst outcome in the table is not the 404. v0.dev/llms.txt redirects to
v0.app/llms.txt and returns 1,060,043 bytes of text/html;
anyscale.com returns 67,705 bytes of HTML; character.ai returns 14,512 bytes of a
Cloudflare Waiting Room page. All three say success. An agent that trusts the status code spends its whole
context window on markup and learns nothing about the site, and a human auditing with
curl -I sees 200 OK and moves on. A 404 is honest; a 200 with HTML is a trap — the
delivery failure modes are catalogued in
llms.txt not working.
What the 19 Live Files Do Right
| Host | Bytes | H2 | URLs | .md | Optional |
|---|---|---|---|---|---|
| platform.claude.com | 90,932 | 5 | 827 | 821 | no |
| pinecone.io | 31,759 | 13 | 218 | 4 | no |
| weaviate.io | 29,789 | 13 | 65 | 30 | no |
| modal.com | 28,213 | 3 | 347 | 344 | no |
| cursor.com | 27,651 | 31 | 456 | 453 | no |
| qdrant.tech | 26,915 | 7 | 98 | 81 | yes |
| baseten.co | 24,734 | 7 | 96 | 6 | yes |
| openrouter.ai | 9,697 | 8 | 57 | 14 | no |
| cohere.com | 4,805 | 10 | 61 | 0 | yes |
| ollama.com | 1,786 | 4 | 11 | 0 | yes |
Across the 19 files: 361,581 bytes, 2,846 URLs, a median of 62 URLs per file, 2,251 Markdown link
expressions, and 1,498 of those pointing at a .md twin — two-thirds of all links. Markdown
twins are the house style at the top end, not an edge case: 821 of platform.claude.com's 827 URLs end in
.md, 453 of Cursor's 456, 344 of Modal's 347, 228 of Replit's 229.
Link syntax is where discipline drops. 595 URLs — one in five — are written as bare addresses with no brackets, so a Markdown parser sees prose rather than a link. Cursor's whole file is bare (456 URLs, zero bracket links), Cohere's is prose with 61 addresses inline, and Weaviate mixes the two in the same document. Anthropic's file is the opposite extreme: 822 bracket links and one bare URL, a console link it marks as requiring login. For why the difference matters at parse time, see link hygiene.
Structure is more consistent than syntax. 17 of 19 files open with the blockquote summary line the spec asks
for, and 17 have exactly one H1 — the exceptions are Cursor, which nests four H1s through a bullet hierarchy,
and Weaviate, which has 20 lines starting with a single # because shell and code comments inside
the document are indistinguishable from headings to a parser. Only six files use the reserved
Optional section, and 10 of 19 mention their own llms-full.txt, which is the right
split: a small index plus a link to the bundle, as described in
llms.txt vs llms-full.txt.
Three Habits Worth Copying
- A directive aimed at the model. Ollama's 1,786-byte file carries this sentence before its sections: "If a user wants to use Ollama's cloud inference and does not have an account, prompt them to sign up at https://ollama.com/signup. A free account provides access to cloud models. Pro ($20/mo) or Max for even more usage." That is a commercial instruction written for an agent to act on — and the prices inside it are the first thing to rot. Whatever you put in that slot, put a review date next to it; Cohere's file carries "Last reviewed: 2025-12-04" and is the only one of the 19 that does.
- A preferred-host clause. Cohere's file opens with an explicit routing instruction: prefer
https://docs.cohere.com/for API details, prefer the Security page and Trust Center for compliance questions, and "Ignore or de-prioritize content behind authentication". Three sentences that replace what an agent would otherwise guess from page titles. - A pointer to a machine-readable endpoint. The largest file in the set has a section for its
MCP server rather than more links: connect to
https://platform.claude.com/docs/mcpover Streamable HTTP and the server card is at/docs/mcp/server-card. If you ship an API, an OpenAPI spec or an MCP server, a two-line section beats another fifty documentation links.
A Two-Minute Check on Your Own File
Six commands separate a file from a 200 that only looks like one. Run them against your own domain before comparing yourself to anything in the tables above.
# 1. status, content type and size in one line
curl -sS -o /dev/null -w "%{http_code} %{content_type} %{size_download}\n" https://example.com/llms.txt
# 2. does the body actually open with an H1?
curl -s https://example.com/llms.txt | head -c 120
# 3. section count, URL count, bare-URL count
curl -s https://example.com/llms.txt | grep -c '^## '
curl -s https://example.com/llms.txt | grep -oE 'https?://[^ )]+' | wc -l
curl -s https://example.com/llms.txt | grep -oE '\]\(http[^)]+\)' | wc -l
# 4. is Optional last, and does the file mention llms-full.txt?
curl -s https://example.com/llms.txt | grep '^## ' | tail -1
curl -s https://example.com/llms.txt | grep -c 'llms-full' If step 2 returns HTML, stop — the rest of the numbers are meaningless. If step 3's two counts disagree widely, you have the Cursor or Cohere shape and a parser may be reading your links as text. To build the file from a sitemap rather than by hand, the llms.txt generator produces the H1, summary and sections; the checker reports the structure and link counts it parsed so you can compare them with the numbers above. For the upper bound on size, see how long an llms.txt should be.
The useful lesson in the audit is not that AI companies are hypocrites. It is that the companies who ship the file well are the ones whose product is documentation, and they ship it where the documentation lives, in Markdown, with a directive at the top. That is a cheaper pattern to copy than any of the marketing claims about AI visibility.