🎮 Get a game · $19

⌨️ Free game 20 of 20 · copy & paste

Typing Speed Game in HTML & JavaScript (WPM Test): Free Code

Type the words as fast as you can for 30 seconds and get your words per minute (WPM) and accuracy. The current word is highlighted and mistakes turn red. Copy the code below, save it as typing-game.html and open it in any browser.

Type
Word & quick
Level
Beginner
Code
112 lines, 1 file
Libraries
None
Works on
Phones & computers
You learn
Input events and the WPM formula

▲ Play it right here. Type the words; press Space after each one.

What's in this free Typing Speed Test game

The code (112 lines, one file)

typing-game.html⬇ Download
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Typing Speed Game</title>
<!--
  Free HTML Typing Speed game (WPM test) — one file, no libraries. Save it as typing-game.html and open it in a browser.
  From htmlgamescode.com (free to use in your own projects).
  Type the words as fast as you can. The timer starts with your first key. Press Space after each word.
-->
<style>
  * { box-sizing: border-box; margin: 0; padding: 0; }
  body {
    min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
    background: #1b1446; color: #fff; font-family: system-ui, -apple-system, "Segoe UI", sans-serif; padding: 14px;
  }
  h1 { font-size: 24px; }
  .stats { display: flex; gap: 8px; font-weight: 800; }
  .stats span { background: #2a2170; padding: 6px 12px; border-radius: 10px; }
  .words { width: min(94vw, 440px); height: 132px; overflow: hidden; padding: 12px 14px; border-radius: 16px; background: #2a2170; font: 600 22px/1.6 ui-monospace, Menlo, monospace; }
  .words span { margin-right: 10px; border-radius: 5px; }
  .words .now { background: rgba(255,255,255,.15); }
  .words .ok { color: #7dff5a; } .words .bad { color: #ff4d6d; text-decoration: line-through; }
  input { width: min(94vw, 440px); padding: 12px 14px; font: 600 20px ui-monospace, Menlo, monospace; border: 3px solid #382c8f; border-radius: 14px; background: #fff; color: #1b1446; outline: none; }
  input.wrong { border-color: #ff4d6d; }
  button { border: 0; border-radius: 14px; padding: 11px 24px; font: 700 17px system-ui, sans-serif; color: #fff; background: #ff5fb1; box-shadow: 0 4px 0 #b8327a; cursor: pointer; }
  .result { font-size: 20px; font-weight: 800; text-align: center; min-height: 28px; }
</style>
</head>
<body>
  <h1>⌨️ Typing Speed Test</h1>
  <div class="stats"><span>⏱ <b id="time">0</b>s</span><span>WPM: <b id="wpm">0</b></span><span>Best: <b id="best">0</b></span></div>
  <div class="words" id="words"></div>
  <input id="input" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false" placeholder="Start typing here…" aria-label="Type the words">
  <div class="result" id="result"></div>
  <button id="restart">↻ Restart</button>

<script>
  // ---- settings: change these to make it your own ----
  const SECONDS = 30;            // length of the test
  const WORD_COUNT = 120;        // words shown per test
  const WORDS = "the be to of and a in that have it for not on with he as you do at this but his by from they we say her she or an will my one all would there their what so up out if about who get which go me when make can like time no just him know take people into year your good some could them see other than then now look only come its over think also back after use two how our work first well way even new want because any these give day most us apple river light house green music happy water smile cloud dream world quick brown jump over lazy dog fast learn code game play score level".split(" ");   // the words to type

  const $ = id => document.getElementById(id);
  const load = k => { try { return Number(localStorage.getItem(k)) || 0; } catch { return 0; } };
  const save = (k, v) => { try { localStorage.setItem(k, v); } catch {} };
  let list, spans, index, correctChars, typedWords, started, timer, finished, best = load("typing-best");

  function newTest() {
    list = Array.from({ length: WORD_COUNT }, () => WORDS[Math.floor(Math.random() * WORDS.length)]);
    $("words").innerHTML = list.map(w => `<span>${w}</span>`).join(" ");
    spans = [...$("words").children];
    index = 0; correctChars = 0; typedWords = 0; started = 0; finished = false;
    clearInterval(timer);
    $("time").textContent = SECONDS; $("wpm").textContent = 0; $("best").textContent = best; $("result").textContent = "";
    $("input").value = ""; $("input").disabled = false; $("input").className = ""; $("input").focus();
    mark();
  }

  function mark() {
    spans.forEach(s => s.classList.remove("now"));
    if (spans[index]) {
      spans[index].classList.add("now");
      $("words").scrollTop = spans[index].offsetTop - $("words").offsetTop - 12;   // keep the current line at the top
    }
  }

  function wpm() {
    const minutes = started ? Math.max(1 / 60, (Date.now() - started) / 60000) : 1;
    return Math.round(correctChars / 5 / minutes);      // 1 "word" = 5 characters, the standard WPM formula
  }

  function tick() {
    const left = Math.max(0, SECONDS - Math.floor((Date.now() - started) / 1000));
    $("time").textContent = left; $("wpm").textContent = wpm();
    if (left === 0) finish();
  }

  function finish() {
    finished = true; clearInterval(timer); $("input").disabled = true;
    const score = Math.round(correctChars / 5 / (SECONDS / 60));
    const accuracy = typedWords ? Math.round(spans.slice(0, index).filter(s => s.classList.contains("ok")).length / typedWords * 100) : 0;
    const record = score > best;
    if (record) { best = score; save("typing-best", best); }
    $("wpm").textContent = score; $("best").textContent = best;
    $("result").textContent = `${score} WPM · ${accuracy}% accuracy${record ? " · New best! 🏆" : ""}`;
  }

  $("input").addEventListener("input", e => {
    if (finished) return;
    if (!started) { started = Date.now(); timer = setInterval(tick, 250); }
    const value = e.target.value;
    if (value.endsWith(" ")) {                           // space = check the word and move on
      const typed = value.trim();
      if (!typed) { e.target.value = ""; return; }
      const ok = typed === list[index];
      spans[index].classList.add(ok ? "ok" : "bad");
      if (ok) correctChars += typed.length + 1;          // +1 for the space
      typedWords++; index++;
      e.target.value = ""; e.target.className = "";
      mark();
      if (index >= list.length) finish();
    } else {
      e.target.className = list[index].startsWith(value) ? "" : "wrong";   // red border while it's wrong
    }
  });
  $("restart").addEventListener("click", newTest);
  newTest();
</script>
</body>
</html>

How to use it

  1. Click Copy code (or Download).
  2. Paste it into any text editor and save it as typing-game.html.
  3. Open the file in Chrome, Safari, Firefox or Edge. That's it, it runs offline.

How the code works

Checking words

The input event fires on every key. When the value ends with a space, the word is compared with the current one and marked right or wrong.

WPM

Words per minute uses the standard formula: correct characters ÷ 5 ÷ minutes.

Scrolling

The word box scrolls so the line with the current word stays on top.

Make it your own

All the settings are at the top of the script. Change a value, save and reload:

SettingDefaultWhat it does
SECONDS30length of the test
WORD_COUNT120words shown per test
WORDS"the be to of and a in tha…the words to type

Put it on your website

Upload typing-game.html next to your page and add this where the game should appear:

<iframe src="typing-game.html" width="460" height="620" style="border:0;max-width:100%" title="Typing Speed Test game"></iframe>

FAQ

Is this Typing Speed Test code really free?

Yes. Copy it and use it in your own website, school project or app, change it as much as you like and publish it, even commercially. A link back to HTML Games Code is welcome but not required.

How do I run the Typing Speed Test game?

Copy the code, paste it into a text editor, save the file as typing-game.html and double-click it. It opens in your browser and works offline; there is nothing to install.

What are the controls?

Type the words; press Space after each one.

Does it work on phones?

Yes. It has touch controls and fits a phone screen, and it works with a keyboard and mouse on a computer.

Can I put it on my website?

Yes. Upload typing-game.html and link to it, or show it inside an iframe on any page (see "Put it on your website" above).

Can I turn it into an Android app?

Yes. Any HTML game can be packaged as an Android APK. Our HTML Games APK Builder does it for our premium games, or you can use a tool like htmltoapk.com for this file.

More free HTML games