1
Known agent or crawler
The request is matched against
agents.json in this order:- the
User-Agentheader; - an exact
Acceptfingerprint, compared ignoring case and spacing; - the
Signature-Agentheader, but only on requests that also carrySignatureandSignature-Input.
2
Asks for markdown
If
Accept ranks text/markdown or text/x-markdown above text/html, the request is an agent. Browsers never do this; AI tools that read pages do.3
Generic HTTP client or headless browser
The user agent is matched against
http-clients.json. A match is a bot, with kind http-client or headless.4
Browser
A user agent counts as a browser when all of these hold:
- it starts with
Mozilla/; - it carries a rendering-engine token such as
KHTML, like Gecko,Gecko/orTrident/; - it shows no sign of automation, such as a
bottoken, a URL, an email address, or a testing tool’s name.
human unless their headers contradict it (see below).5
Everything else
Anything else is a
bot with kind unidentified. That includes empty user agents, truncated browser strings and one-off scripts. unknown is reserved for requests with no user agent and no headers at all.Browser checks
Real browsers send a predictable set of headers. Many automated clients that borrow a browser user agent don’t. A browser user agent becomes afake-browser bot when:
Acceptrankstext/plainabovetext/html, or asks for metalink downloads. This is checked wheneverAcceptis present.- These three are checked only when you pass
headersComplete: true:- a recent Chrome, Firefox or Safari sends no
sec-fetch-*headers; - a Firefox or Safari user agent sends
sec-ch-ua, which only Chromium-based browsers send; - there’s no
Accept-Language.
- a recent Chrome, Firefox or Safari sends no