How to Build Your Own Typing Test Website from Scratch

Key Points
  • A typing test has five core components: text source, input handler, timer, scorer, and results display.
  • Use performance.now() for keystroke timing — it gives sub-millisecond precision in any modern browser.
  • Net WPM requires tracking both correct and incorrect characters separately throughout the test.
  • Anti-cheat requires server-side validation of keystroke timing patterns — client-side scores can be faked.
  • The hardest part isn't the WPM formula — it's handling the input edge cases (backspace, spaces, paste blocking).

The Architecture Overview

A production-quality typing test has five distinct systems working together. Understanding each one separately makes the whole thing easier to build.

ComponentWhat it doesKey technology
Text sourceProvides the words/passage for the testWord list array, passage database, or API
Input handlerCaptures keystrokes and compares against expected textJavaScript keydown events
TimerTracks elapsed time with sub-millisecond precisionperformance.now()
ScorerCalculates WPM, accuracy, and error countsFormula engine (client + server)
Results displayShows final score and per-second speed graphDOM manipulation or charting library

The Input Handler: The Hardest Part

The input handler is where most of the complexity lives. You need to track:

  • The current position in the text
  • Whether each typed character is correct or incorrect
  • What happens when the user presses backspace (move position back, mark character as untyped)
  • Whether the user can advance past an error (some tests block this, others allow it)
  • Paste events (should be blocked in a fair test)

The cleanest data structure is a character state array: one entry per character in the text, with a state of "untyped", "correct", or "incorrect". The current cursor position is an index into this array. Every keydown event either advances the index (on any character key) or decrements it (on backspace).

Timing with performance.now()

The browser's performance.now() API returns the number of milliseconds elapsed since the page loaded, with sub-millisecond resolution. This is the right tool for timing a typing test because:

  • It doesn't drift like Date.now()
  • It's monotonically increasing (never goes backward)
  • It has ~0.1ms resolution on most browsers

Record a start timestamp when the first character is typed, and an end timestamp when the test completes. Elapsed time = (endTime - startTime) / 1000 / 60 in minutes.

The WPM Formula

The standard formula for WPM: WPM = (characters_typed / 5) / elapsed_minutes

For net WPM: net_WPM = gross_WPM - (uncorrected_errors / elapsed_minutes)

One "word" = 5 characters (including spaces). This standardises across different word lengths so long words don't penalise speed unfairly.

Anti-Cheat Architecture

Client-side scores can be manipulated. Anyone can open developer tools and send a fake score submission. A production typing test with a leaderboard needs server-side validation. The most reliable method is sending the full keystroke timestamp array to the server with the score, then validating:

  1. Does the timing data produce the claimed WPM?
  2. Are inter-keystroke intervals within physically plausible ranges? (Under 20ms per key is suspicious)
  3. Is the timing pattern consistent with a human? (Bots often have uniform inter-keystroke timing)
  4. Do the keystrokes match the expected characters for the claimed accuracy?

This is the same approach TypingTest.now uses for its leaderboard validation. For more detail, see understanding the logic behind typing speed algorithms.

Building the Results Display

The minimum results display shows WPM, accuracy percentage, and error count. A better display adds a per-second WPM graph (plot the rolling WPM at each second of the test). This graph reveals consistency — a flat line is better than a high peak with a long valley.

For a reference implementation to compare against, take the 1-minute test and inspect the results page. The architecture described here is what powers it. For the Python implementation version, see coding a typing speed test in Python.

Ready to put it into practice?

Take a free typing test and start tracking your progress.

Free Typing Test →