Bot detection that bots can’t spoof
Catch headless browsers, automation frameworks, scrapers and AI agents — decided server-side from raw tells, TLS fingerprints and how a real hand actually moves.
Why client-side bot checks fail
Anything the browser computes, a bot can patch. A script that returns isBot: false
is trivially overwritten. Robust bot detection must be decided server-side from
raw evidence the automation can’t consistently fake. Prynt’s agent ships tells — not a
boolean — and the engine weighs them where the bot can’t reach.
The tells that give automation away
- Headless & automation flags:
navigator.webdriver, Selenium/Puppeteer/ Playwright globals, CDP artifacts, missingwindow.chrome, empty plugin/language lists. - Native-function tampering: patched
getContext/toDataURL/getParameter(canvas-noise and UA-spoof tools betray themselves here). - SwiftShader / software GL under a non-headless UA, iframe hardware mismatches, and fresh-iframe webdriver re-reads that bypass a top-level override.
- JA4 TLS fingerprint captured at the edge, before any JS runs — a browser UA riding a curl/Go/Python TLS stack is a spoofed client.
- Behavioral biometrics: dead-straight mouse paths, zero timing variance, superhuman typing and a motion sensor that never moves reveal a machine even when the environment is perfectly spoofed.
AI agents are the new bot surface
Agentic-AI traffic — ChatGPT Operator, Perplexity, Claude and Gemini agents, GPTBot, CCBot — is the fastest-growing traffic class of 2026. Prynt classifies it as a distinct verdict (not just “bot”) so you can allow, throttle or block AI agents on your own terms.
Detect, then act — at the edge
Detection without mitigation is half a product. Prynt wires the verdict to Prynt Challenge — a self-hostable, risk-adaptive proof-of-work (an open-source Turnstile/Arkose alternative) — and to Prynt Edge connectors (Cloudflare Worker, nginx/OpenResty) that allow, challenge or block sub-10ms before your origin.
Related
Device fingerprinting · Account-takeover prevention · Prynt vs FingerprintJS · Glossary