Skip to content
Botscent

Privacy

What Botscent reads, what it keeps and what it sends, probe by probe and header by header.

This page lists what Botscent reads, what it keeps and what it sends. It describes the library's behaviour. It is not legal advice.

In short

  • The page half reads browser properties and uses them only inside the page. It makes no network request, sets no cookie, writes no storage and writes nothing to the DOM.
  • The page half keeps no observed value. Each probe compares what it reads with a known shape and keeps only the id of a reason that held.
  • Nothing leaves the page unless your code sends it, through a carrier that you choose. A carrier sends the verdict, never an observed value.
  • The server half reads the request's headers and nothing else. It makes no outbound request.
  • No part of the library has telemetry or an identifier, or sends anything to the maintainers.

The page half: every probe

ProbeWhat it readsWhen
navigatornavigator.webdriver. Whether navigator.userAgent begins with a listed prefix, and whether navigator.platform is a listed value.At start.
credentialsThe property descriptors of navigator.credentials.get, navigator.credentials.create and three PublicKeyCredential methods: accessor or value, function name and length, and whether the source looks native. It calls none of them.At start, then at 1.5 s and 5 s.
geetestThe descriptors of window.initGeetest and window.initGeetest4, if present.At start, then at 1.5 s and 5 s.
promptThe shape of window.prompt: its name, its length and the length of its source text.At start, then at 1.5 s and 5 s.
computerOnly in Chrome 139 or later on Linux x86_64: whether the screen is 1280x800, whether the Ubuntu and Droid Sans fonts are installed (text widths on a canvas), and whether "Google Chrome" is among the brands. Then whether the Cambria font is installed, and whether passkey autofill (isConditionalMediationAvailable) is available. With 5 of those 6 signs, the WebGL renderer.Once, at the first idle moment after start (within 300 ms). Only in Chrome 139 or later on Linux x86_64.
rendererWebGL's renderer name, such as a GPU model or SwiftShader, from one short-lived canvas. Only in Chrome 139 or later on Linux x86_64, and only when the credential methods carry 1Password's accessor family or computer found 5 of its 6 signs. That describes the cloud browsers of Muse and Grok Bot, and very few people.At most once per page, after the other clauses have matched, off the start task.
keyboardThe size of navigator.keyboard.getLayoutMap(), where the browser has it. It reads no keys.At start.
overlayFor children of <html> other than <head> and <body> with an open shadow root: their id, position, z-index and pointer-events.At start, at 1.5 s and 5 s, after DOM changes there, and every 5 s while the page is visible.
markersWhether elements with a few specific ids exist, and whether a favicon link in <head> has a known attribute.As overlay, and also at a trusted pointerdown or keydown.
inputOn trusted pointerdown, keydown, wheel and input events: only whether the document was hidden and focused at that moment. It reads no coordinates, keys, targets or text.While started.
domA MutationObserver on the children of <html> and <body>, and on <head> for favicons. It only schedules overlay and markers.While started.

The page half reads the botscent entry in the navigation's Server-Timing once, at start. That entry is the server half's verdict, which your own server sent.

diagnostics reports the status of each probe and the transport's outcome. A status is ok, pending, unsupported or failed. It never reports a value that a probe read. Debug output from start({ debug: true }) logs reason ids and statuses to the console.

What can leave the page

Only a carrier that your code uses sends anything:

  • reportHeaders gives a Botscent-Report header for a request to the page's own origin. Your code adds the header to a fetch.
  • A form with data-botscent-field gets a botscent field on its own POST submission to the same origin.

Each carrier sends the verdict as a wire entry: a version, the agent name when there is one, and reason ids. A person's page sends nothing, and an entry never contains an observed value.

When a value leaves the device this way, your site collects it. The purpose of your site decides what that collection needs. The same applies when you send the verdict to analytics.

The server half

inspect reads these parts of a request:

  • The User-Agent, Signature, Signature-Input and Signature-Agent headers.
  • Host or :authority, the method and the request target.
  • Any other header that a signature covers, to verify the signature.
  • On Cloudflare, the platform's verified-bot fields in request.cf.

The adapters also read Sec-Fetch-Dest and Accept, to tell a document navigation from other requests.

The server half reads no body and no cookie. It keeps nothing between requests and makes no outbound request, because each release bundles the signer keys.

Debug output is off by default. For each request, it logs the method, the host, the path without the query, and up to 200 characters of the user agent. If your logs must not hold these values, keep debug output off in production.

npx botscent check

npx botscent check requests the URL that you give it, opens the URL in a Chrome on your machine, and reads the page half's diagnostics. It sends nothing to any other place.

Its --report block has only what Botscent owns: versions, its own Server-Timing entries, diagnostics and bounded check results. The block has no query string, cookie or address.

Purpose

In the EU, Article 5(3) of the ePrivacy Directive governs access to a device, read with the EDPB's Guidelines 2/2023. These texts turn on what the information is used for and whether it leaves the device:

  • The page half reads properties that never leave the device, unless your code sends the verdict.
  • Headers that your server already receives can still be in scope when your server uses them to collect information about the device.
  • Protection of a service, such as rate limits and abuse prevention, and measurement of traffic, such as analytics, are different purposes. An exemption for one purpose does not cover the other.

Botscent therefore keeps the two apart. Access decisions use only the request's own verdict, and nothing reaches analytics unless your code sends it there.