How browsers actually report a key press

KeyboardEvent gives you three overlapping answers about which key was pressed. Only one of them describes physical hardware.

Cover image for How browsers actually report a key press

When you press a key, the browser hands JavaScript a KeyboardEvent carrying several overlapping descriptions of what just happened. Choosing the wrong one is the single most common reason a key tester misbehaves.

The three properties

event.code identifies the physical key by its position on a US ANSI keyboard. Press the key to the right of Tab and you get KeyQ — on a QWERTY board, an AZERTY board, or a Dvorak board alike. It does not change with the active layout, and it does not change when you hold Shift.

event.key identifies the character produced. The same physical key gives q, then Q with Shift held, then a if the operating system is set to AZERTY. It answers “what did the user type”, not “which switch closed”.

event.keyCode is a deprecated numeric identifier. It still works in current browsers, but its values were never fully standardised and it conflates layout with position. New code should not use it.

Why a tester uses code

A key tester is asking a hardware question: did this switch register? That makes code the only correct choice. Using key would mean the same physical key lighting up different positions on screen depending on Shift state and OS layout — exactly the confusion a diagnostic tool should remove.

document.addEventListener("keydown", (event) => {
  // Physical position — stable across layouts and modifier state.
  markKeyAsWorking(event.code);
});

The keys that never arrive

Some keys produce no event at all, because they are resolved inside the keyboard’s own controller before anything reaches the host:

  • Fn on laptops and compact boards. Holding it changes what other keys report; it sends nothing itself.
  • Touch ID on Apple laptops, which is a sensor rather than a key.
  • Most vendor media and macro keys, which are handled by firmware or a driver.

No browser API can see these, so a tester that counts them in its total can never reach 100% on a perfectly healthy keyboard. Drawing them for visual accuracy while excluding them from the count is the honest compromise.

Suppressing the browser’s own shortcuts

To test Tab, F5, F11 or F12 you have to stop the browser acting on them first:

document.addEventListener("keydown", (event) => {
  event.preventDefault();
  // ...
});

This is a blunt instrument — it disables ordinary shortcuts for as long as the page has focus. That is an acceptable trade for a diagnostic tool, provided the page says so. It is not something a general-purpose site should do.

Back to all posts