Benchmark protocol
How TypingTester.io calculates your result
A typing score is useful only when its rules are visible. This page documents the current local scoring engine, timer, error policy, test text, and storage limits. It is a reproducible product benchmark, not a professional certification or a universal typing standard.
- Scoring version
- 1.0.0
- Policy
- typingtester-standard-v1
- Corpus schema
- 1
WPM and accuracy
TypingTester.io uses the conventional five-character word. Displayed WPM is correct characters ÷ 5 ÷ effective elapsed minutes. Gross WPM is all typed characters ÷ 5 ÷ effective elapsed minutes. Both WPM values are rounded to the nearest whole number.
Accuracy is correct typed characters ÷ all typed characters × 100and is rounded to 2 decimal places. An untouched test displays 100% accuracy and 0 WPM. Punctuation, spaces, line breaks, and code characters are compared exactly.
The engine uses a 1-second minimum denominator to prevent near-zero timing from creating an unbounded WPM value. The saved elapsed time remains the actual measured value; the guard affects only the rate calculation.
Timing and completion
The timer begins when the first committed character is entered. The browser uses its monotonic high-resolution clock when available, with the system clock as a fallback. Timed tests finalize at their configured boundary even if a throttled browser interval wakes later. Text-completion sessions can finish earlier.
Finalization is idempotent: a timeout and a final input event cannot save two results. The final event's latest character is scored directly rather than waiting for a state update. Actual elapsed seconds and the configured duration are stored as separate fields.
Paste is disabled inside the measured typing input so a result represents committed typing. The separate custom-practice editor accepts pasted text, but that source text is not stored. IME composition is accepted only when the browser emits the committed composition value.
Errors, corrections, and incomplete text
- Incorrect characters are typed positions that do not match the expected character. Characters beyond the expected text are incorrect.
- Error positions count each position that was mistyped at least once. Repeating a mistake at the same position adds a mistake attempt but not another distinct position.
- Corrected errors are previously mistyped positions that are correct in the final text. Backspace does not erase their attempt history.
- Uncorrected errors are positions still wrong when the result is calculated.
- If time expires before the text ends, only characters actually typed are included. Provisional IME composition input is not committed until the composition event finishes.
A reproducible scoring fixture
This fixture is calculated by the same pure function used by the live and final result displays. The typist entered “hello” in 60 seconds after first mistyping and then correcting the third character.
{
"input": {
"expectedText": "hello",
"typedText": "hello",
"errorHistory": [
{
"position": 2,
"expected": "l",
"typed": "z",
"occurredAtMs": 10000
}
],
"startedAtMs": 0,
"endedAtMs": 60000,
"configuredDurationSeconds": 60
},
"result": {
"scoringVersion": "1.0.0",
"wpm": 1,
"rawWpm": 1,
"accuracy": 100,
"errors": 1,
"mistakeAttempts": 1,
"correctedErrors": 1,
"uncorrectedErrors": 0,
"elapsedSeconds": 60,
"configuredDurationSeconds": 60
}
}Text cohorts and comparability
Timed word tests sample from a stable, deduplicated English word cohort. Sentence and JavaScript modes use original project text released under CC0-1.0. Corpus IDs and versions change when a material cohort changes. Custom text has no corpus ID and should not be compared as if it were the same benchmark.
| Corpus | Version | Category | License | Character distribution |
|---|---|---|---|---|
| en-common-199 | 2.0.0 | common-words | CC0-1.0 | 760 letters (1 uppercase) · 0 numbers · 0 punctuation · 0 symbols · 198 whitespace |
| en-advanced-50 | 2.0.0 | advanced-words | CC0-1.0 | 640 letters · 0 numbers · 0 punctuation · 0 symbols · 49 whitespace |
| en-original-sentences | 1.0.0 | sentences | CC0-1.0 | 542 letters (10 uppercase) · 0 numbers · 15 punctuation · 0 symbols · 107 whitespace |
| javascript-original | 1.0.0 | code | CC0-1.0 | 413 letters (12 uppercase) · 5 numbers · 88 punctuation · 21 symbols · 102 whitespace |
| adaptive-mixed-practice | 1.0.0 | focused practice | CC0-1.0 mixed practice units and word cohort | Generated per evidence-backed plan; stored result includes its expected-text hash. |
Compare results only when their duration, mode, scoring version, and corpus are compatible. Very short tests naturally vary more than longer samples, and different sites may use different correction or error policies.
Weak-key evidence and focused practice
Benchmark sessions build an aggregate local profile of character-class accuracy, expected-versus-typed confusions, weak keys, and weak bigrams. Practice, lesson, and custom sessions are excluded from this durable profile. A key or bigram is eligible for a recommendation only after at least 8 expected appearances and 2 mistake attempts. One isolated mistake is not labelled as a weakness.
When enough evidence exists, the practice generator can create a deterministic 30-second focused drill or a two-minute accuracy drill from the versioned adaptive cohort. It mixes relevant target patterns with control words and explains the attempts and mistakes behind the recommendation. Without enough evidence it offers balanced practice while more local samples are collected.
Privacy, retention, and export
Tests run in your browser without an account. Results use local storage schema 2; the newest 50 valid records are retained on this browser. Older records are migrated defensively, and malformed records are ignored rather than breaking your statistics page.
Saved records contain scores and timing. Benchmark records and JSON exports can include aggregate error statistics; CSV exports use summary fields only. Corpus identifiers are included when available. No export contains the expected passage or your complete typed text. Custom text stays in the current browser session and is not sent to TypingTester.io. You can export or delete local results from the statistics page.
Product actions expose an in-browser event hook with a per-event allowlist of aggregate dimensions such as mode, duration, corpus version, and score. The hook makes no network request on its own. Source passages, complete typed strings, custom content, keystrokes, and confusion-pair content are not permitted in its payloads.
Known limitations and changelog
Browser scheduling, device load, input method behavior, keyboard layout, and test length can affect a result. A local browser result does not verify identity, hardware, or test conditions. Use comparable settings and multiple samples when tracking progress.
Version 1.0.0 · 15 July 2026
Introduced one versioned pure scoring engine, actual elapsed time, latest-character completion, idempotent finalization, explicit corrected and uncorrected errors, and aggregate-only weak-key profiling.