Bots & traffic

8 min readUpdated

How to block AI crawlers: robots.txt, server rules and IP checks

Quick answer

To block AI crawlers, list each operator's documented token in robots.txt under Disallow: /, for example GPTBot, ClaudeBot, Google-Extended, Applebot-Extended, CCBot and meta-externalagent, and leave search crawlers allowed. robots.txt is a request, not enforcement: some user-triggered fetchers may ignore it, so refuse those agents at the server too, keep robots.txt itself reachable, and check claimed crawlers against the operators' published IP ranges.

01Which AI crawlers are there? The tokens, checked October 2026

Each AI operator documents its own tokens, and most now run separate bots for training, search and user-triggered fetching, so the first decision is which of those to refuse. The table records what each operator's own documentation said in October 2026. Tokens change, so recheck the sources before relying on it.

Two entries are not crawlers. Google-Extended and Applebot-Extended are robots.txt tokens only: Google and Apple crawl with Googlebot and Applebot and use the token to decide how the content may be used. Both companies say these tokens do not affect inclusion in their search results.

TokenOperatorPurposeFollows robots.txt?Published IP list
GPTBotOpenAIContent that may be used to train its modelsYesopenai.com/gptbot.json
OAI-SearchBotOpenAIResults in ChatGPT searchYes, within about 24 hoursopenai.com/searchbot.json
ChatGPT-UserOpenAIPages fetched when a user asksRules may not apply, says OpenAIopenai.com/chatgpt-user.json
ClaudeBotAnthropicContent that could contribute to model trainingYesclaude.com/crawling/bots.json
Claude-SearchBotAnthropicIndexing to improve search resultsYesThe same list
Claude-UserAnthropicPages fetched for a user's questionYesThe same list
Google-ExtendedGoogleToken: use in Gemini model training and groundingYes, as a tokenGooglebot's ranges
Applebot-ExtendedAppleToken: use in Apple foundation model trainingYes, as a tokenApplebot's list
PerplexityBotPerplexitySearch results; not used for model training, says PerplexityYesperplexity.com/perplexitybot.json
Perplexity-UserPerplexityPages fetched for a user's questionGenerally ignores it, says Perplexityperplexity.com/perplexity-user.json
CCBotCommon CrawlAn open web archive that anyone can reuseYes, including Crawl-delayindex.commoncrawl.org/ccbot.json
BytespiderByteDanceSearch and AI model data, according to third-party directoriesNot verified: documented only on ByteDance's Chinese-language webmaster siteNot verified
meta-externalagentMetaTraining AI models and indexing contentYesNone on Meta's crawler page
meta-webindexerMetaResults and citations in Meta AI searchYesNone on Meta's crawler page
meta-externalfetcherMetaLinks fetched at a user's requestMay bypass it, says MetaNone on Meta's crawler page

02How to block AI crawlers in robots.txt

List the tokens to refuse in one group and give it Disallow: /. Several User-agent lines may share a group. RFC 9309 makes crawlers match their token case-insensitively and obey the group that names them, falling back to the * group only when none does, so search crawlers that are not listed keep following the * group.

Two details catch people out. robots.txt applies per host, so every subdomain needs its own file, as Anthropic's documentation points out. And changes are not instant: RFC 9309 lets crawlers cache the file for up to 24 hours, and OpenAI, Perplexity and Meta each mention a delay of about a day.

GoalTokens to disallowWhat still happens
Opt out of model training onlyGPTBot, ClaudeBot, Google-Extended, Applebot-Extended, CCBot, Bytespider, meta-externalagentAI search crawlers can still index the site and cite it
Opt out of AI search as wellAdd OAI-SearchBot, Claude-SearchBot, PerplexityBot and meta-webindexerOpenAI says opted-out sites can still appear as navigational links in ChatGPT
Refuse user-triggered fetches tooAdd ChatGPT-User, Claude-User, Perplexity-User and meta-externalfetcherSome of these may ignore robots.txt, so enforce at the server
robots.txt opting out of every AI crawler and fetcher in the table above (parsed with Python's urllib.robotparser: every listed agent refused; Googlebot, Bingbot and Applebot allowed)
# Opt out of the AI crawlers and fetchers in the table above (checked October 2026)
User-agent: GPTBot
User-agent: OAI-SearchBot
User-agent: ChatGPT-User
User-agent: ClaudeBot
User-agent: Claude-SearchBot
User-agent: Claude-User
User-agent: Google-Extended
User-agent: Applebot-Extended
User-agent: PerplexityBot
User-agent: Perplexity-User
User-agent: CCBot
User-agent: Bytespider
User-agent: meta-externalagent
User-agent: meta-externalfetcher
User-agent: meta-webindexer
Disallow: /

# Everyone else, search engines included
User-agent: *
Disallow: /account/

03What robots.txt cannot do

robots.txt states a preference that well-run crawlers honour. RFC 9309 says its rules 'are not a form of access authorization', and the protocol has several further limits.

  • It does not stop clients that ignore it, including user-triggered fetchers whose operators say robots.txt may not apply
  • It works only from now on: Anthropic, for example, describes a ClaudeBot block as excluding the site's future materials from training
  • It cannot reach copies held elsewhere, such as archives other crawlers already made or pages that users paste into an assistant
  • It does not stop impersonators or unnamed scrapers, which is why web scraping needs its own defences
  • A robots.txt that answers with a 5xx error tells every crawler, search engines included, to assume complete disallow, while a 4xx answer tells them they may crawl everything

04How to block AI crawlers in nginx

Server rules enforce what robots.txt only requests. A map in the http context sets a variable from the User-Agent header, and the location refuses matching requests with 403. The patterns are case-insensitive regular expressions, so the documented tokens match however an operator capitalises them.

Keep robots.txt itself outside the block. Under RFC 9309 a 4xx answer for robots.txt means the file is unavailable and crawlers may access everything, and Anthropic warns that blocking its crawlers' addresses stops them reading the opt-out. A refused robots.txt is therefore worse than none.

This works only for crawlers that announce themselves. Google-Extended and Applebot-Extended never appear in a User-Agent header, and refusing Googlebot or Applebot would remove the site from their search engines, so those two can be handled only in robots.txt.

Refusing AI training crawlers while keeping robots.txt reachable (checked with nginx -t and live requests on nginx 1.22.1)
# /etc/nginx/conf.d/ai-crawlers.conf (http context)
map $http_user_agent $ai_crawler {
    default               0;
    ~*GPTBot              1;
    ~*ClaudeBot           1;
    ~*CCBot               1;
    ~*Bytespider          1;
    ~*meta-externalagent  1;
    # add OAI-SearchBot, Claude-SearchBot, PerplexityBot, ChatGPT-User,
    # Claude-User, Perplexity-User, meta-externalfetcher or meta-webindexer to refuse them too
}

# in the server block
location = /robots.txt {
    try_files $uri =404;    # served to everyone, AI crawlers included
}

location / {
    if ($ai_crawler) {
        return 403;
    }
    # ... the site's normal configuration
}

05How to tell a real AI crawler from an impersonator

A User-Agent header proves nothing, so when one AI crawler is allowed and others are refused, check the address too. OpenAI, Anthropic, Perplexity and Common Crawl publish their ranges as JSON files with a creationTime field showing when each list was generated, and Common Crawl also supports reverse DNS under crawl.commoncrawl.org. The general method, including reverse DNS for search engines, is in the guide to verifying web crawlers, and an IP lookup shows which network an address belongs to.

The snippet below turns OpenAI's search crawler list into an nginx geo file and refuses requests that claim to be OAI-SearchBot from anywhere else. Regenerate the file on a schedule and reload nginx afterwards, because the lists change. Behind a CDN or load balancer, configure the realip module first, or every request appears to come from the proxy and the real crawler is refused as well.

Refusing OAI-SearchBot impersonators (tested on nginx 1.22.1 with requests from outside and, simulated, from inside the published ranges)
# 1. Build the geo file from OpenAI's published list (via a temporary file, so a failed download keeps the old list)
curl -fsS https://openai.com/searchbot.json | python3 -c 'import json,sys; [print(p.get("ipv4Prefix") or p.get("ipv6Prefix"), "1;") for p in json.load(sys.stdin)["prefixes"]]' > /etc/nginx/openai-searchbot.geo.new && mv /etc/nginx/openai-searchbot.geo.new /etc/nginx/openai-searchbot.geo

# 2. In the http context
geo $from_openai_search {
    default 0;
    include /etc/nginx/openai-searchbot.geo;
}
map $http_user_agent $claims_oai_search {
    default          0;
    ~*OAI-SearchBot  1;
}
map "$claims_oai_search:$from_openai_search" $fake_oai_search {
    default  0;
    "1:0"    1;
}

# 3. In location /
if ($fake_oai_search) {
    return 403;
}

06How to see which AI crawlers visit a site

Count them in the access log before and after a change: it shows whether the opt-out took effect and which agents ignore it. In nginx's default combined log format the User-Agent is the sixth field when a line is split on double quotes. OpenAI says it may add a robots.txt marker to its user-agent when it fetches that file, which makes those checks easy to spot.

Counting AI agents and the responses they received in a combined-format access log (tested with GNU awk 5.2.1)
# requests per AI agent (one count per request)
awk -F'"' '{ua = tolower($6)}
  match(ua, /gptbot|oai-searchbot|chatgpt-user|claudebot|claude-searchbot|claude-user|perplexitybot|perplexity-user|ccbot|bytespider|meta-externalagent|meta-externalfetcher|meta-webindexer/) {
    print substr(ua, RSTART, RLENGTH)
  }' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# what the training crawlers requested and the status they got
awk -F'"' 'tolower($6) ~ /gptbot|claudebot|ccbot|bytespider|meta-externalagent/ {split($3, s, " "); print $2, s[1]}' \
  /var/log/nginx/access.log | sort | uniq -c | sort -rn

07Why is an AI crawler still visiting?

SymptomLikely causeHow to checkFix
Visits continue for hours after the changerobots.txt is cached for up to 24 hoursLook for a fresh robots.txt fetch by that agent in the logWait a day before judging
Visits continue for daysA wrong or outdated token, or the rule sits in another host's robots.txtFetch robots.txt on the exact host and subdomain being crawledUse the operator's current token on every host
The agent's name arrives from addresses outside its listAn impersonatorCompare the address with the operator's JSON listRefuse it at the server or at the edge
ChatGPT-User, Perplexity-User or meta-externalfetcher still fetch pagesUser-triggered fetchers may not follow robots.txtTheir user-agent in the logRefuse them with a server rule if they are unwanted
Search traffic fell after the changeA search crawler was caught, for example by Disallow: / under *Crawl statistics in Google Search Console and Bing Webmaster ToolsDisallow only the AI tokens
Every crawler stopped, search includedrobots.txt returns a 5xx error, which means complete disallowcurl -sI https://example.com/robots.txtServe robots.txt as a static file that always answers 200
Crawlers ignore every rulerobots.txt is refused with 403, which means no rules applyThe status robots.txt returns to that user-agentExempt robots.txt from every block

08What a CDN or WAF can and cannot do about AI crawlers

An edge in front of the site can apply the same rules before requests reach the origin, check claimed crawlers against published ranges at scale, rate-limit the agents that are tolerated and serve them cached pages, so a heavy crawl costs the origin little. Bot management goes further, challenging clients that claim to be browsers but behave like scripts.

No edge does everything. It cannot recognise every undeclared scraper with certainty or recall content that was collected or copied earlier, and challenging all automation also catches assistants, accessibility tools and monitors that may be wanted. Blocking has a price too: OpenAI says sites that opt out of OAI-SearchBot are not shown in ChatGPT search answers, and Anthropic says blocking Claude-SearchBot or Claude-User may reduce visibility in its search results. Decide agent by agent, not all at once.

Questions

Frequently asked questions

No. Google says Google-Extended does not affect a site's inclusion in Google Search and is not a ranking signal. It controls only whether content Google crawls may be used to train Gemini models and to ground answers in Gemini apps and Vertex AI. Crawling itself is done by Googlebot, so Google-Extended can be set in robots.txt but not blocked at the server.

Not completely. Disallowing GPTBot tells OpenAI not to use the content for training, but OAI-SearchBot is a separate token for ChatGPT search, and ChatGPT-User fetches pages when a user asks, where OpenAI says robots.txt rules may not apply. Content collected before the change, or copied by others, is not affected either.

Anthropic documents three: ClaudeBot for collecting content that may be used in training, Claude-SearchBot for search indexing and Claude-User for pages fetched when a user asks Claude a question. Anthropic says its bots honour robots.txt and the non-standard Crawl-delay directive. Older tokens found in copied lists, such as anthropic-ai, are not on its current page.

Up to about a day. RFC 9309 says crawlers should not use a cached copy for more than 24 hours, and OpenAI, Perplexity and Meta each mention a delay of around 24 hours for their systems. If an agent is still crawling after that, check the token spelling, the host the rule sits on, and whether the visitor is an impersonator.

Yes, with most operators. OpenAI and Anthropic separate their training and search crawlers, and Perplexity says PerplexityBot is not used for training, so GPTBot and ClaudeBot can be disallowed while OAI-SearchBot, Claude-SearchBot and PerplexityBot stay allowed. Google-Extended and Applebot-Extended opt out of training without affecting ordinary search. Common Crawl has a single token for its whole archive.

Technically no: RFC 9309 says robots.txt rules are not a form of access authorisation, and some user-triggered fetchers say they may ignore them. In the EU, a machine-readable opt-out can matter under the text and data mining rules, and AI providers that sign the General-Purpose AI Code of Practice commit to crawlers that follow robots.txt. Enforce anything essential on the server.

Sources

Sources and verification

robots.txt parsed with urllib.robotparser from Python 3.11.2; nginx rules checked with nginx -t and live requests against a scratch nginx 1.22.1 instance (403 for listed agents, 200 for robots.txt and browsers, 403 for an OAI-SearchBot claim from outside the published ranges); log commands run with GNU awk 5.2.1 on a sample log; IP lists fetched from the operators and the geo file built with curl 7.88.1, including a failed download that left the previous list in place; Debian 12, October 2026.

  1. 01RFC 9309: Robots Exclusion Protocol · IETF
  2. 02Overview of OpenAI crawlers · OpenAI
  3. 03Does Anthropic crawl data from the web, and how can site owners block the crawler? · Anthropic
  4. 04Google's common crawlers: Google-Extended · Google for Developers
  5. 05About Applebot (including Applebot-Extended) · Apple
  6. 06Perplexity crawlers · Perplexity
  7. 07CCBot · Common Crawl
  8. 08Common Crawl FAQ (Crawl-delay support) · Common Crawl
  9. 09Meta web crawlers · Meta for Developers
  10. 10Bytespider (third-party agent directory) · Known Agents
  11. 11Directive (EU) 2019/790 on copyright in the Digital Single Market, Article 4 · EUR-Lex
  12. 12Code of Practice for General-Purpose AI Models: Copyright Chapter · European Commission
  13. 13Module ngx_http_map_module · nginx.org
  14. 14Module ngx_http_geo_module · nginx.org
  15. 15Module ngx_http_realip_module · nginx.org

Last updated