Velocity Fingerprint

Detects bots by measuring the statistical regularity of inter-request timing intervals across a session.

The velocity fingerprint checker measures how regular the time gaps between a visitor's requests are. Human browsing is inherently irregular: users read content, click around, get distracted, and navigate unpredictably. Bots operate on timers or tight loops and produce intervals that are either very consistent or mechanically patterned.

This checker runs in the heavy phase and reads timestamps from the timing cache keyed by canary cookie.


How It Works

The checker stores up to 10 request timestamps per canary cookie in the cache. Evaluation begins once at least 5 timestamps are available.

From the stored timestamps, the checker computes the intervals between consecutive requests. It then calculates the coefficient of variation (CV) of those intervals: the standard deviation divided by the mean.

A CV close to zero means the intervals are nearly identical: the visitor is making requests on a fixed timer. A high CV means the intervals vary widely, consistent with human behavior. When the CV falls below cvThreshold, the checker applies the penalty and attaches TIMING_TOO_REGULAR.

The checker requires at least 5 samples before it evaluates timing. This means a minimum of 5 requests with a canary cookie are needed before this check can fire. Short sessions where bots send only a few requests will not trigger it.

Configuration

server.ts
await defineConfiguration({
  store: { main: { driver: 'sqlite', name: './bot-detector.db' } },
  checkers: {
    enableVelocityFingerprint: {
      enable: true,
      cvThreshold: 0.1,
      penalties: 40,
    },
  },
})
enable
boolean
Enables or disables this checker. Default: true.
cvThreshold
number
The coefficient of variation below which timing is considered unnaturally regular. Lower values only flag very mechanical bots; higher values flag moderately regular timing as well. Default: 0.1.
penalties
number
Score applied when the CV falls below the threshold. Default: 40.

Reason Codes

CodeTrigger
TIMING_TOO_REGULARThe coefficient of variation of inter-request intervals is below cvThreshold.

If your application includes long-polling or WebSocket reconnection logic that sends requests on a fixed interval, consider raising cvThreshold slightly or disabling this checker for those specific endpoints. Fixed-interval programmatic clients that are not bots can trigger this check.
Logo