Allow AI Crawlers in robots.txt Without Opening Everything
Allow AI crawlers in robots.txt on the paths that earn citations, keep them out of checkout, account and internal search, and verify what each agent reaches.

You've already decided to let the AI crawlers in. The harder question starts one second later: which parts of the site do they get? Allowing AI crawlers in robots.txt is not one switch. It's a path list, and the default path list on most sites hands a retrieval agent your checkout flow, your internal search results and four hundred near-empty tag archives alongside the twelve guides you actually wanted quoted.
This post is about that path list. If you're still deciding whether to allow them at all, which agents exist, and how a retrieval crawler differs from a training crawler, that's the other article: Block or Allow AI Crawlers. One rule from it carries over and you cannot skip it. The moment you create a group for a named agent, that agent reads only that group and stops reading User-agent: * entirely. Rules are never inherited between groups, so every path rule below has to be repeated inside every group you write.
Start from your URL templates, not the agent list
Most AI crawler guides open with a table of bots. That's the wrong end of the problem once the decision is made, because robots.txt does not control agents at the page level. It controls them at the path pattern level, and path patterns come from your templates.
So the first artifact you need isn't a bot list. It's a template inventory: every distinct URL shape your CMS can emit, with one representative URL for each.
A typical small content site emits more shapes than its owner expects:
| Template | Path prefix | Representative URL |
|---|---|---|
| Article | `/blog/` | `/blog/organic-ctr-benchmark/` |
| Long-form guide | `/guides/` | `/guides/search-console-setup/` |
| Glossary term | `/glossary/` | `/glossary/dwell-time/` |
| Comparison page | `/compare/` | `/compare/clicks-vs-visits/` |
| Category and tag archives | `/category/`, `/tag/` | `/tag/ctr/` |
| Archive page 2 and beyond | `?page=` | `/blog/?page=3` |
| Internal search results | `/search` | `/search?q=ctr` |
| Gated content | `/members/` | `/members/full/chapter-4/` |
| Cart and checkout | `/cart/`, `/checkout/` | `/checkout/step-2/` |
| Account area | `/account/` | `/account/orders/` |
| Staging or preview | `/preview/` | `/preview/draft-881/` |
| Outbound redirect | `/go/` | `/go/partner-a/` |
| Tracked variant | `?utm_` | `/blog/organic-ctr-benchmark/?utm_source=newsletter` |
Here's the part that gets skipped. Your exposure surface is the URL set, not the page set. One guide is one page in your head and often a dozen URLs in reality: the canonical, the tracked variant from your newsletter, the sorted view, the paginated view, the uppercase link somebody pasted, the print route. A rule that opens /guides/ opens all of them. A retrieval agent that samples the sorted-and-tracked variant chunks a page whose main content sits below a filter bar, and that becomes the version of you it quotes. A canonical tag doesn't rescue this, because the crawler has to fetch the page to read the canonical, and by then it has the content.
Write the inventory down before you write a single rule. Everything after this section gets applied to that table.
Two tests that decide whether a path is worth exposing
Run each template through two questions. Both have to pass.
Test 1: does a single URL under this path answer a question completely, without the rest of the site? Retrieval systems split pages into chunks and rank the chunks, so a URL that only makes sense inside a browsing session has nothing to contribute. A glossary term passes. A category archive doesn't. There's more on how that splitting works in how AI answer engines break a page into retrieval chunks.
Test 2: would a quote from this path still be true and safe ninety days from now? Retrieval indexes lag. Anything you expose can be repeated back with your brand attached long after you changed it. Price pages and spec tables pass this test only if you accept that a stale figure will surface at some point.
Paths that clear both, on a typical content site:
| Path prefix | What lives there | Complete on its own | Still true in 90 days | Decision |
|---|---|---|---|---|
| `/blog/` | evergreen articles | Yes | Mostly | Open |
| `/guides/` | long-form how-to | Yes | Yes | Open |
| `/docs/` | product documentation | Yes, per page | Only the current version | Open the current path, close archived versions |
| `/glossary/` | one term per URL | Yes | Yes | Open, and this is the highest-yield path on most sites |
| `/compare/` | X versus Y pages | Yes | Only if you maintain them | Open, and put a review date on the template |
| `/pricing/` | public plans | Yes | Changes | Open, accepting that stale numbers will be quoted |
| `/about/`, `/contact/` | entity facts | Yes | Yes | Open, this is how an assistant learns who you are |
| `/case-studies/` | published results | Yes | Yes | Open once cleared by whoever owns the client relationship |
The glossary row isn't filler. Definitional pages are the cheapest citations available: one URL, one question, one answer, no navigation required to make sense of it. If your template inventory has no glossary and no docs, that's a content gap robots.txt cannot fix. What earns the citation once the door is open is covered in how AI assistants pick their sources.
Stuck on page two?
Real human clicks that lift your CTR and move you up the rankings.
Paths that should never be quoted
The instinct is to sort paths into public and private. Wrong axis. Almost everything in the table below is technically public. The reason to close it is that a quote from it would be wrong, thin, or somebody else's words wearing your domain name.
| Path | Why it fails | What a bad quote looks like |
|---|---|---|
| `/checkout/`, `/cart/` | Session-bound, no content, often just a redirect target | An assistant describing your checkout from an empty-cart state |
| `/account/`, `/orders/` | Auth-gated, and error or preview states sometimes render publicly | Field labels and error copy quoted as product documentation |
| Internal search results | Infinite URL space, thin output, and the text is whatever a stranger typed | Your domain quoted saying a phrase nobody at your company wrote |
| `/tag/`, deep pagination | Lists of titles with no answer in them | A title list surfaced as the answer, competing with the real article |
| `/preview/`, `/staging/` | Unfinished drafts and abandoned positions | A killed draft quoted as your current position |
| `/members/`, `/download/` | Paid or email-gated | Free redistribution of the thing people pay for |
| `/go/`, `/out/` | Redirect endpoints with no body | Partner destinations surfaced as your content |
| Parameter variants | Duplicates of pages you already opened | The worst-rendered version of a good page |
Internal search deserves its own paragraph, because it's the path people leave open by accident. A search results page publishes user input under your domain. Anyone can request /search?q= followed by any phrase they like, get it rendered inside your header and footer with your logo above it, then link to that URL from somewhere a crawler will find. If a retrieval agent is allowed on that path, the phrase becomes a chunk attributed to your site. No exploit is involved and there's nothing to patch. The fix is one Disallow line, and it belongs in every group in the file.
Deep pagination and thin tag archives fail for a duller reason. They're real pages with real content, but the content is a list of headlines. A retrieval index doesn't know a listing page from an article. It knows this URL on your domain mentions the query term nine times, which turns the listing page into a direct competitor of the article you wanted cited.
How Allow and Disallow precedence is actually resolved
This is where most circulating AI crawler templates fall apart, and it's mechanical enough to check by hand.
Two rules, both documented in Google's robots.txt specification and consistent with RFC 9309, the Robots Exclusion Protocol standard published in September 2022:
- The rule that applies is the most specific match, measured by the number of characters in the rule's path, wildcards included.
- When two rules are the same length, the least restrictive one wins, which means
AllowbeatsDisallow.
Google's own worked cases, worth memorizing because every argument about robots.txt collapses into one of them:
| Rules in the file | URL requested | Rule that applies | Why |
|---|---|---|---|
| `Allow: /p` and `Disallow: /` | `/page` | `Allow: /p` | 2 characters beats 1 |
| `Allow: /folder` and `Disallow: /folder` | `/folder/page` | `Allow: /folder` | Same length, least restrictive wins |
| `Allow: /page` and `Disallow: /*.htm` | `/page.htm` | `Disallow: /*.htm` | 6 characters beats 5 |
| `Allow: /page` and `Disallow: /*.ph` | `/page.php5` | `Allow: /page` | Same length, least restrictive wins |
| `Allow: /$` and `Disallow: /` | `/` | `Allow: /$` | 2 characters beats 1 |
| `Allow: /$` and `Disallow: /` | `/page.htm` | `Disallow: /` | `/$` matches the root only |
Source: Google Search Central, robots.txt specifications. Two wildcards are supported, for zero or more of any character and $ for end of URL. A trailing is ignored, so /blog/* and /blog/ are the same rule.
The consequence nobody states
Allow: is not how you grant access. Access is the default. A path with no matching rule is crawlable. Allow exists for exactly one job: carving an exception out of a broader Disallow you wrote yourself.
That matters because the AI crawler snippets people copy are full of decorative Allow lines, and those lines aren't inert. They compete. Here's a template that looks careful and isn't:
User-agent: PerplexityBot
Allow: /blog/
Allow: /guides/
Disallow: /*?
Disallow: /search
Resolve /blog/organic-ctr-benchmark/?utm_source=newsletter against it. Allow: /blog/ is 6 characters. Disallow: /*? is 3. The Allow wins, so every tracked, sorted and paginated variant of every article stays open. The author believed they had closed the parameter space. They opened it, with a line they added for reassurance.
Two fixes, and the first is better:
- Delete the
Allowlines./blog/and/guides/were never disallowed, so nothing changes except thatDisallow: /*?now applies to them. - Or out-specify them.
Disallow: /blog/*?is 8 characters and beatsAllow: /blog/at 6. Use this only when the Allow is doing real work.
The other prefix trap
Disallow: /search is a prefix match on the path, not a directory match. It blocks /search?q=ctr, and it also blocks /search-experience/, /search-console-guide/ and anything else that starts with those seven characters. On a site that writes about search, that's a meaningful slice of the library gone, silently.
If any of your slugs start with a blocked word, write the two precise forms instead:
Disallow: /search?
Disallow: /search/
Run the same check on /tag, /go, /api and /print. One of them usually collides with a real article slug.
A worked robots.txt, line by line
A small content site with a blog, guides, a glossary, a members area holding one free sample, an internal search and a store. The stance on training agents was settled in the decision post, so it sits in its own group at the bottom and doesn't get re-argued here.
# https://www.sparkcliks.com/robots.txt
# These rules apply to this host and this scheme only. An apex domain
# or an http variant that also serves the site needs its own copy.
# Group 1: every crawler not named in another group.
User-agent: *
Disallow: /account/
Disallow: /checkout/
Disallow: /cart/
Disallow: /search?
Disallow: /search/
Disallow: /preview/
Disallow: /go/
Disallow: /*?
# Group 2: AI retrieval and user-triggered fetch agents.
# Repeated in full, because a named group inherits nothing from *.
User-agent: OAI-SearchBot
User-agent: ChatGPT-User
User-agent: Claude-SearchBot
User-agent: Claude-User
User-agent: PerplexityBot
User-agent: Perplexity-User
Disallow: /account/
Disallow: /checkout/
Disallow: /cart/
Disallow: /search?
Disallow: /search/
Disallow: /preview/
Disallow: /go/
Disallow: /tag/
Disallow: /members/
Allow: /members/sample/
Disallow: /members/sample/*?
Disallow: /*?
# Group 3: training-only agents. Your stance from the decision post lives here.
User-agent: GPTBot
User-agent: ClaudeBot
User-agent: CCBot
Disallow: /
Sitemap: https://www.sparkcliks.com/sitemap.xml
The reasoning, for every line that isn't self-explanatory:
| Line | What it does | Why it reads that way |
|---|---|---|
| No `Allow: /blog/` anywhere | Nothing, deliberately | `/blog/` is never disallowed, so it's already open. Adding the line would out-specify `Disallow: /*?` and reopen every tracked URL |
| `Disallow: /search?` plus `/search/` | Blocks the results page in both forms | The shorter `Disallow: /search` would also swallow `/search-experience/` |
| `Disallow: /tag/` in group 2 only | Search crawlers keep the tag archives, AI agents don't | Tag pages help human browsing and discovery. They hand a retrieval index a title list that competes with the article |
| `Disallow: /members/` in group 2 only | Search crawlers still index the gated page, AI agents can't read it | You want the page findable. You don't want the paid chapter reproduced inside an answer |
| `Allow: /members/sample/` | Carves the free sample back out | 16 characters, beats `Disallow: /members/` at 9. This is the only Allow in the file and it's earning its place |
| `Disallow: /members/sample/*?` | Closes the parameter variants of that sample | 18 characters, beats the Allow at 16. Without it, `/members/sample/?ref=x` stays open, because the Allow out-specifies `Disallow: /*?` |
| `Disallow: /*?` | Every URL carrying a query string | Kills tracked variants, sort and filter views, and pagination in one rule. The canonical article is untouched |
| Group 3 restated in full | The training stance | A named group inherits nothing, so `Disallow: /` here has to be complete on its own |
| `Sitemap:` outside every group | Applies file-wide | It isn't a group directive. Position doesn't change its meaning, but keep it at the bottom so nobody reads it as part of group 3 |
Two limits worth knowing before the file grows. Google enforces a 500 kibibyte cap on robots.txt and ignores everything past it, and it generally caches the file for up to 24 hours. A change you push at 9am is not a change that's in effect at 9:05.
Blocking a path does not remove what was already ingested
robots.txt governs the next fetch. It's not a delete request, and the format has no directive that means "forget what you already have."
Split by where the copy actually lives:
| Where the content is | Does a new Disallow remove it | What actually changes it |
|---|---|---|
| A retrieval index, the thing that produces citations | No | Change or remove the page and leave it crawlable so the update gets picked up. A 404 or 410 drops it on the next fetch |
| Model weights from a completed training run | No, and nothing else does either | Nothing addressable. Vendor opt-outs apply to future runs |
| Third-party archives and mirrors | No | Their own removal process, where one exists |
| Someone else's article quoting you | No | Not a crawler problem at all |
The counterintuitive part, and the one that costs people the most time: to get a wrong answer corrected, you have to leave the door open. If a retrieval index holds a page saying something you no longer want quoted, and you respond by adding Disallow: for that path, you've frozen the last version the crawler saw. The agent can't re-fetch, so it can't discover the page changed. The sequence that works is: fix the page, keep it crawlable, wait for a re-crawl, confirm in your logs that the new version was fetched, and only then decide whether the path still needs closing.
Nobody publishes a service level agreement on re-crawl timing for these agents, and neither will this post. Watch your access log for the next hit on that URL and treat that as your clock.
robots.txt, noindex and per-page AI controls are three layers
These three get used interchangeably in conversation and they do genuinely different jobs. For AI search, the distinction that matters most is the last column.
| Control | Where it lives | What it stops | Page must stay crawlable |
|---|---|---|---|
| `Disallow` | robots.txt, per host and scheme | A compliant agent fetching the URL at all | No, this is the thing that stops crawling |
| `noindex` | Meta robots tag or `X-Robots-Tag` header | The page entering the search index | Yes |
| `nosnippet` | Meta robots tag or header | Snippet text being shown, and the page being used as direct input for AI Overviews and AI Mode | Yes |
| `max-snippet:[n]` | Meta robots tag or header | Anything past n characters being shown or used as direct input | Yes |
| `data-nosnippet` | An HTML attribute on one element | That element only. The rest of the page stays eligible | Yes |
| `Google-Extended`, `Applebot-Extended` | robots.txt user-agent tokens | That vendor's non-search AI uses | Not applicable |
Google's robots meta tag documentation was updated to state that nosnippet and max-snippet apply to AI Overviews and AI Mode as well as ordinary results, which makes them the only per-page instrument that speaks to an AI surface. The trade is blunt: nosnippet also removes your ordinary search snippet.
The asymmetry is the point of this section. Per-page AI controls are a Google-only lever. OpenAI, Anthropic and Perplexity document robots.txt user-agent tokens and nothing per-page. For those agents, path-level control in robots.txt is the entire toolbox, which is why the inventory you built in section one carries so much weight.
There's also a trap that mirrors the classic robots.txt versus noindex problem, one layer up: a Disallow on a path stops the crawler from reading the nosnippet on that path. If your goal is "indexed, ranking, not used as AI input," the page has to stay crawlable and carry nosnippet. Blocking it in robots.txt gets you neither result cleanly. The full mechanic, including why blocked pages still show up in results, is in robots.txt vs noindex.
Two things are moving and neither is a control you can ship today. Cloudflare's Content Signals Policy, launched in September 2025, adds search, ai-input and ai-train signals as a comment block inside robots.txt and is deployed across a large number of domains, but no crawler operator has committed to honoring it. The IETF AIPREF working group is drafting a shared vocabulary for the same idea, and as of 2026 the attachment specification that would carry it in robots.txt still hasn't shipped as a standard. Treat both as directional. A related file that does exist and is worth understanding sits in llms.txt explained.
Verify what a given agent can actually reach
Writing the file is the easy half. Here's the check, worked against the file above.
Step 1: resolve a representative URL for every template
One URL per template from your section-one inventory, resolved by hand against each group. Do it in a spreadsheet. It takes about fifteen minutes and it's the only way to catch a precedence surprise before a crawler does.
| Representative URL | Group 1 (`*`) | Group 2 (AI retrieval) | Group 3 (training) |
|---|---|---|---|
| `/blog/organic-ctr-benchmark/` | Allowed | Allowed | Blocked |
| `/blog/organic-ctr-benchmark/?utm_source=newsletter` | Blocked by `/*?` | Blocked by `/*?` | Blocked |
| `/glossary/dwell-time/` | Allowed | Allowed | Blocked |
| `/search-experience/` | Allowed | Allowed | Blocked |
| `/search?q=ctr` | Blocked | Blocked | Blocked |
| `/tag/ctr/` | Allowed | Blocked by `/tag/` | Blocked |
| `/members/sample/chapter-1/` | Allowed | Allowed by the 16-character Allow | Blocked |
| `/members/full/chapter-4/` | Allowed | Blocked by `/members/` | Blocked |
| `/checkout/step-2/` | Blocked | Blocked | Blocked |
Read the /members/ and /tag/ rows carefully. Group 1 and group 2 disagree on purpose, and that disagreement is the entire reason to write a second group. If your two groups never differ on any row, you didn't need the second group.
Step 2: confirm the file is served on every host and scheme
Rules apply only to the host, protocol and port that served the file. A site reachable at both the apex and the www subdomain is two robots.txt files unless one redirects to the other.
for h in https://www.sparkcliks.com https://www.sparkcliks.com http://www.sparkcliks.com; do
printf '%s ' "$h"
curl -s -o /dev/null -w '%{http_code} %{content_type} %{redirect_url}\n' "$h/robots.txt"
done
You want a 200 with text/plain on the canonical host and a redirect to it from the others. A 200 serving your HTML 404 page is the common failure, and a crawler that reads HTML where rules should be treats the whole site as allowed.
Step 3: read the access log by path, not by agent
The decision post covers counting hits per agent. The question here is different: of the paths you opened, which ones are the agents actually fetching? That's the only evidence that your intent and your file agree.
grep -E 'OAI-SearchBot|Claude-SearchBot|PerplexityBot|ChatGPT-User' access.log \
| awk '{print $7}' \
| sed -E 's/\?.*//' \
| cut -d/ -f1-2 \
| sort | uniq -c | sort -rn | head -20
Read the output against your intent. A closed path showing up means the rule didn't resolve the way you thought, so take that URL back to step 1. A path you opened and cared about showing zero hits across 30 days is a sitemap and internal linking problem, not a robots.txt problem. One caveat: a user agent string is text anyone can send, so check the source address against the vendor's published ranges before concluding anything from a surprising hit.
Step 4: use the Search Console robots.txt report for the parse check
In Google Search Console, open Settings, then robots.txt. It lists the files fetched for your property, the last fetch time, the served status and any parse issues. Use it to confirm the file is syntactically clean and being read, not to answer questions about other agents. There's no console for OAI-SearchBot or PerplexityBot, so your own access log is the only ground truth for those.
Mistakes that quietly undo the whole file
Ranked by how often they turn up in a real file:
- Decorative
Allow:lines. They grant nothing and out-specify the Disallow rules you needed. - Prefix collisions. Check every short Disallow against your real slug list.
- Blocking a path, then expecting the tags on it to work. A blocked page's
noindex,nosnippetand canonical are all unreadable. - Only one host covered. The apex serves its own robots.txt, or the http variant does, and neither one got the rules.
- Blocking
/assets/or/wp-content/. Retrieval agents that render before chunking need the stylesheet and the script. Block those and your page gets evaluated as an unstyled column of text. - A Disallow line that publishes the path. robots.txt is public and people read it. Writing
Disallow: /internal-pricing-2027/tells the world that directory exists. Anything that genuinely must not be reached needs authentication, not a line in a public text file. - Trailing wildcards mistaken for precision.
/blog/*is the same rule as/blog/. If you wrote the star to mean something, it didn't.
Run this against your own file
- [ ] Every template from your inventory has a resolved verdict in every group.
- [ ] No
Allow:line exists unless it carves an exception out of aDisallowin the same group. - [ ] Every short
Disallowhas been checked against the slug list for collisions. - [ ] Internal search is blocked in every group, in both the
?and/forms. - [ ] Parameter and pagination URLs are closed for the AI groups.
- [ ] Group 1 and the AI group differ on at least one row, or the second group is pointless.
- [ ] Every host and scheme that serves the site either serves this file or redirects to it.
- [ ] The file is under 500 KiB and returns 200 with
text/plain. - [ ] Anything that must stay private is behind authentication, not behind a Disallow.
None of this guarantees a citation. Being reachable is a precondition, not a cause. What it buys you is that when an assistant does quote your domain, it's quoting a page you picked.
Frequently asked questions
FAQ
Create one group listing the retrieval agents you're allowing, then put a Disallow line for each private path inside that group. Don't add Allow lines for the public paths: paths with no matching rule are already crawlable, and the extra lines can override the Disallow rules you meant to keep.
No. Crawling is the default, so Allow only matters as an exception carved out of a Disallow in the same group. A stray Allow: /blog/ sitting next to Disallow: /*? reopens every tracked and paginated URL under /blog/, because the longer path pattern wins.
No. robots.txt governs the next fetch, not existing copies. Worse, blocking the path stops the agent from re-fetching, which freezes whatever version it already holds. To correct a wrong answer, fix the page and keep it crawlable until you've seen the re-fetch land in your logs.
Yes, in every group. A search results page renders whatever a stranger typed inside your branded template, so leaving that path open lets a phrase you never wrote become a chunk attributed to your domain. Block both /search? and /search/ so you catch the query form and the directory form.
Disallow stops the fetch, noindex keeps a fetched page out of the search index, and nosnippet keeps a fetched, indexed page from being shown as a snippet or used as direct input for AI Overviews and AI Mode. The last two need the page to stay crawlable, and nosnippet is a Google control with no documented equivalent at OpenAI, Anthropic or Perplexity.
Filter your server access log by those user agent strings, strip the query string, group the results by path prefix, then compare that list against the paths you meant to open. There's no Search Console equivalent for non-Google agents, and user agent strings can be forged, so confirm surprising hits against each vendor's published address ranges.
Related articles

How to Check If AI Crawlers Can Read Your Page
Check if AI crawlers can read your page with seven exact commands: raw HTML versus rendered DOM, per agent robots.txt, edge blocks, consent walls and logs.

How to Keep Brand Entity Consistency Across Profiles
Brand entity consistency decides whether an answer engine can tell who you are. The full conflict surface, a one hour audit, and the order to fix things in.

Self-Contained Answer Blocks That Survive Extraction
Write self-contained answer blocks that survive extraction: lead with the answer, resolve pronouns, name the entity, and make every passage quotable on its own.
