Understanding the Logic Behind Typing Speed Algorithms

Key Points
  • A typing speed algorithm has six layers: input capture, character comparison, timing, WPM calculation, error classification, and anti-cheat validation.
  • The WPM formula is simple, but correctly classifying each character state is where the complexity lives.
  • performance.now() is the right timing API — it's monotonic and sub-millisecond.
  • Anti-cheat requires sending keystroke timing data to the server, not just the final score.
  • Statistical analysis of inter-keystroke intervals can reliably identify bot-generated scores.

The Six Layers of a Typing Test Algorithm

When you type a character in a typing test, a chain of operations runs in a few milliseconds. Understanding each layer explains both how to build one and why scores can vary between platforms.

LayerWhat it doesKey detail
Input captureReceives raw keystrokesUses keydown events, not keypress (deprecated)
Timestamp recordingRecords when each key was pressedperformance.now() in browser; perf_counter() in Python
Character comparisonMatches typed character to expectedPosition-based, not substring matching
Error classificationLabels each character as correct/incorrect/extraDetermines what counts toward WPM penalty
WPM calculationConverts correct characters to WPM(correct_chars / 5) / elapsed_minutes
Anti-cheat validationVerifies score plausibilityServer-side timing analysis

Input Capture: Why keydown, Not keypress

The browser fires three keyboard events per keystroke: keydown, keypress (deprecated), and keyup. Typing tests use keydown because it fires on every key including modifier keys (Shift, Ctrl) and special keys (Backspace, Enter), and it fires before the browser's default action. The keypress event was deprecated in modern browsers and doesn't fire reliably for all keys.

Each keydown event provides: the key value (what character was typed), the key code (which physical key was pressed), and can be timestamped with performance.now().

Character Comparison and Error Classification

The character comparison layer maintains a position index and compares the typed character at each position against the expected character from the source text. The state machine for each position looks like:

  • Untyped: Position not yet reached
  • Correct: Typed character matches expected character
  • Incorrect: Typed character does not match expected
  • Corrected: Was incorrect, then backspaced and corrected
  • Skipped: Position was passed over (in tests that allow advancing past errors)

The net WPM formula only counts characters in the "correct" or "corrected" state. Characters left in "incorrect" state are subtracted as error penalties.

Anti-Cheat: The Statistical Validation Layer

A client-side score is trivially fakeable — anyone can inspect the network request and replay it with a modified score. The anti-cheat layer works by requiring the client to send the full keystroke timestamp array alongside the score. The server then independently calculates what the WPM should be from the timing data and rejects submissions where the claimed score doesn't match.

Beyond simple replay attacks, statistical analysis of inter-keystroke intervals (IKIs) catches bot-generated scores. Human typists have naturally variable IKIs — the time between keystrokes varies with word familiarity, finger assignment, and random motor noise. Bot-generated keystrokes tend to have suspiciously uniform IKIs, or IKIs that are physically impossible for human hands (under 20ms per character at claimed speeds above 200 WPM).

For more on how this connects to the leaderboard specifically, see how to build a typing test website from scratch. For the JavaScript implementation of the input capture layer, see handling keyboard events in JavaScript.

Ready to put it into practice?

Take a free typing test and start tracking your progress.

Free Typing Test →