guide

Keyboard Test Guide

A reference for the desktest.net Keyboard Test. Covers how the visual keymap reads input, how to read the verdict, and what to do about stuck keys, missing keys, and dead modifier combos.

Open the Keyboard Test ->

What does the Keyboard Test check?

The tool drives the browser's standard KeyboardEvent API: capture-mode keydown and keyup listeners attached at the document level, keyed off KeyboardEvent.code so the physical key position stays stable across QWERTY, AZERTY, and Dvorak. No plugin, no extension, no upload. Works on Chrome, Edge, Firefox, and Safari. The three steps run in order; each must pass before the next:

  1. Keyboard event API fires. Feature-detects window.KeyboardEvent, confirms code and key properties are present, and attaches a passive watch so any real keystroke during the run gets counted. Also notes whether the page is loaded inside an iframe (some embedded shells swallow keys).
  2. Every key registers. Renders a 104-key US ANSI visual keymap: function row, number row, QWERTY block, ASDF row, ZXCV row, bottom row with modifiers and Space, plus the nav cluster (Insert, Home, PgUp, Delete, End, PgDn, arrows) and the numpad. You press each key; the matching tile turns green. event.repeat is filtered so the OS auto-repeat does not double-count. If a tile receives keydown but no keyup within 2 seconds, it turns red and is flagged stuck.
  3. Modifier combos work. Four combos: Shift+A, Ctrl+C, Ctrl+Shift+P, and CapsLock on its own. Ctrl+C and Ctrl+Shift+P call preventDefault() so they do not copy from the page or trigger Chrome's print dialog. Alt+Tab is deliberately skipped because the OS grabs it before the browser sees it.

When should I run this?

Reading the results

The visual keymap uses three colors. Green means a key fired keydown and (eventually) keyup cleanly. Red means a key fired keydown but did not fire keyup within 2 seconds: stuck. Blue marks the modifier keys (Shift, Ctrl, Alt, Win) as a hint that those tiles are special; once pressed, they turn green like any other.

The running counter under the prompt shows X / 104 keys verified. A second strong-red number appears for stuck keys when there are any. You do not have to hit all 104; click Done when you have covered the keys you care about. Anything under 60 unique keys triggers a partial verdict rather than a pass, so the report does not lie about coverage.

Modifier combos render as a list. Each row turns green when the combo is detected. Ctrl+C is intercepted so it does not copy the page text; Ctrl+Shift+P is intercepted so it does not pop Chrome's print preview.

Each row has a status badge: Pending (grey), Running (yellow), Pass (green), Partial (yellow), or Fail (red). On fail or partial the row expands with the diagnosis and a numbered checklist. The verdict panel at the top names the most likely cause and a recommended next step.

Copy Diagnostic Report copies a plain-text report: browser user-agent, platform, per-step results, every key code that registered, every code that stuck, modifier-combo outcomes, and the diagnosis tag from each step. Paste it into a ticket.

Common failures and fixes

The tool produces a named diagnosis for every failure path. Each maps to a fix. In step order:

no-keyboard-api / no-code-property: no keyboard events reach the page

The browser either does not expose KeyboardEvent, or code is missing from the constructed event. On modern desktop browsers this almost never happens by itself; something has intercepted the event flow before the page sees it.

  1. Focus is somewhere else. Click anywhere on the page first. If the address bar or a browser dev panel has focus, keydown never reaches the document. The test moves focus to a hidden input on Run, but a click outside the tab will steal it.
  2. A browser extension is blocking input. Vimium, SurfingKeys, Tridactyl, and similar keyboard-driven extensions hijack keys at capture phase. Open the test in an incognito or private window with extensions disabled, or whitelist desktest.net in the extension's options.
  3. OS accessibility is intercepting. Windows Speech Recognition, macOS Voice Control, and screen readers in input modes can swallow keys. Toggle them off for the duration of the test.
  4. Page is in an embedded shell. If you opened the test through a kiosk wrapper, an Electron host, or an in-app browser (Slack, Teams preview), open it in a real browser tab instead.

partial-keymap: fewer than 60 keys verified

The keymap recorded under 60 unique keydown events before Done. Two cases:

  1. You clicked Done early. The common one. Rerun and cover the function row (F1 through F12), the entire number row, both Shift keys, both Ctrl keys, Space, Enter, Backspace, and the arrow cluster. Numpad keys are separate from the number row in KeyboardEvent.code (Numpad7 vs Digit7); press both.
  2. Keys really are missing. Isolate by category. First, common-typing keys (letters, Space, Enter, Backspace, Shift, Ctrl). If any of those fail, the keyboard is broken for normal use. Next, the function row (F1 through F12). Many compact keyboards (60%, 65%, 75%) require an Fn-layer combo for F-keys, and the Fn key itself does not emit a KeyboardEvent.code; press the F-key directly, not via Fn. Last, media keys (Mute, Volume, Play). These often emit no event at all because the OS or the keyboard firmware consumes them before the browser layer; that is normal and not a failure of the keyboard itself.

Tip: if a specific letter dies, try a different USB port and, for Bluetooth keyboards, repair the device. A flaky USB cable will drop random scancodes under load.

stuck-keys: key fired keydown without keyup

A code stayed asserted for over 2 seconds without a release event. The most common causes:

  1. Physical key stuck under a crumb. Hair, dried liquid, or grit under the keycap. Pop the cap (most keycaps lift with a fingernail or a wire puller), blow out the switch with a can of compressed air, and reseat the cap. On low-profile laptop scissor switches do not pry hard; the plastic hinges are brittle.
  2. An OS-level keyboard remapper is masking the real key state. SharpKeys writes a Scancode Map to HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layout and remaps at the kernel level. Microsoft PowerToys Keyboard Manager remaps in user space. AutoHotkey scripts that use $ or SendInput can hold keys in an unexpected state. Quit the remapper, reboot if it was SharpKeys (its remap survives until the registry value is removed and the system reboots), and rerun.
  3. Spilled liquid that dried under the membrane. Sugar from soft drinks is the classic killer. The switch never opens because the contact pad is glued shut. On a membrane keyboard this usually means the whole board is done. On a mechanical board, hot-swap the affected switch.
  4. Mechanical switch dying. Cherry MX switches are rated for 50 to 100 million keypresses; cheaper clones much less. A switch that randomly chatters or holds is at end of life. Hot-swap or solder a new one in.
  5. macOS Press and Hold. System Settings, Keyboard, Press and Hold... If on, holding a vowel pops an accent menu; the OS holds the key. Turn it off for testing.

missing-combos: modifier combinations not detected

One or more of Shift+A, Ctrl+C, Ctrl+Shift+P, CapsLock failed to register. Patterns:

  1. A modifier is physically dead. If Shift+A fails but Shift lit green in the keymap, the keyboard is reporting Shift as a keystroke but not as a modifier flag. Rare and usually means a custom firmware (QMK / VIA) layer is wrong. If Shift did not light green in step 2 either, the Shift key is dead. Try the opposite Shift; ShiftLeft and ShiftRight are separate codes.
  2. AutoHotkey is intercepting. A running AHK script with a hotkey like ^c:: or ^+p:: consumes the combo before the browser sees it. Right-click the AHK tray icon, Suspend Hotkeys, rerun. PowerToys with a Shortcut Guide or remap on the same combo behaves the same.
  3. A password manager is intercepting. 1Password, Bitwarden, and Dashlane bind global shortcuts; Ctrl+Shift+P in particular collides with Bitwarden's Lock command on some installs. Open the extension's settings and either reassign or disable the global shortcut.
  4. macOS Caps Lock toggle. macOS treats Caps Lock as a slow toggle by default: a short tap is ignored, only a held press flips state. If CapsLock does not register, tap and hold for half a second, or in System Settings, Keyboard, Modifier Keys, set Caps Lock to act normally.
  5. Windows Sticky Keys. Five rapid Shift presses turns Sticky Keys on; the modifier then latches instead of being held, which changes how the browser sees the modifier flag on a follow-up letter. In Settings, Accessibility, Keyboard, turn Sticky Keys off. Filter Keys can also drop modifier presses below its hold-down threshold; turn it off.

Barcode-scanner-as-keyboard quirks

USB barcode scanners that present as HID keyboards (Honeywell Voyager, Zebra DS2208, Datalogic QuickScan, generic Symcode units) feed scans as a burst of keydown / keyup pairs followed by an Enter. A few specifics when running this test with a scanner connected:

For IT admins

Keyboard input behavior is governed at three layers: hardware (the keyboard or scanner firmware), OS (driver, accessibility, layout), and per-app (browser, remappers, scripts). The test sees only the last layer's view, but the failure pattern tells you which lower layer to look at.

Windows Scancode Map. Kernel-level remap lives at HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layout, value Scancode Map (REG_BINARY). SharpKeys writes here. The remap applies to every user on the machine and survives until the value is deleted and the machine reboots. For shared workstations (kiosks, branch tills, call-center seats), baseline the image with no Scancode Map and block users from writing one via Group Policy on the parent key.

Group Policy for accessibility. Sticky Keys, Filter Keys, and Toggle Keys live under Computer Configuration, Administrative Templates, Control Panel, Personalization on newer templates, and in user mode under Ease of Access Center settings. Push them off on shared workstations: Filter Keys in particular can silently drop short keypresses, which looks identical to a dying keyboard.

Known hardware quirks. Logitech Unifying receivers can drop modifier events when paired with more than four devices on the same dongle; pair the keyboard to its own receiver. Microsoft Surface Type Cover firmware has shipped revisions that misreport Fn-layer keys; the Surface app updates firmware separately from Windows Update, so check it explicitly. Mechanical keyboards running custom firmware can be inspected with VIA Configurator (or its successor, Vial) for VIA-compatible boards, and with the QMK Toolbox plus a JSON keymap for QMK firmware; a wrong layout JSON will silently swap codes.

Recommended baseline. For shared workstations, no third-party keyboard remapper (no SharpKeys, no AutoHotkey on startup, no PowerToys Keyboard Manager). Sticky Keys, Filter Keys, Toggle Keys off. Native US (or local) layout only. The test then reports the keyboard's real state, not the state filtered through a stack of user tools.

Behind the scenes

The tool keys everything off KeyboardEvent.code, not KeyboardEvent.key. code is the physical key location: KeyA is the key second from the left on the ASDF row, regardless of whether the layout is QWERTY or AZERTY. key is the character that would be produced, which changes with modifiers (Shift+a vs a), layout (AZERTY a is at physical KeyQ), and dead-key state (the dieresis dead key followed by a is "a-umlaut"). For a hardware test we want the physical key, so code wins.

Listeners attach at the document level in capture phase so we see every event before any in-page handler can stopPropagation(). event.repeat is filtered so OS auto-repeat (typically 30 ms after a 500 ms hold on Windows defaults) does not register as multiple presses. Tab, Backspace, and Space get preventDefault() so Tab does not move focus away, Backspace does not navigate back (a Firefox default until v86), and Space does not scroll.

Stuck-key detection is a 2-second timer started on keydown and cleared on keyup. If the timer fires first, the code is flagged stuck and turns red. A subsequent clean keyup clears the flag and turns it green; the diagnostic records both the moment of stuck-state and the recovery in the report.

Step 3 combos call preventDefault() on Ctrl+C and Ctrl+Shift+P only after they match, so an unrelated Ctrl+Shift+P outside the combo phase still pops the browser's print preview. Alt+Tab is intentionally not in the combo list because Windows and macOS grab it at the window-manager layer before the browser sees it; testing it here would always fail and tell you nothing useful.

Nothing leaves the browser tab. No keystroke is logged to a server, no telemetry beacon is fired, no analytics. The diagnostic report is built on Copy from in-memory state, and the page discards everything on reload. Open DevTools, Network tab, and confirm: no outbound requests while the test runs.