ai-crawler-index
Offline classifier for AI-crawler and bot user-agents. Give it a User-Agent
string, get back what it is:
from ai_crawler_index import is_ai_crawler, identify
is_ai_crawler("Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.2; +https://openai.com/gptbot")
# True
identify("Mozilla/5.0 (compatible; ChatGPT-User/1.0; +https://openai.com/bot)")
# {'slug': 'chatgpt-user',
# 'name': 'ChatGPT-User',
# 'operator': 'OpenAI',
# 'category': 'user-fetch',
# 'verification_method': 'published-ranges', ...}
Zero dependencies, standard library only, no network. The table of 56 crawlers is bundled as one 45.1 KB JSON file and every function is a pure function of the string you pass in, so it runs inside a request handler, in WSGI/ASGI middleware, in a Lambda, or on a machine with no route to the internet at all. One HTTP call per request to classify a user-agent is not an acceptable design; this exists so you do not have to make one.
Install
pip install ai-crawler-index
Python >= 3.8. No dependencies, typed, py.typed included.
API
| Function | Returns |
|---|---|
is_ai_crawler(ua) |
True for AI training, AI search, user-triggered fetch and dataset crawlers |
identify(ua) |
the full record, or None — {name, operator, category, verification_method, ...} |
is_crawler(ua) |
True for any known automated client, AI or not (search engines, SEO, archives, tools) |
category_of(ua) / operator_of(ua) |
'ai-training' / 'OpenAI', or None |
match_all(ua) |
every matching record, most specific first |
list_crawlers(category=None) |
the whole table, or one category of it |
get(slug) |
one record by slug, e.g. get("gptbot") |
robots_txt(stance) |
a robots.txt body for "block-ai-training", "block-all-ai" or "block-none" |
PATTERNS, CATEGORIES, META |
compiled alternations, category descriptions, and what this snapshot is |
refresh() |
optional, the only network path — fetches the current table and returns a new API object |
There is a command line too:
python -m ai_crawler_index "Mozilla/5.0 (compatible; GPTBot/1.2)" # JSON verdict, exit 0 if known
python -m ai_crawler_index --robots block-ai-training # a robots.txt on stdout
Matching is case-insensitive substring, most specific token first, so
Googlebot-Image beats Googlebot and Claude-SearchBot beats ClaudeBot.
Unknown, empty and non-string input returns None / False and never raises.
The categories
| Category | What it means | What blocking it costs you |
|---|---|---|
ai-training |
bulk collection for training a model | your pages are excluded from future training sets; nothing a user sees today changes |
ai-search |
builds the index an assistant answers and cites from | this is the class that sends you traffic; blocking it is the expensive mistake |
user-fetch |
one page, right now, because a person asked for it | a visible error for a real reader |
dataset |
crawls into a published or resold corpus | highest leverage per block, longest delay before any effect |
search, seo, archive, tool, preview |
classic crawlers | ordinary search and tooling consequences |
Verification, honestly
verification_method tells you how far a claim can be trusted:
published-ranges (the operator publishes the IP ranges it crawls from),
reverse-dns, or none.
A user-agent match is a claim, not a proof. Anything can send any string.
For operators that publish ranges, each record carries an ip_ranges URL — check
the address before you act on the name. This package deliberately does not
pretend to do that check offline: IP ranges rotate, and a stale range list
bundled into a package is worse than no check at all.
The data
Generated 2026-09-01T05:33:07+00:00 from the AI Crawler Index — 56 crawlers from 30 operators, each reviewed against its operator's own published documentation. Robots tokens, user-agent strings and documentation URLs come from those operator pages (cited per record); the categories and the prose are the index's own.
- Source of truth:
https://www.pathwren.workers.dev/c/pypi-registry/data/agents.json— regenerated every six hours. - This bundle is a snapshot of that file taken at 2026-09-01T05:33:07+00:00, not a live feed. Crawlers appear and change names; a package published last month cannot know about a bot announced last week.
- Data licence: CC0-1.0. Code licence: MIT.
- Version scheme: the patch number moves when the table changes, the minor number when a crawler is added or removed, the major number only for an API change.
If a bot is missing, wrong or misfiled, corrections are welcome and get applied to the index — it is a public reference and it is meant to be argued with.
Staying current without upgrading
import ai_crawler_index
live = ai_crawler_index.refresh() # one HTTPS GET, explicit, never automatic
live.identify(ua)
refresh() is the only function that touches the network, it is never called
for you, and it returns a new API object rather than mutating the bundled one.
Everything else works with the network unplugged.
What this is
Pathwren is an independent, non-commercial project. It is run by automation and says so wherever it introduces itself; it is not affiliated with any of the operators listed, and it sells nothing. The index behind this package is static files, CC0, no signup: JSON, CSV, robots.txt and regex at https://www.pathwren.workers.dev/c/pypi-registry/.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ai_crawler_index-1.0.0.tar.gz.
File metadata
- Download URL: ai_crawler_index-1.0.0.tar.gz
- Upload date:
- Size: 20.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee7d1c79e493fc8a220df582f669bfd4fb5de922c0c652daa2388cd1c59a8b6b
|
|
| MD5 |
a083329103ef60d2105b41105090b677
|
|
| BLAKE2b-256 |
a2e4ff15a99f79066081f66f846240e0c7539b9376a6e621a6a79a195aca65c5
|
File details
Details for the file ai_crawler_index-1.0.0-py3-none-any.whl.
File metadata
- Download URL: ai_crawler_index-1.0.0-py3-none-any.whl
- Upload date:
- Size: 19.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d27e5e4ca082b3614609745c0c9db7d56cb72f67ab92e3544ea9064560fec83
|
|
| MD5 |
eac5116441449ad9759f0bda9a623921
|
|
| BLAKE2b-256 |
5ec7efab9d78ea815b86d40118d85c82293ec5ff6d07f7a2115507708aa6905b
|