Browser — block on load
import { isHuman } from "bot-signal";
const result = detectInstantClient(window);
if (!result.isLegitClient) {
location.href = "/blocked";
}
Live demo — everything runs in your browser
bot-signal (npm package `bot-signal`) spots headless browsers, automation frameworks, and scripted interaction — in the browser and on the server. This page runs the real library against you.
npm install bot-signal
Layer 1 · synchronous
detectInstantClient(window) inspects the environment in a single pass —
WebDriver flags, automation artifacts, rendering, and window geometry. Signals roll up
into a weighted suspicionScore.
Layer 2 · over time
createBehavioralClientDetector() watches how the pointer, wheel, and
keyboard behave. Humans are noisy; scripts are not. Touch taps, keyboard clicks,
and key auto-repeat are recognized — they never count against you.
Layer 3 · Node
detectServerClientAsync() runs in Node — GeoIP, datacenter ranges,
AbuseIPDB, iCloud Private Relay, and TLS fingerprints, all offline. This simulator
uses the library's real weights and formula:
score = 1 − Π(1 − wᵢ).
Ship it
One package, three layers. Import from the root, or use the
/browser and /server entry points.
import { isHuman } from "bot-signal";
const result = detectInstantClient(window);
if (!result.isLegitClient) {
location.href = "/blocked";
}
import { createBehavioralClientDetector } from "bot-signal";
const result = await createBehavioralClientDetector({ context: window })
.observe(10_000);
if (!result.isLegitClient) challenge();
import { detectServerClientAsync } from "bot-signal/server";
const result = await detectServerClientAsync({
clientIp: req.ip,
clientTimezone: req.headers["x-timezone"],
userAgent: req.headers["user-agent"],
tlsFingerprint: req.headers["x-ja3-hash"],
});
if (!result.isLegitClient) res.status(403).end();