Skip to main content

ai-crawler-robots

A robots.txt that looks right and blocks nothing is the normal failure. This package reads the file you already have and tells you which of the 56 AI crawlers it actually stops.

from ai_crawler_robots import lint, audit, is_allowed

lint(open("robots.txt").read())
# [{'level': 'error', 'line': 3, 'code': 'ua-is-not-a-token',
#   'message': 'User-agent takes a product token, not a full user-agent string. '
#              'This group matches no crawler.',
#   'found': 'Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)',
#   'fix': 'User-agent: GPTBot'}]

is_allowed(text, "GPTBot", "/blog/post")
# {'allowed': False, 'rule': 'Disallow: /blog', 'line': 8, 'group': 'GPTBot', ...}

audit(text)["blocked"]        # ['anthropic-claudebot', 'openai-gptbot', ...]
audit(text)["unenforceable"]  # crawlers that will not obey it whatever it says

Install

pip install ai-crawler-robots

Python >= 3.8. Zero dependencies, standard library only. No network at import: 56 crawler records and 8 ready-made stances ship inside the wheel (68.1 KB), snapshot taken 2026-09-01.

Nothing in this package fetches a URL. There is no argument anywhere that takes one. refresh() is the only call that touches the network, you have to name it, and it fetches exactly one document: the same data.json that ships in the wheel.

The faults it finds

The most common robots.txt failure is not a syntax error — it is a file that a person reads as correct and a parser reads as empty. 23 checks, of which these are the ones that cost real traffic:

code what it means
user_agent_is_a_ua_string User-agent: carrying a whole browser-style string. RFC 9309 matches a product token; that group matches nothing.
unknown-token a token no crawler in the table sends — usually a typo, ChatGPT-user for ChatGPT-User, or a name somebody invented
duplicate_group a second group for the same token; only the first one applies, the rest is decoration
noindex_in_robots Noindex: in robots.txt. Google stopped honouring it on 1 September 2019 and it never worked anywhere else.
unenforceable the rule is correct and the operator states robots.txt does not apply to that fetcher. You need an edge rule, and this says so.
crawl_delay Crawl-delay: is not in RFC 9309 and Google, OpenAI and Anthropic all ignore it
path_without_slash Disallow: admin does not match /admin
html_response / empty / bom the file never parsed at all

Every finding carries a line number, what was found, and a fix string you can paste.

Command line

ai-crawler-robots lint robots.txt                       # the faults, worst first
ai-crawler-robots audit robots.txt                      # every AI crawler: blocked / allowed / unenforceable
ai-crawler-robots check robots.txt --agent GPTBot --path /blog/
ai-crawler-robots diff old.txt new.txt                  # what changed by effect, not by text
ai-crawler-robots policy block-ai-training              # print a ready-made stance
ai-crawler-robots policy block-ai-training --merge robots.txt
ai-crawler-robots explain GPTBot                        # who it is, what blocking costs

lint exits 1 when it finds an error, 0 otherwise, so it works as a CI gate:

ai-crawler-robots lint robots.txt --strict || exit 1

audit — the question people actually have

$ ai-crawler-robots audit robots.txt
robots.txt: 56 crawlers, 12 blocked, 39 allowed, 5 unenforceable

BLOCKED (12)
  openai-gptbot            GPTBot              OpenAI       ai-training
  anthropic-claudebot      ClaudeBot           Anthropic    ai-training
  ...
ALLOWED, AND YOU PROBABLY MEANT TO BLOCK (7)
  google-extended          Google-Extended     Google       ai-training
  ...
UNENFORCEABLE BY robots.txt (5)
  These fetch on behalf of a user in a live session. Their operators state
  robots.txt does not govern them. Blocking needs an edge rule.

The third group is the one that surprises people. A user-triggered fetcher is not a crawler, most operators say so in their own documentation, and a Disallow aimed at one is a line that will never fire.

diff — did that edit do anything?

$ ai-crawler-robots diff robots.old robots.new
2 crawler(s) changed verdict for /
  google-extended     allowed -> blocked
  meta-externalagent  allowed -> blocked
44 unchanged. Formatting-only changes are not reported.

Compares by effect. Reordering groups, changing whitespace and rewriting comments produce an empty diff, because none of them change what a crawler does.

Ready-made stances

8 of them, the same bodies published at the index:

  • allow-all — Every crawler on this index is named and allowed. Use when you want maximum reach into search and assistants and have nothing to withhold
  • block-ai-training — Refuse the crawlers that feed model training. Keep the ones that put you in ChatGPT, Claude, Perplexity and Gemini answers
  • block-all-ai — Training, AI search, user-triggered fetches and corpus builders, all refused. Classic search engines still allowed
  • block-datasets — Refuse the crawlers whose output is a dataset other people train on: Common Crawl, AI2, Webz.io, Diffbot, ImagesiftBot
  • allow-ai-search-only — Be findable and citable in assistants without contributing to training corpora
  • block-seo-tools — Ahrefs, Semrush and friends. No user-facing consequence, and often the largest single slice of your bot traffic
  • block-disputed — The ones repeatedly reported as ignoring robots.txt. Included for completeness — expect to enforce this at the edge instead
  • maximum-ai-visibility — Allow every AI crawler and every search engine; refuse only SEO scrapers. For sites whose goal is to be found and cited by machines

--merge adds a stance to an existing file without touching the groups already in it, so your Googlebot rules survive.

Where the data comes from

The AI Crawler Index — an independent, non-commercial public reference. Every crawler record links to the operator's own documentation, and explain prints that link. Presence in the table means the operator documents that crawler; it is not an opinion about whether you should allow it.

refresh() fetches today's table and caches it six hours, which is how often the index behind it is rebuilt:

from ai_crawler_robots import refresh
refresh()   # {'crawlers': 56, 'generated_at': '...'}

Companion packages

Same table, different questions:

  • ai-crawler-index — what does this user-agent claim to be?
  • ai-crawler-verify — is that claim true? Checks the address against the operator's published ranges.
  • ai-crawler-logs — who was actually in your access log, and what to paste to act on it.

Licence

Code MIT. Bundled data CC0-1.0. Independent and non-commercial; not affiliated with, endorsed by or speaking for any crawler operator named in the table.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ai_crawler_robots-1.0.0.tar.gz (34.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ai_crawler_robots-1.0.0-py3-none-any.whl (32.9 kB view details)

Uploaded Python 3

File details

Details for the file ai_crawler_robots-1.0.0.tar.gz.

File metadata

  • Download URL: ai_crawler_robots-1.0.0.tar.gz
  • Upload date:
  • Size: 34.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.2

File hashes

Hashes for ai_crawler_robots-1.0.0.tar.gz
Algorithm Hash digest
SHA256 9b45402eb1f144fb2d127f1bd1d0dd40415cc3f2c8254fb6dd12870aea301f84
MD5 004275ac58fbb830d4147f39dd2d9985
BLAKE2b-256 e034a187368fd48760c7667126bcb7489dae8d4947e3798b57f7d4ab0eaf0a58

See more details on using hashes here.

File details

Details for the file ai_crawler_robots-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for ai_crawler_robots-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e0c7bfe828230094dbadcb13d0385e75994f450bdad827d6e6f91c40622f351d
MD5 cd93b330786b41ef02b511b9814804cb
BLAKE2b-256 ebdb0fc9548e2ab53a95862e3e74b994ad1ea1ef1f9e3b66ed91ff331099846e

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page