Rhythm says a lot about how a result was produced. People speed up and slow down, pause between words, make mistakes and fix them. Scripts tend not to. Recording that rhythm is useful, but only if it costs nothing while you type. A typing test that stutters to collect data about typing has failed at its main job.
Typestrix splits the work in two: almost nothing happens per keystroke, and the real analysis runs once, when the test is already over.
From keystroke to verdict
Pick a step, or use the arrows, to walk through the diagram.
The per-key cost is one subtraction
Each keystroke does three things: read a monotonic clock, subtract the previous timestamp, and push to an array. The data lives in refs rather than React state, so recording it never schedules a render. The running check is a single comparison and two counters.
performance.now() is used instead of Date.now() because it is monotonic and sub-millisecond: a system clock change during a test cannot distort the gaps.
What the analysis looks for
The scoring function combines several weak signals instead of trusting any single one:
- Uniformity. Human gaps between keys vary a lot. Near-identical gaps over a whole test are a strong machine pattern.
- Pauses. People pause between words and phrases. A run with no pauses at all, at speed, is unusual.
- Impossible bursts. Occasional very fast pairs are normal when two hands overlap. A sustained share of them is not.
- Corrections. Errors that are never corrected, at high speed, do not look like a person reacting to mistakes.
- Speed and accuracy together. At very high speeds, people make some mistakes. Near-perfect accuracy at extreme speed over a long test is rare.
- The chart. A per-second speed line that is unnaturally flat.
- Focus. Leaving the tab during a signed-in test, which also pauses the timer.
The rhythm signals only switch on at higher speeds, so slow and medium typists never trip them, and every signal is weak on its own. A fast, accurate human usually triggers one minor signal at most.
Focus is a separate channel
Switching tabs or windows during a signed-in test opens a "Test paused" dialog and stops the timer, and input is refused until you resume. The events are kept with timestamps for the final score. A blur can be innocent (a notification, a password manager), which is why it weighs little on its own.
What leaves the browser
None of the raw telemetry does. Timestamps, key values and focus events stay in memory on your device and are discarded when the next test starts. The server receives only the result itself: speed, accuracy, character counts and the per-second chart, and it runs its own independent checks on that.
That split is deliberate. Detailed rhythm data is useful for a quick local verdict, but it is also personal. Keeping it on the device means there is nothing to store, leak or explain later.
Heuristics, not proof
Every threshold here is a judgement, not a law of nature. Accessibility tools, unusual keyboards and input methods can produce patterns that look atypical. That is why the signals are weighted, gated and combined, and why the final word on what is saved belongs to the server, not to this score.