Published 15 August 2026 · Last updated 15 August 2026
The same keyboard can produce very different numbers on two machines, in two browsers, or on the same machine ten minutes apart. That is not a flaw in the measurement — it is the measurement working correctly. A browser test times the software path between event creation and your JavaScript, and that path is shared with everything else the system is doing.
So the honest way to use a result is as a comparison against another taken under conditions you controlled. This guide lists what moves the number, roughly in order of impact, and ends with a protocol for a fair comparison.
| Variable | Rough impact | How to control it |
|---|---|---|
| Remote desktop or VM | Tens of ms, highly variable | Test on the physical machine |
| CPU load and background work | Small on the median, large on the tail | Close other apps and tabs |
| Power and thermal state | Can multiply the whole distribution | Plug in, use a high-performance plan |
| Timer resolution | Quantises everything; inflates apparent jitter | Keep the browser fixed; read the env panel |
| Browser engine and version | Around a millisecond, plus quantisation | Never compare across browsers |
| OS input stack and remappers | Sub-ms to several ms | Note what is installed; test with it off |
| Extensions and injected scripts | Usually small, occasionally severe | Use a clean browser profile |
| Refresh rate | Dominates the input-to-frame channel only | Compare like refresh rates |
| Focus and tab visibility | Samples become invalid entirely | Keep the window focused and foreground |
| Keyboard and its connection | Little to no effect on this metric | Expect no change; investigate if there is one |
Browser engine and version
Chromium, Gecko and WebKit each schedule input differently, split work across processes differently, and stamp events at slightly different points in their pipelines. They also coarsen their clocks by different amounts. Engine changes between versions are routine.
Expect a browser change alone to move a median by around a millisecond, and to change apparent jitter more than that if the timer resolution differs. Comparing a Chrome number against a Firefox number tells you nothing about your keyboard.
Timer resolution and cross-origin isolation
Every measurement here is limited by the smallest time difference the browser will express. Depending on the engine and configuration that may be around a tenth of a millisecond, or a full millisecond unless the page is cross-origin isolated, and some engines add jitter on top.
A 1 ms clock does not make the median wrong, but it snaps every sample onto a whole millisecond grid: real variation of 0.3 ms can appear as alternating 0 and 1 ms readings and produce a jitter figure that is entirely an artefact. Each measurement page probes the clock and prints the result, so read that panel before trusting a spread figure — the methodology page explains the probe.
Operating system and its input stack
Windows, macOS and Linux each hand input to applications through their own layers of filtering and routing. On top of that sit the things users install: vendor keyboard software, remapping utilities, macro tools, accessibility features, and security products that hook keyboard input for inspection.
Anything that inserts itself into the input path adds a hop before the browser ever sees the key. The base OS difference is usually small — sub-millisecond to a couple of milliseconds — but a badly behaved hook can add much more. If you suspect one, the cleanest test is to measure with it running and again with it disabled, changing nothing else.
CPU load and scheduling
This is the largest controllable factor on most machines. A page's JavaScript runs on one thread and a running task cannot be interrupted, so an event arriving during a long task waits for it to finish. A compile, a video call, a sync client or an animating tab all compete for the same cores.
The signature is distinctive: the median barely moves while the 90th and 95th percentiles climb sharply, because most events still get through quickly and a minority get stuck behind something. If your tail is much larger than your median, look at what else the machine is doing before you look at the keyboard.
Power and thermal state
An unplugged laptop on a battery-saver profile is a different computer. Clock speeds drop, work migrates to efficiency cores, and sustained load adds thermal throttling on top. This scales the whole distribution rather than adding a fixed offset — a result that doubles when the charger comes out is completely plausible.
Plug in, use the same power profile for both halves of a comparison, and let the machine settle rather than testing thirty seconds after a heavy task.
GPU, compositor and refresh rate
Refresh rate barely touches the event latency channel, because that number is finished before anything is drawn. It dominates the input-to-frame channel. At 60 Hz frames are 16.7 ms apart, so an event arriving at a random moment waits about 8.3 ms on average for the next one; at 144 Hz the frame is 6.9 ms and at 240 Hz it is 4.2 ms. Variable refresh rate makes the interval move during the test.
Comparing input-to-frame across two displays is mostly comparing the displays; use the event latency channel instead, or hold the refresh rate constant.
Page focus and tab visibility
Browsers throttle work in hidden or unfocused tabs, and a key press delivered to an unfocused window does not describe your normal typing at all. Rather than let those samples quietly distort a result, the collector excludes them and says so — each one is recorded with a reason and reported in the exclusion summary, and losing focus mid-test lowers the reported test quality.
Extensions and injected scripts
Extensions inject content scripts into pages, and some register their own keyboard listeners — password managers, form fillers, shortcut managers, translation tools. Those listeners run on the same main thread, and the usual cost is a fraction of a millisecond, though an extension doing real work on every keystroke can add several.
The fix is straightforward: repeat the test in a clean profile or a private window with extensions disabled. A large difference between the two is a genuine finding about your setup.
Virtual machines and remote desktop
This is the one that invalidates everything. Remote desktop protocols capture input on the client, send it over a network, and replay it on the host — often batched, and always subject to network conditions. Virtual machines add a virtualised input device and a hypervisor scheduler.
Expect tens of milliseconds of added latency and a wildly inconsistent distribution. A result taken over a remote session describes the session, not the keyboard or even the host machine. If your numbers look strange and you are connected remotely, that is your answer.
The keyboard's own connection
Here is the counter-intuitive one. Switching from a wired keyboard to Bluetooth, or from one board to another, usually does not move the browser-observed event latency much. The measurement starts when the browser creates the event, so anything the transport added has already happened and is invisible — it shifts the true end-to-end delay without appearing in this number at all.
So if changing keyboards does change your browser result substantially, the likely cause is software rather than the transport: a different driver, vendor software, a KVM or hub that re-enumerates the device, or a remapping layer that only runs for one of them. That is worth knowing, and it is exactly the kind of thing this test can surface. Why the transport itself is invisible is covered in why browser tests can't measure hardware latency.
A protocol for a fair comparison
To make two measurements genuinely comparable, hold everything constant except the one variable you are testing:
- Same physical machine, tested locally — never over remote desktop or inside a VM.
- Same browser and same version, in the same profile state (both clean, or both normal).
- Mains power, same power plan, and a machine that has been idle for a minute rather than just finished a heavy task.
- Close other applications and other tabs. Nothing syncing, compiling, updating or playing video.
- Window focused and in the foreground for the whole run. Do not alt-tab mid-test.
- At least 30 valid samples per run — fewer than 10 is not a result, and percentiles need a reasonable count to mean anything.
- Use the same key or set of keys, pressed at a similar deliberate rhythm, for both runs.
- Run each condition three times and use the median of the medians. A single run can be unlucky.
- Change exactly one variable between conditions.
- Record the measurement environment panel alongside each result, so you can tell later whether the clock resolution was the same.
Then compare properly. Look at the median and the spread together, never the fastest single sample — the minimum is a lottery win, not a capability. If two medians differ by less than the interquartile range of either run, treat that as noise rather than a finding. The session comparison tool lines two saved runs up so you can read medians, percentiles and consistency side by side.
Start by running the keyboard latency test and noting the quality label it reports. If it says the sample count is low or that focus was lost, fix that first — no amount of comparison logic rescues a bad run.