botTotals keyed by bot ID with an intent on each, and Export Page Analytics returns per-bot tier splits under pages[].bots — this endpoint tells you what those IDs and intents mean.
Programmatic (API key) access requires the Pro plan and above — requests
from Starter accounts return
403 plan_upgrade_required.Versioning
The taxonomy is published as numbered, immutable snapshots starting at1.0. Every response carries the version it came from and the date that version took effect.
A major bump is the signal that switching on
intent in your own code may need updating. A minor bump never changes the set of possible intent values.
Request
Headers
Body Parameters
Example Request
Current taxonomy:Response
Success (200)
intents and bots are two flat arrays joined on intent — bots are not nested under their bucket. Looking a bot up by the ID you got from an export is a direct index into bots; listing a bucket’s members is one filter on intent.
Fields
Buckets are returned in display order (AI intents first); bots are sorted by
botId.
Retired bots are included, not dropped. A bot we have stopped classifying stays in the payload with
isActive: false, so decoding an archived export never hits an ID that resolves to nothing. For “which bots can crawl my site today”, filter bots on isActive.AI intents.
isAiIntent is true for exactly training, answer-fetch, and search-index. That is the definition behind “AI crawl volume” in the dashboard: models reading your content. search-classic (Googlebot, Bingbot) is deliberately excluded — including it would drown the AI signal in ordinary organic crawling.Matching a User-Agent yourself
uaPatterns is the actual rule set we classify with, published so you can reproduce our attribution against your own access logs rather than taking the bot IDs on faith.
They are lowercased substrings, not whole User-Agent strings and not regular expressions. To match a request the way we do:
- Lowercase the request’s
User-Agent. - Find every bot with a pattern contained in it.
- The longest matching pattern wins. This matters:
googlebot-imageandgooglebotare separate bots, and a Googlebot-Image request contains both. Matching shortest-first would collapse the whole Google suite into one bucket. - No match → the hit is counted under the
unknownbot at theunknowntier. That entry is the synthetic catch-all, so itsuaPatternsis deliberately empty — it is the bucket you fall into, never one you match.
A UA match alone only establishes the
declared tier — anyone can send any User-Agent. Reaching verified additionally requires the source IP to check out, which is what verificationMethod describes below. If your own counts come out higher than ours, that difference is usually spoofed traffic we declined to attribute.Verification methods
verificationMethod is how a bot can reach the verified attribution tier. A bot with none can never be verified, so it will only ever appear as declared in your exports — that is expected, not a data quality problem.
Error Responses
Examples
JavaScript / Node.js
The version-aware pattern — fetch definitions only when the version changes, then decode an export’s bot keys into display names:A handful of bot keys on days before the legacy cutover are aggregates with no taxonomy entry and carry
"intent": null. Skip keys that don’t resolve, as the example above does.