How it works
What each half of Botscent reads, when each half sees evidence, and how the halves share a verdict.
Botscent looks for agents in two places: in the request that loads a page, and in the page itself. The server half reads the request. The page half watches the page. Each half gives a verdict of the same shape.
request ──> server half ──> the request's own verdict (inspect)
│
│ Server-Timing entry, for agents only
▼
page ─────> page half ────> the page verdict (verdict, useBotscent)
│
│ reportHeaders or data-botscent-field, when your code opts in
▼
your server ──────────────> a page report (readReport)The server half
The server half reads what one request declares. It finds 3 kinds of evidence:
- a Web Bot Auth signature, checked against the signers' keys that each release bundles
- a user-agent token that an agent, a crawler or an HTTP client publishes for itself
- the verified-bot field of the hosting platform, such as Cloudflare's
request.cf
The server half reads headers only, never the body. It calls no service. It runs on Node.js, Cloudflare Workers, Vercel, Deno and Bun, and in Python. You call inspect, or add an adapter that calls inspect for each request.
The page half
The page half watches the document for evidence that an agent operates the page. It finds 3 kinds of evidence:
- the automation flag,
navigator.webdriver - the shapes and markers that agent browsers and extensions leave, such as the Claude for Chrome marker
- input that arrives while the document is hidden
The page half is about 5 KB gzipped and makes no network request. When it sees agent evidence, the page verdict stays agent for the rest of the document's life.
When evidence arrives
Each kind of agent shows its evidence at a different time:
| Agent | Examples | Half | When |
|---|---|---|---|
| Hosted agents that sign or declare their requests | ChatGPT, Devin, Manus, Grok Bot | server | At the request |
| Cloud browsers and browsers under automation | Muse, Instinct, Cloudflare Browser Run, any browser with the webdriver flag | page | At load, before any input |
| Extension and desktop agents | ChatGPT for Chrome, Claude for Chrome, the Codex in-app browser | page | When the agent acts, which can be seconds or minutes after load |
| Agents that send input to a hidden document | No name from this evidence | page | At input |
So the page verdict can change during a visit. Code that reads the page verdict must follow its changes. useBotscent, subscribe and the botscent event on window give each change. See Page API.
One page, both halves
The server half can send the request's own verdict to the page in a Server-Timing entry. Then the page verdict holds the evidence of both halves. An adapter writes the entry only for an agent's navigation. By default, it writes the entry only where it runs in front of the cache. See From the server to the page.
The page half sends nothing on its own. Your code can send the page verdict to your server as a page report. The server keeps the page report apart from the request's own verdict. See From the page to the server.
What it does not do
- It does not detect automation built to look like a person.
- It does not read a request body, or what a person types into the page.
- It does not say who performed a particular action on the page.
- It does not send anything to the maintainers. There is no telemetry.
- It has not been measured with Comet or with Windows assistive tools.
Related
- The verdict: what
type,agent_nameandreasonsmean. - The trust model: which verdict you can use to decide access.
- Privacy: every probe of the page half and every header that the server half reads.