Guide · 8 min read · updated 2026-08-22

robots.txt for AI crawlers: the complete reference

The exact rules a compliant AI crawler applies to your robots.txt, the four mistakes that quietly void it, and a worked reference file.


A compliant crawler resolves your robots.txt in three steps: pick exactly one group by user-agent token, pick the winning rule inside that group by pattern length, and if nothing matched, fetch. That is the whole algorithm. Almost every robots.txt failure we see in scans comes from assuming a fourth step exists.

The specification is RFC 9309, which the major AI crawler operators say they implement: OpenAI, Anthropic, Google, Apple, Perplexity, Amazon, Mistral, Common Crawl and DuckDuckGo all publish robots.txt tokens and describe standard behaviour. What follows is the mechanism, then the failure modes, then a reference file you can adapt.

Step one: group selection

Consecutive User-agent lines with no rules between them form a single group that shares the rules beneath it. A crawler compares its own product token against every group's tokens and selects one group:

  1. Longest matching token wins. The group whose token is the longest case-insensitive match for the crawler's product token is selected. A crawler identifying as Googlebot-News obeys a googlebot-news group even when a googlebot group also exists in the same file.
  2. Otherwise the * group. With no token match at all, the crawler uses the User-agent: * group.
  3. Otherwise everything is allowed. No matching group and no * group means no restrictions. Allow-by-default is the specification's position, not a lenient interpretation of it.
Groups do not compose. Rules are never inherited, merged or overridden across groups. Once a crawler has selected its group, the rest of the file is invisible to it. This is why adding a friendly Allow: / under User-agent: * does nothing for a crawler that has its own group, and why a Disallow: / under * does nothing to a crawler you named ten lines earlier.

Two operators complicate this deliberately. Apple documents that "if robots instructions don't mention Applebot but mention Googlebot, the Apple robot will follow Googlebot instructions" (support.apple.com/en-us/119829). Amazon documents the same fallback for Amzn-SearchBot toward other search-bot rules (developer.amazon.com/amazonbot). For these two agents, the effective policy is not readable from their own group alone.

Step two: rule precedence inside the group

Every Allow and Disallow in the selected group is matched against the request path. The rule with the longest pattern decides. When an Allow and a Disallow match with equal pattern length, Allow wins. Two wildcards are supported: * matches any sequence of characters, and a trailing $ anchors the pattern to the end of the path.

RuleBlocksDoes not block
Disallow: /reports/reports, /reports/q3, /reports-archive/Reports, /old/reports
Disallow: /reports//reports/q3/reports-archive
Disallow: /*.pdf$/a/b.pdf/a/b.pdf?v=2
Disallow: /*?/search?q=x/search
Disallow: /
Allow: /blog/
/about/blog/post-1
Disallow:nothing at allevery path in the group

The last row is worth its own sentence. An empty Disallow: is a valid line that matches no path, so it permits everything in its group. It is the specification's idiom for "this agent is unrestricted", and it is not a typo to be repaired. Deleting the value from a working Disallow: / inverts the rule.

Four mistakes that void an otherwise correct file

1. A blanket rule that shadows nothing

The pattern we see most often is a file that ends with User-agent: * and Disallow: /, written by someone who believed it was a catch-all, sitting in a file that also contains named groups for Googlebot and bingbot. The named crawlers are unaffected. Every crawler without a group is fully blocked, and that set includes most answer-engine retrieval fetchers and, by construction, every agent that ships after you wrote the file. The blast radius is exactly the agents you did not think about.

2. Blocking by path when the crawler enters by sitemap

Path rules govern fetching, not discovery. A URL listed in your sitemap, linked from a canonical tag, or already held in a search index is still a candidate; the crawler simply gets a disallow when it tries to fetch it. The observable result is a URL that answer engines know about and cannot read, which is worse than either being open or being absent. If a section is genuinely private, remove it from the sitemap and from internal links as well as disallowing it. If it is public, do not disallow it because a staging convention leaked into production.

3. Case handling

Tokens and field names are case-insensitive; paths are not. Disallow: /admin/ leaves /Admin/ open. On servers that resolve both to the same handler this is a bypass, not a nuance.

4. Assuming one file covers the property

robots.txt is fetched at host level. Amazon's documentation states the rule explicitly: site.example.com/robots.txt governs that host independently of example.com. Marketing site, docs, help centre, status page and shop each need their own file. A scan of your apex domain tells you nothing about your docs subdomain, which is frequently the content an assistant most wants to quote.

Crawl-delay: who honours it

Crawl-delay is not in RFC 9309, and support is genuinely split:

OperatorCrawl-delaySource
AnthropicHonouredAnthropic crawler support article
AppleExplicitly ignoredApplebot documentation
AmazonExplicitly ignoredAmazonbot documentation
GoogleAbsent from the specGoogle crawlers reference

The practical consequence: a Crawl-delay intended to protect a fragile origin protects it from some crawlers and not others, while a delay long enough to matter can push a retrieval fetch past an answer engine's timeout. Rate-limit at the edge instead, where enforcement is real and applies uniformly.

Agents that are outside the contract by design

Several documented agents state that they may not follow robots.txt. Perplexity says Perplexity-User "generally ignores robots.txt rules". Meta says meta-externalfetcher "may bypass robots.txt rules", and facebookexternalhit may bypass it for "security or integrity checks". OpenAI's ChatGPT-User and Amazon's Amzn-User use softer wording: rules "may not apply" and "may not follow all robots.txt directives". These are all user-initiated fetchers, acting on behalf of a person who asked for a specific page. Writing a Disallow for them is a statement of preference, not a control. Our crawler registry records this per agent, so a report does not claim you have blocked something you have not.

Two tokens are the inverse case: Google-Extended and Applebot-Extended emit no user agent at all. Google states that "Google-Extended doesn't have a separate HTTP request user agent string" and that the token is used "in a control capacity"; Apple states that "Applebot-Extended does not crawl webpages". Your posture toward these two exists only in robots.txt, and no log analysis can tell you anything about them.

A worked reference file

This implements one common policy: allow answer-engine retrieval and classic search, deny model training. Adapt the token lists to your own decision rather than copying the policy.

# ---------------------------------------------------------------------------
# robots.txt for example.com   -   reviewed 2026-08-22
# Policy: allow retrieval and search, deny training.
# This file governs THIS HOST ONLY. docs.example.com needs its own copy.
# No Crawl-delay: support is split (Anthropic honours it, Apple and Amazon
# do not, Google's spec omits it). Rate limits belong at the edge.
# ---------------------------------------------------------------------------

# --- Answer-engine retrieval: allowed everywhere public --------------------
User-agent: OAI-SearchBot
User-agent: PerplexityBot
User-agent: Claude-SearchBot
User-agent: Claude-User
User-agent: MistralAI-Index
User-agent: DuckAssistBot
User-agent: Amzn-SearchBot
Disallow: /cart/
Disallow: /account/
Disallow: /internal/
Disallow: /*?
Allow: /*?page=

# --- Classic search index, which is also the crawl behind AI Overviews ----
User-agent: Googlebot
User-agent: bingbot
User-agent: Applebot
User-agent: Amazonbot
Disallow: /cart/
Disallow: /account/
Disallow: /internal/
Disallow: /reports/
Allow: /reports/public/

# --- Training crawlers: denied --------------------------------------------
User-agent: GPTBot
User-agent: ClaudeBot
User-agent: CCBot
User-agent: MistralAI-Training
User-agent: Bytespider
User-agent: meta-externalagent
Disallow: /

# --- Control tokens: no crawler, robots.txt is the only surface -----------
User-agent: Google-Extended
Disallow: /

User-agent: Applebot-Extended
Disallow: /

# --- Everything not named above -------------------------------------------
# Reached only by crawlers with no group of their own. It neither loosens
# nor tightens any group above: rules never cross group boundaries.
User-agent: *
Disallow: /cart/
Disallow: /account/
Disallow: /internal/

Sitemap: https://example.com/sitemap.xml

Three details in that file repay attention. Disallow: /*? followed by Allow: /*?page= works because the Allow pattern is longer, so paginated listings stay fetchable while every other query string is closed. Disallow: /reports/ with Allow: /reports/public/ is the same mechanism at directory level. And the * group repeats the shared disallows rather than relying on inheritance, because inheritance does not exist.

X-Robots-Tag, noindex and the snippet directives

robots.txt controls the fetch. The robots meta tag and the X-Robots-Tag response header control what happens to the page after it is fetched. They share one directive vocabulary, they combine, and the most restrictive value wins. The header form is the only option for non-HTML resources such as PDFs, images and JSON, and it can be set at the CDN without touching a template.

X-Robots-Tag: noindex, nofollow
X-Robots-Tag: max-snippet:120
X-Robots-Tag: applebot: nosnippet
<meta name="robots" content="max-snippet:120, noarchive">

<p>Public summary that may be quoted.
  <span data-nosnippet>Internal note, never quotable.</span>
</p>
DirectiveDocumented byEffect on AI output
noindexGoogle, Apple, AmazonRemoves eligibility entirely. The page is still fetched, then discarded, so it can never be cited.
nosnippetGoogle, AppleApple states that nosnippet content "will not be used as additional context… when AI models are used to generate output", and doubles as the opt-out from Apple's broad world knowledge answers.
max-snippet:NGoogleCaps the extractable text length, which caps what a generated answer can quote.
data-nosnippetGoogle, BingSection-level suppression. Bing added support on 2025-10-15, described as hiding sections "without affecting visibility or ranking" in "Bing Search and AI answers" (Bing Webmaster Blog).
noarchiveAmazonAmazon honours page-level noarchive as "do not use the page for model training", a training control most audits never check.
applebot: nosnippetApplePer-agent header form, which works for non-HTML resources where a meta tag is impossible.

What does not work is the non-standard family. Meta's crawler documentation is blunt about it: "we make it easy for site managers and content owners to indicate their preferences by using industry-standard practices like robots.txt rather than non-standard formats like NoAI tags." Treat noai and noimageai meta tags as decoration.

Note the asymmetry when you choose between the two layers. A robots.txt disallow is cheap, applies before the fetch, and is enforced by nothing but goodwill. A header directive requires the crawler to fetch the page first, so it costs you the request but controls the display. If your goal is "index me, do not quote me", the header is the only tool that expresses it.

Verify rather than assume

Our scanner parses robots.txt per RFC 9309 and evaluates every token in the registry against the same document, so the report tells you which crawlers a rule actually covers rather than which ones you intended. The full procedure, including how a group is selected and how a live block is distinguished from a robots.txt disallow, is documented on the methodology page.

Scan your site to see, per crawler, which group in your robots.txt is selected, which rule decides the verdict at your root path, whether that verdict came from a rule or from allow-by-default, and which X-Robots-Tag or meta directives your origin is attaching on top of it.

Common questions

Does Disallow: / for GPTBot stop ChatGPT from citing my pages?

No. GPTBot is OpenAI's training crawler. Appearance in ChatGPT search is governed by a different token: OpenAI documents that "sites that are opted out of OAI-SearchBot will not be shown in ChatGPT search answers, though can still appear as navigational links." Blocking GPTBot removes you from training corpora and leaves retrieval untouched, which is a coherent policy, but only if you also leave OAI-SearchBot allowed.

Does a User-agent: * group apply on top of a named group?

No. Under RFC 9309 a crawler selects exactly one group, the one whose user-agent token is the longest match for its own product token, and it never consults rules in any other group. A permissive * group therefore cannot soften a specific Disallow, and a restrictive * group cannot tighten a specific Allow. This is the single most common misreading of the format.

Is robots.txt case-sensitive?

Field names and user-agent tokens are matched case-insensitively, so User-agent, user-agent and USER-AGENT are the same field and GPTBot matches gptbot. Path patterns are case-sensitive, because URL paths are. Disallow: /admin/ does not block /Admin/, and on a server that treats those as the same document you have written a rule with a trivial bypass.

How long does a robots.txt change take to apply?

It varies by operator, and none of them apply it instantly. OpenAI, Meta and Perplexity document roughly 24 hours. DuckDuckGo documents 72 hours for DuckAssistBot. Amazon caches robots.txt for up to 30 days, and states that if it cannot fetch the file it "will behave as if it does not exist". A site audited minutes after an edit is not yet in its new state.

Do subdomains inherit the root domain's robots.txt?

No. robots.txt is fetched per host. Amazon's crawler documentation states plainly that site.example.com/robots.txt governs that host independently of example.com. A blog, docs site, help centre or shop on its own subdomain needs its own file, and needs auditing separately.

Keep reading