How bot detection works.
Three engines, one score, a verdict your backend can read in under 50ms. No black box — every score comes with the detections behind it.
Live in three steps.
Drop in the SDK
One script tag with your public site key. It collects behavioral signals in the browser and posts them to ingest — no PII, no config.
<script
src="https://cdn.botect.ai/v1/sdk.js"
data-site-key="pk_live_8f2a…"
async
></script>We score every session
Three independent engines run off the request path. The strongest piece of evidence wins — a stable 1–99 score, a band, and the exact detections behind it.
{
"session": "ses_3kd9…",
"score": 12,
"band": "definite",
"detections": ["webdriver_present", "headless_ua"]
}Read the verdict
Your backend asks for the verdict with your secret private key. Cached, <50ms p99, and it fails open — if we degrade, you get allow.
Authorization: Bearer sk_live_…
{ "score": 12, "band": "definite",
"action": "block", "verified_bot": null }Three engines, one score.
Each engine scores on its own. We take the strongest piece of evidence — not an average — so one decisive tell is never diluted by softer signals.
Request-shape tells — header order, user-agent coherence, ASN reputation. The cheap, deterministic checks that catch lazy automation instantly.
- Header shape
- UA coherence
- ASN / IP reputation
In-browser tells the network layer can never see — automation flags, headless fingerprints, navigator anomalies. Affirmative webdriver is a definite bot.
- webdriver flag
- Headless fingerprints
- navigator anomalies
How a real human moves through a page. Synthetic scroll and zero genuine interaction over a session window read as automation — the signals the big providers skip.
- Mouse entropy
- Scroll velocity
- First-input delay
One score, from 1 to 99.
Lower is more bot. You set the likely-bot threshold T (default 30) — everything below it lands in an automated band, everything above reads human. Verified crawlers sit in their own band so you never block search.
No scoring opinion yet — the sentinel 0, never confused with 1. Fails open.
Hard automation tells — webdriver, headless, known-bad. Block-grade evidence.
Below your threshold T. Synthetic behavior, suspicious shape. Good challenge candidate.
At or above T. Genuine pointer movement, coherent request, real interaction.
A confirmed good crawler — Googlebot, Bingbot, Applebot — verified against the directory and still on your allowlist.
Decide what happens.
Rules, not black boxes
Start from ready-made rules for the common cases, or write safe expressions over the same signal fields for the rest. Compiled to an AST — never eval.
Observe-first
Enforcement is off by default. Watch real scores against your traffic, tune the threshold, then turn blocking on when you trust it.
An allowlist you control
Googlebot, Bingbot, Applebot and friends are verified against a maintained directory, then it is your call: keep search, refuse AI training crawlers, switch off a single operator. Categories carry your decision to crawlers added later.
Five verdict actions
block · challenge · allow · log · delay. Map each band to the response you want; log is observe-only so you can stage enforcement safely.
Fast where it counts.
Scoring happens asynchronously, off your users’ request. Verdict reads hit a Redis cache — <50ms p99 — and fail open by design. If Botect is degraded or the session is unknown, you get an allow, not a wall.
p99 verdict read
No false walls
Scoring off the request path
Any backend, any language
Score your first request in ten minutes.
Sign up, drop in the SDK, watch real scores against your own traffic — blocking stays off until you say so.