Free JavaScript Keycode Finder
Press any key on your keyboard to see its JavaScript event properties.
Key History
How It Works
- Press any key: Click in the input area and press any key on your keyboard, letters, numbers, function keys, arrows, modifiers, or special keys.
- Read the key codes: The tool instantly displays the key's event.key, event.code, event.keyCode (legacy), and charCode values.
- Use in your code: Copy the exact values you need for your keyboard event listeners or shortcut implementations.
Why Use Keycode Finder?
JavaScript keyboard events expose several different properties (key, code, keyCode, charCode, and which) and knowing which to use and what value to compare against is consistently tricky. The KeyCode Finder eliminates guesswork by letting you press a key and immediately see all its event properties. This is invaluable for building keyboard shortcuts, handling special keys, implementing hotkeys, and debugging keyboard event listeners.
Features
- All event properties: Shows event.key, event.code, event.keyCode, event.which, and event.charCode for every keypress.
- Modifier key detection: Displays whether Shift, Ctrl, Alt, and Meta were held during the keypress.
- Special key support: Works with function keys (F1–F12), arrow keys, Enter, Escape, Tab, Backspace, and all other special keys.
- Key history: Keeps a log of recent keypresses so you can compare multiple keys.
- Copy values: Click any value to copy it directly to your clipboard.
Frequently Asked Questions
What is the difference between event.key and event.keyCode?
event.key is the modern standard, it returns a readable string like "ArrowLeft" or "Enter". event.keyCode is a legacy numeric code (deprecated but still supported). Use event.key for new code; use event.keyCode when maintaining older browser compatibility.
How do I detect Ctrl+S or other key combinations?
Keyboard combinations use event.key combined with modifier checks: if (event.ctrlKey && event.key === "s"). Press Ctrl+S in this tool to see all the values, then replicate the exact condition in your event listener.
Why do some keys show the same keyCode?
keyCode values were not standardized and some keys share codes depending on context. event.code is more reliable, it identifies the physical key position (e.g., "KeyA") regardless of the keyboard layout, while event.key reflects what character that key produces.
A 30-year history of keyboard events in JavaScript
Keyboard events have a notoriously messy history in the DOM. Netscape Navigator 2 (1995) introduced the original onkeydown, onkeypress, and onkeyup handlers with a numeric keyCode property, which had no spec; browsers each invented their own values. Internet Explorer 4 (1997) implemented its own variant with event.keyCode as the only property, while Netscape stuck with event.which. DOM Level 2 Events (W3C, November 2000) standardised event flow (capture/bubble) but explicitly punted on keyboard events because vendors couldn't agree. The result: developers wrote code like e.keyCode || e.which for over a decade. DOM Level 3 Events (W3C Working Draft 2003, Recommendation 2018) finally introduced the modern event.key (Unicode character or named key like «ArrowLeft») and event.code (physical key position like «KeyA», independent of layout), along with deprecating keyCode, charCode, and which. The UI Events specification (W3C, ongoing) is the modern home for this work. Browsers caught up gradually: Chrome 51 (May 2016), Firefox 47 (June 2016), Safari 10.1 (March 2017) all shipped event.code support. The legacy keypress event is deprecated in favour of beforeinput and input events.
The 5 properties, decoded
event.key(modern, use this). The character or named key produced. Letters and digits give you the Unicode character respecting modifiers and layout (Shift+a = «A», AZERTY Q-position = «a»). Named keys are strings like «Enter», «Escape», «ArrowLeft», «F5», «Control». Defined in UI Events.event.code(modern, use for games). Identifies the physical key on the keyboard, independent of layout or modifiers. Examples: «KeyA», «Digit1», «ArrowUp», «ShiftLeft», «MetaLeft». Use this for WASD movement, vim-style nav, and shortcuts that should ignore keyboard layout.event.keyCode(deprecated). Numeric code. 13 = Enter, 27 = Escape, 32 = Space, 37-40 = Arrow Left/Up/Right/Down, 65-90 = A-Z, 112-123 = F1-F12. Values were never standardised, only became consistent across browsers through convergence. Avoid in new code.event.which(deprecated). Netscape's equivalent of keyCode. For most printable characters and non-printable keys, identical to keyCode. The old polyfille.keyCode || e.whichhandled cases where one was 0.event.charCode(deprecated, only on keypress). The Unicode code point of the character.97for «a»,65for «A». Only fires onkeypress(which is itself deprecated). Theinputandbeforeinputevents are the modern replacements.- Modifier booleans.
event.shiftKey,event.ctrlKey,event.altKey,event.metaKey(Command on macOS, Windows key on Windows). Always check modifiers explicitly:e.metaKey || e.ctrlKeyfor cross-platform «save» (Cmd+S on Mac, Ctrl+S on Windows/Linux). event.location. Distinguishes left vs right modifiers and the numpad. 0=standard, 1=left modifier, 2=right modifier, 3=numpad. Useful for distinguishing left-Shift vs right-Shift for gaming layouts.
Where keycode lookup actually matters
- Application keyboard shortcuts. Cmd/Ctrl+S to save, Cmd/Ctrl+Z to undo, Cmd/Ctrl+K to open command palette (Slack, Linear, GitHub, Notion all use this since around 2020). Always use
event.keyfor the printable key and a modifier boolean for the meta key. - Command palette and fuzzy finder. The Cmd+K pattern popularised by Slack (2014) and Linear (2019). Listen for the open shortcut globally, then handle ArrowUp/ArrowDown navigation, Enter to select, Escape to dismiss.
- Browser games and HTML5 game development. Phaser, Babylon.js, Three.js. Always use
event.codefor movement keys so WASD works on AZERTY keyboards (where «W» is in the «Z» position). Sebastian Lague, Notch (early Minecraft prototype), and itch.io games all hit this AZERTY pitfall. - Accessibility patterns. Modal dialogs need Escape to close. Combobox widgets need ArrowDown/ArrowUp/Enter/Escape. Tooltips need to dismiss on Escape. The WAI-ARIA Authoring Practices Guide defines keyboard interaction patterns for every common widget;
event.keyis the standard for those checks. - Text editor and code editor implementation. Monaco (VS Code's editor in the browser), CodeMirror, ProseMirror, Lexical all map keyboard events to commands. They use
event.codefor vim/emacs-style key bindings that don't depend on layout. - Form UX enhancements. Submit on Enter, blur on Escape, advance focus on Tab. Common in checkout flows, search bars, autocomplete fields.
- Browser extension hotkeys. Vimium, SurfingKeys, Tridactyl provide keyboard navigation for the entire web. They listen at the document level and handle complex modal key sequences (gg = go to top, like vim).
Common mistakes in keyboard event handling
- Using
keyCodein new code. Deprecated since DOM Level 3 (2018), inconsistent across browsers historically, and breaks on non-US layouts (the comma key haskeyCode188 on US, 191 on some German keyboards). Useevent.keyinstead. - Hardcoding
e.key === "w"for game movement. On AZERTY (French) keyboards, the physical W key types «z». Players reach for what they remember as the WASD cluster but get the wrong input. Useevent.code === "KeyW"instead, which identifies the physical position. - Checking only
ctrlKeyfor «save». On macOS, Cmd+S is the convention;ctrlKeyis false butmetaKeyis true. Always check both:(e.metaKey || e.ctrlKey) && e.key === "s". - Forgetting
preventDefaulton browser-reserved shortcuts. Hijacking Cmd+S without preventDefault still triggers Save Page As. Same for Cmd+P (print), Ctrl+F (browser find), Ctrl+N (new window, can't be blocked anyway), Ctrl+Tab (Chrome won't let you). Calle.preventDefault()in the handler. - Ignoring IME composition. Japanese, Chinese, Korean input methods (IME) fire
keydownevents while the user is composing characters. Checke.isComposingor usecompositionendevent before firing your shortcut handler. Slack famously botched this for Japanese users in 2017. - Using deprecated
keypressevent. Fires only for character-producing keys (not arrow keys, function keys, etc.). Deprecated; usekeydownfor shortcuts andinput/beforeinputfor text changes. - Triggering shortcuts on every repeat. Holding down a key fires
keydownevents repeatedly. For toggle actions (open palette, switch tab), checke.repeatand bail early to avoid registering 30 «open» commands when the user accidentally held the key.
More frequently asked questions
Why doesn't my key handler fire when the user has a non-US keyboard?
Almost always because you're checking event.key for a character that only exists with Shift on that layout. On a German QWERTZ keyboard, «/» is Shift+7 (not its own key); on AZERTY French, digits 0-9 are typed with Shift+the-row-above. Use event.code (physical key) for position-based shortcuts, or event.key for content-based shortcuts (where you actually want the character the user just typed).
How do I handle Cmd+K / Ctrl+K consistently across platforms?
The standard idiom: if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") { e.preventDefault(); openPalette(); }. On macOS, e.metaKey is the Cmd key; on Windows/Linux, e.ctrlKey is what users expect. Accept both. Always preventDefault because the browser binds Cmd+K to «focus address bar» in some browsers. Add !e.repeat to avoid firing on key-hold.
Can JavaScript detect global keystrokes outside the page?
No, and this is by design for security. The browser only fires keyboard events for the focused page or element. Browser extensions can listen with broader scope using the chrome.commands API. Native apps in Electron, Tauri, etc., can use OS-level global hooks. Banking and 2FA apps rely on this isolation: a malicious tab cannot keylog your password manager.
What's the right way to detect «just pressed» vs «being held»?
For toggles, check !e.repeat in the keydown handler, the first event has repeat: false, subsequent auto-repeat events have repeat: true. For continuous actions (game movement), track key state in a Set: add on keydown, remove on keyup, then in your render loop check keysHeld.has("KeyW"). This decouples input from frame rate and handles multiple simultaneous keys (move + jump).
Is anything sent to a server when I press keys here?
No. Key events are captured locally by JavaScript and displayed on this page without any network request. Open the Network tab in DevTools, type away; you'll see zero outbound traffic. Safe for testing in any context, including discovering what passwords or sensitive shortcuts produce on your keyboard.