Simulating Behavioral Biometrics
The Human Signal Is (Nearly) Impossible to Fake by Hand
Mouse paths, keystroke timing, scroll velocity, gaze, and dwell time are the final frontier of bot detection. A WAF's machine-learning model has seen millions of human sessions; it knows the statistical shape of human interaction. Perfectly consistent, perfectly efficient automation is statistically impossible to confuse with that shape. The only way to pass is to model the human shape statistically.
Mouse Movement Modeling
Humans do not move in straight lines. A mouse path is curved, accelerates, overshoots the target, hesitates, then lands. The standard model is a Bézier curve with an overshoot-and-correct phase for the final approach. Libraries like humanize-js (Node) and Python's mouse automation packages implement these curves. Implement phase timing too: the entire path should take a variable 400–900ms, not a fixed 500ms.
def bezier_mouse(from_x, from_y, to_x, to_y, steps=40):
# Approximate a human-ish curved path between two points
points = []
for i in range(steps + 1):
t = i / steps
# simple quadratic curve with a mid-point control offset
cx = (from_x + to_x) / 2 + random.randint(-30, 30)
x = (1 - t) ** 2 * from_x + 2 * (1 - t) * t * cx + t ** 2 * to_x
y = (1 - t) ** 2 * from_y + 2 * (1 - t) * t * random.randint(-20, 20) + t ** 2 * to_y
points.append((round(x), round(y)))
return points
Keystroke Dynamics
Typists have a characteristic inter-keystroke interval (IKI) distribution and a signature pattern for pause-after-capitals and pauses mid-word. Hardcode a jittered, biased distribution instead of a flat random tick: fast bursts around 60–110ms between common letter pairs, longer pauses before capitals and after punctuation.
Scroll Behavior
Humans scroll in bursts: a fast fling, a hesitation, a slower reading scroll, a small corrective nudge. They rarely scroll at constant velocity. Segment your scrolls into "scan" (fast) and "read" (slow) phases with random pauses, and vary the distance scrolled per burst rather than always reaching the bottom instantly.
Timing the Page, Not Just the Input
Human behavior is not confined to mouse and keyboard. Sessions have a temporal envelope that WAFs model explicitly: the time between page load and first interaction, the dwell time before scrolling, the pause before submitting a form, and the total session length. A user who loads a page and clicks a button 40 milliseconds later did not read the page. A session that lasts exactly nine seconds is a bot's signature.
Build a timing budget into every page visit: a plausible read time proportional to the amount of text on the page (a 2,000-word article warrants 20–60 seconds), a hesitation before clicks near destructive buttons, and a random idle state if the workflow allows. These dwell times are cheap to inject and enormously effective, because WAFs weight temporal signals heavily when the pointer telemetry is synthetic.
The Danger of Over-Perfection
The deepest irony of biometrics evading is that over-optimized "human" simulation looks more machine-like than a genuinely imperfect simulation. The fix is statistical noise at every layer: everything from the timing between mutations to the exact pixel jerk on a Bézier curve. When in doubt, add more low-amplitude Gaussian noise to every value a real human would wobble on.
Validate on Real Sensor Traces
If you have access to any human session telemetry (from your own products, or a public dataset), train your generator to match its distributions rather than inventing curves by hand. The best keystroke and mouse models in the wild are fitted to real traces: pairs of consecutive keypresses, path curvature statistics, and dwell-time histograms. Simulation should aim to be statistically plausible, not geometrically pretty—a too-smooth curve is as suspicious as no curve at all.