Anti-bot detection systems analyze behavioral patterns to distinguish humans from automation. The most common tell is timing — Math.random()-based delays create detectable patterns. This guide covers how CSPRNG with human-matched distributions defeats these systems.
Why Math.random() Gets You Caught
JavaScript's Math.random() uses a xorshift128+ PRNG with a deterministic, predictable state. From just a few outputs, the entire sequence can be reconstructed. Anti-bot systems use this to detect automation:
- ▸Math.random() produces a deterministic sequence — predictable from outputs
- ▸Uniform distribution is unnatural — humans don't act with even timing
- ▸No long-tail behavior — humans have occasional very long pauses
- ▸No correlation between actions — human delays correlate with task complexity
CSPRNG: Cryptographically Secure Alternative
crypto.randomBytes() uses the OS entropy pool (CryptGenRandom on Windows, /dev/urandom on Linux). This produces truly unpredictable output that cannot be reconstructed or correlated:
// CSPRNG with 4096-byte buffer for efficiency
const crypto = require('crypto');
const BUF_SIZE = 4096;
let buf = crypto.randomBytes(BUF_SIZE);
let bufOffset = 0;
function cryptoRandom(): number {
if (bufOffset + 8 > BUF_SIZE) {
buf = crypto.randomBytes(BUF_SIZE);
bufOffset = 0;
}
const hi = buf.readUInt32BE(bufOffset);
const lo = buf.readUInt32BE(bufOffset + 4);
bufOffset += 8;
return (((hi >>> 5) * 0x4000000 + (lo >>> 6)) / 0x20000000000000);
}Human-Matched Distributions
The key insight is that humans don't act with uniform timing. Real human behavior follows specific statistical distributions. By matching these, automation becomes indistinguishable from human input.
| Distribution | Use Case | Characteristics | Percentage |
|---|---|---|---|
| Triangular | Fast actions (clicks, quick typing) | Peaked at 30% of range — most actions are fast | 70% |
| Gaussian (Normal) | Normal actions (navigation, reading) | Bell curve around midpoint | 25% |
| Exponential | Long pauses (thinking, distracted) | Long-tail — occasional very long delays | 5% |
Implementing Human Delay
The human delay function combines all three distributions to create natural timing patterns:
function humanDelayRng(min: number, max: number): number {
const r = cryptoRandom();
if (r < 0.70) {
// 70%: Triangular peaked at 30% of range (fast actions)
const mode = min + (max - min) * 0.3;
return clamp(triangular(min, mode, max), min, max);
} else if (r < 0.95) {
// 25%: Gaussian around midpoint
const mid = (min + max) / 2;
const std = (max - min) * 0.2;
return clamp(gaussian(mid, std), min, max);
} else {
// 5%: Exponential tail (long thinking pauses)
const rate = 1 / ((max - min) * 0.3);
return clamp(min + exponential(rate), min, max * 1.5);
}
}Typing Delays: Log-Normal Distribution
Human typing follows a log-normal distribution — most keystrokes are fast with occasional slow ones. This is the most critical distribution for detection:
function typingDelay(): number {
// Log-normal: most keystrokes fast, occasional slow ones
const base = logNormal(60, 0.4); // mean=60ms, sigma=0.4
return Math.max(20, Math.min(200, Math.round(base)));
}⚠ WarningTyping too fast (sub-20ms per keystroke) or too uniformly (all keystrokes within 5ms of each other) is the #1 detection signal for anti-bot systems.
Mouse Movement: Bezier Curves with Jitter
Humans don't move the mouse in straight lines. They follow curved paths with micro-jitters. Implement this with bezier curves and gaussian jitter:
async function humanMouseMove(page, targetX, targetY) {
const startX = cryptoInt(0, 1920);
const startY = cryptoInt(0, 1080);
const steps = cryptoInt(18, 35); // variable step count
for (let i = 0; i <= steps; i++) {
const t = i / steps;
const easeT = t * (2 - t); // ease-out
const jitterX = gaussian(0, 10); // micro-jitter
const jitterY = gaussian(0, 10);
const x = startX + (targetX - startX) * easeT + jitterX;
const y = startY + (targetY - startY) * easeT + jitterY;
await page.mouse.move(x, y);
await wait(10 + cryptoRandom() * 20); // variable step delay
}
}Click Position: Not Centered
Automation tools click the exact center of elements. Humans click slightly off-center. Randomize click position within element bounds:
function clickOffset(): number {
// Click at 30-70% of element bounds, not center
return 0.3 + cryptoRandom() * 0.4;
}Putting It All Together
The automation project combines all these techniques into a complete anti-detection system. The visual test page shows the CSPRNG keyboard and mouse behavior in real-time.
- ▸CSPRNG for all random values (crypto.randomBytes, 4096-byte buffer)
- ▸Triangular/Gaussian/Exponential distribution mix for delays
- ▸Log-normal distribution for typing delays
- ▸Bezier curves with gaussian jitter for mouse movement
- ▸Off-center click positions (30-70% of element bounds)
- ▸Variable mouse step count (18-35 steps)
- ▸Human-like scroll amounts with natural variation
- ▸Occasional long breaks (exponential tail) during repetitive tasks
✦ TipThe combination of CSPRNG + human-matched distributions + bezier mouse movement makes automation statistically indistinguishable from human behavior. Anti-bot systems cannot detect the difference.