Understanding the Logic Behind Typing Speed Algorithms
- 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.
| Layer | What it does | Key detail |
|---|---|---|
| Input capture | Receives raw keystrokes | Uses keydown events, not keypress (deprecated) |
| Timestamp recording | Records when each key was pressed | performance.now() in browser; perf_counter() in Python |
| Character comparison | Matches typed character to expected | Position-based, not substring matching |
| Error classification | Labels each character as correct/incorrect/extra | Determines what counts toward WPM penalty |
| WPM calculation | Converts correct characters to WPM | (correct_chars / 5) / elapsed_minutes |
| Anti-cheat validation | Verifies score plausibility | Server-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.
¿Listo para ponerlo en práctica?
Haz una prueba de mecanografía gratuita y empieza a hacer seguimiento de tu progreso.
Prueba de mecanografía gratuita →