Skip to content

v1.20.0 — signal accuracy

Choose a tag to compare

@cport1 cport1 released this 28 Jul 15:23

Scoring changes for ordinary browsers. If you have tuned custom thresholds, re-check them — legitimate visitors now score lower.

Two signals no longer scored

webdriver_configurable and chrome_runtime_missing were reported as Playwright artifacts and scored in the headless category. Neither indicates automation.

Measured in Chrome 150, driven by a person, with navigator.webdriver === false:

signals reported: ["webdriver_configurable", "chrome_runtime_missing"]
  • webdriver_configurable — WebIDL defines navigator.webdriver as configurable, so every browser reports the descriptor exactly as a patched one does.
  • chrome_runtime_missingchrome.runtime is only exposed to a page when an extension declares externally_connectable matching it, so an ordinary Chrome on an ordinary site has none.

Both are now ignored, in the client and in all three servers — the servers too, because deployed clients will keep sending them for a while.

before after
a genuine Chrome, headless category 0.771 0
a genuine Chrome, overall score ~0.23 0.111

webdriver_deleted and playwright_globals are unchanged. Deleting the property or injecting framework globals is deliberate tampering that no shipped browser does, and automated browsers remain identified by navigator.webdriver being true.

Agent detection is unaffected: benchmark true-positive rate stays at 97.33%, with every captured agent class at 100%.

Touch form submissions

The submit classifier consulted only keydown and mousedown, within 100ms of the submit event. touchstart was recorded but never read, so a tap whose compatibility mousedown lagged was read as a programmatic submit — as was any click-to-submit slower than 100ms on a loaded device.

It now selects by time rather than by the last five events, considers touchstart, and allows 500ms.

Benchmark

bench/capture/normalize.js now reproduces a measured browser rather than an idealised one. It previously pinned the navigator.webdriver descriptor non-configurable and supplied a chrome.runtime object, which made the human panel cleaner than any real browser and left it unable to observe signals attached to those properties.

The rule is now recorded in the harness: anything pinned during normalization is a signal the panel cannot see, so pin as little as possible and pin it to measured values. All 22 personas were re-captured against the corrected normalization.

The proof-of-work pacing in the replayer is also more precise, so replayed solves land inside the server's accepted timing band rather than near its edges.

Human panel false-positive rate remains 0.00%, now measured on a panel that carries what a real browser carries.

Upgrading

No API or configuration changes. Scores move downward for legitimate visitors and are unchanged for automation.