Code values for keyboard events - Web APIs

Code values for keyboard events
===============================

The following tables show what code values are used for each native scancode or virtual keycode on major platforms. The reason is that some browsers choose to interpret physical keys differently, there are some differences in which keys map to which codes. These tables show those variations when known.

Code values on Windows
----------------------

This table shows the Windows scan codes representing keys and the `KeyboardEvent.code` values which correspond to those hardware keys. Only keys which generate scan codes on Windows are listed.

 In the cells, "(❌ Missing)" means that this code value cannot be detected on this browser;
 "(⚠ Not the same on xyz)" means that this string represents a different code value on the browser xyz and that special care has to be done
 when using it.

|  | **`KeyboardEvent.code`** value |
| --- | --- |
| Code | Firefox | Chrome |
| `0x0000` | `"Unidentified"` | `""` |
| `0x0001` | `"Escape"` | `"Escape"` |
| `0x0002` | `"Digit1"` | `"Digit1"` |
| `0x0003` | `"Digit2"` | `"Digit2"` |
| `0x0004` | `"Digit3"` | `"Digit3"` |
| `0x0005` | `"Digit4"` | `"Digit4"` |
| `0x0006` | `"Digit5"` | `"Digit5"` |
| `0x0007` | `"Digit6"` | `"Digit6"` |
| `0x0008` | `"Digit7"` | `"Digit7"` |
| `0x0009` | `"Digit8"` | `"Digit8"` |
| `0x000A` | `"Digit9"` | `"Digit9"` |
| `0x000B` | `"Digit0"` | `"Digit0"` |
| `0x000C` | `"Minus"` | `"Minus"` |
| `0x000D` | `"Equal"` | `"Equal"` |
| `0x000E` | `"Backspace"` | `"Backspace"` |
| `0x000F` | `"Tab"` | `"Tab"` |
| `0x0010` | `"KeyQ"` | `"KeyQ"` |
| `0x0011` | `"KeyW"` | `"KeyW"` |
| `0x0012` | `"KeyE"` | `"KeyE"` |
| `0x0013` | `"KeyR"` | `"KeyR"` |
| `0x0014` | `"KeyT"` | `"KeyT"` |
| `0x0015` | `"KeyY"` | `"KeyY"` |
| `0x0016` | `"KeyU"` | `"KeyU"` |
| `0x0017` | `"KeyI"` | `"KeyI"` |
| `0x0018` | `"KeyO"` | `"KeyO"` |
| `0x0019` | `"KeyP"` | `"KeyP"` |
| `0x001A` | `"BracketLeft"` | `"BracketLeft"` |
| `0x001B` | `"BracketRight"` | `"BracketRight"` |
| `0x001C` | `"Enter"` | `"Enter"` |
| `0x001D` | `"ControlLeft"` | `"ControlLeft"` |
| `0x001E` | `"KeyA"` | `"KeyA"` |
| `0x001F` | `"KeyS"` | `"KeyS"` |
| `0x0020` | `"KeyD"` | `"KeyD"` |
| `0x0021` | `"KeyF"` | `"KeyF"` |
| `0x0022` | `"KeyG"` | `"KeyG"` |
| `0x0023` | `"KeyH"` | `"KeyH"` |
| `0x0024` | `"KeyJ"` | `"KeyJ"` |
| `0x0025` | `"KeyK"` | `"KeyK"` |
| `0x0026` | `"KeyL"` | `"KeyL"` |
| `0x0027` | `"Semicolon"` | `"Semicolon"` |
| `0x0028` | `"Quote"` | `"Quote"` |
| `0x0029` | `"Backquote"` | `"Backquote"` |
| `0x002A` | `"ShiftLeft"` | `"ShiftLeft"` |
| `0x002B` | `"Backslash"` | `"Backslash"` |
| `0x002C` | `"KeyZ"` | `"KeyZ"` |
| `0x002D` | `"KeyX"` | `"KeyX"` |
| `0x002E` | `"KeyC"` | `"KeyC"` |
| `0x002F` | `"KeyV"` | `"KeyV"` |
| `0x0030` | `"KeyB"` | `"KeyB"` |
| `0x0031` | `"KeyN"` | `"KeyN"` |
| `0x0032` | `"KeyM"` | `"KeyM"` |
| `0x0033` | `"Comma"` | `"Comma"` |
| `0x0034` | `"Period"` | `"Period"` |
| `0x0035` | `"Slash"` | `"Slash"` |
| `0x0036` | `"ShiftRight"` | `"ShiftRight"` |
| `0x0037` | `"NumpadMultiply"` | `"NumpadMultiply"` |
| `0x0038` | `"AltLeft"` | `"AltLeft"` |
| `0x0039` | `"Space"` | `"Space"` |
| `0x003A` | `"CapsLock"` | `"CapsLock"` |
| `0x003B` | `"F1"` | `"F1"` |
| `0x003C` | `"F2"` | `"F2"` |
| `0x003D` | `"F3"` | `"F3"` |
| `0x003E` | `"F4"` | `"F4"` |
| `0x003F` | `"F5"` | `"F5"` |
| `0x0040` | `"F6"` | `"F6"` |
| `0x0041` | `"F7"` | `"F7"` |
| `0x0042` | `"F8"` | `"F8"` |
| `0x0043` | `"F9"` | `"F9"` |
| `0x0044` | `"F10"` | `"F10"` |
| `0x0045` | `"Pause"` | `"Pause"` |
| `0x0046` | `"ScrollLock"` | `"ScrollLock"` |
| `0x0047` | `"Numpad7"` | `"Numpad7"` |
| `0x0048` | `"Numpad8"` | `"Numpad8"` |
| `0x0049` | `"Numpad9"` | `"Numpad9"` |
| `0x004A` | `"NumpadSubtract"` | `"NumpadSubtract"` |
| `0x004B` | `"Numpad4"` | `"Numpad4"` |
| `0x004C` | `"Numpad5"` | `"Numpad5"` |
| `0x004D` | `"Numpad6"` | `"Numpad6"` |
| `0x004E` | `"NumpadAdd"` | `"NumpadAdd"` |
| `0x004F` | `"Numpad1"` | `"Numpad1"` |
| `0x0050` | `"Numpad2"` | `"Numpad2"` |
| `0x0051` | `"Numpad3"` | `"Numpad3"` |
| `0x0052` | `"Numpad0"` | `"Numpad0"` |
| `0x0053` | `"NumpadDecimal"` | `"NumpadDecimal"` |
| `0x0054 (`Alt` + `PrintScreen`)` | `"PrintScreen"` (⚠ Not the same on Chrome) | `""` (❌ Missing) |
| `0x0055` | `"Unidentified"` | `""` |
| `0x0056` | `"IntlBackslash"` | `"IntlBackslash"` |
| `0x0057` | `"F11"` | `"F11"` |
| `0x0058` | `"F12"` | `"F12"` |
| `0x0059` | `"NumpadEqual"` | `"NumpadEqual"` (was `""` prior to Chrome 48) |
| `0x005A` | `"Unidentified"` | `""` |
| `0x005B` | `"Unidentified"` | `""` (was `"F13"` prior to Chrome 48) |
| `0x005C` | `"Unidentified"` | `""` (was `"F14"` prior to Chrome 48) |
| `0x005D` | `"Unidentified"` | `""` (was `"F15"` prior to Chrome 48) |
| `0x005E` | `"Unidentified"` | `""` |
| `0x005F` | `"Unidentified"` | `""` |
| `0x0060` | `"Unidentified"` | `""` |
| `0x0061` | `"Unidentified"` | `""` |
| `0x0062` | `"Unidentified"` | `""` |
| `0x0063` | `"Unidentified"` | `""` (was `"F16"` prior to Chrome 48) |
| `0x0064` | `"F13"` | `"F13"` (was `"F17"` prior to Chrome 48) |
| `0x0065` | `"F14"` | `"F14"` (was `"F18"` prior to Chrome 48) |
| `0x0066` | `"F15"` | `"F15"` (was `"F19"` prior to Chrome 48) |
| `0x0067` | `"F16"` | `"F16"` (was `"F20"` prior to Chrome 48) |
| `0x0068` | `"F17"` | `"F17"` (was `"F21"` prior to Chrome 48) |
| `0x0069` | `"F18"` | `"F18"` (was `"F22"` prior to Chrome 48) |
| `0x006A` | `"F19"` | `"F19"` (was `"F23"` prior to Chrome 48) |
| `0x006B` | `"F20"` | `"F20"` (was `"F24"` prior to Chrome 48) |
| `0x006C` | `"F21"` | `"F21"` (was `""` prior to Chrome 48) |
| `0x006D` | `"F22"` | `"F22"` (was `""` prior to Chrome 48) |
| `0x006E` | `"F23"` | `"F23"` (was `""` prior to Chrome 48) |
| `0x006F` | `"Unidentified"` | `""` |
| `0x0070` | `"KanaMode"` | `"KanaMode"` (was `""` prior to Chrome 48) |
| `0x0071` (`Hanja` key without Korean keyboard
 layout)
  | `"Lang2"` | `"Lang2"` (was `""` prior to Chrome 48) |
| `0x0072` (`Han/Yeong` key without Korean keyboard
 layout)
  | `"Lang1"` | `"Lang1"` (was `""` prior to Chrome 48) |
| `0x0073` | `"IntlRo"` | `"IntlRo"` (was `""` prior to Chrome 48) |
| `0x0074`, `0x0075` | `"Unidentified"` | `""` |
| `0x0076` | `"F24"` | `"F24"` (was `""` prior to Chrome 48) |
| `0x0077` | `"Unidentified"` (❌ Missing) | `"Lang4"` (was `""` prior to Chrome 48) (⚠ Not the same on Firefox) |
| `0x0078` | `"Unidentified"` (❌ Missing) | `"Lang3"` (was `""` prior to Chrome 48) (⚠ Not the same on Firefox) |
| `0x0079` | `"Convert"` | `"Convert"` (was `""` prior to Chrome 48) |
| `0x007A` | `"Unidentified"` | `""` |
| `0x007B` | `"NonConvert"` | `"NonConvert"` (was `""` prior to Chrome 48) |
| `0x007C` | `"Unidentified"` | `""` |
| `0x007D` | `"IntlYen"` | `"IntlYen"` |
| `0x007E` | `"NumpadComma"` | `"NumpadComma"` (was `""` prior to Chrome 48) |
| `0x007F` | `"Unidentified"` | `""` |
| `0xE000` ～ `0xE007` | `"Unidentified"` | `""` |
| `0xE008` | `"Unidentified"` (❌ Missing) | `"Undo"` (⚠ Not the same on Firefox) |
| `0xE009` | `"Unidentified"` | `""` |
| `0xE00A` | `""` (❌ Missing) | `"Paste"` (⚠ Not the same on Firefox) |
| `0xE00B` ～ `0xE00F` | "" | `""` |
| `0xE010` | `"MediaTrackPrevious"` | `"MediaTrackPrevious"` |
| `0xE011` ～ `0xE016` | `""` | `""` |
| `0xE017` | `"Unidentified"` (❌ Missing) | `"Cut"` (⚠ Not the same on Firefox) |
| `0xE018` | `"Unidentified"` (❌ Missing) | `"Copy"` (⚠ Not the same on Firefox) |
| `0xE019` | `"MediaTrackNext"` | `"MediaTrackNext"` |
| `0xE01A, 0xE01B` | `"Unidentified"` | `""` |
| `0xE01C` | `"NumpadEnter"` | `"NumpadEnter"` |
| `0xE01D` | `"ControlRight"` | `"ControlRight"` |
| `0xE01E` | `"Unidentified"` | `""` (was `"LaunchMail"` prior to Chrome 48) |
| `0xE01F` | `"Unidentified"` | `""` |
| `0xE020` | `"AudioVolumeMute"` | `"AudioVolumeMute"` |
| `0xE021` | `"LaunchApp2"` | `"LaunchApp2"` (was `""` prior to Chrome 48) |
| `0xE022` | `"MediaPlayPause"` | `"MediaPlayPause"` |
| `0xE023` | `"Unidentified"` | `""` |
| `0xE024` | `"MediaStop"` | `"MediaStop"` |
| `0xE025` ～ `0xE02B` | `"Unidentified"` | `""` |
| `0xE02C` | `"Unidentified"` (❌ Missing) | `"Eject"` (⚠ Not the same on Firefox) |
| `0xE02D` | `"Unidentified"` | `""` |
| `0xE02E` | `"VolumeDown"` (⚠ Not the same on Chrome) | `"AudioVolumeDown"` (was `"VolumeDown"` prior to
 Chrome 52) (⚠ Not the same on Firefox)
  |
| `0xE02F` | `"Unidentified"` | `""` |
| `0xE030` | `"VolumeUp"` (⚠ Not the same on Chrome) | `"AudioVolumeUp"` (was `"VolumeUp"` prior to Chrome
 52) (⚠ Not the same on Firefox)
  |
| `0xE031` | `"Unidentified"` | `""` |
| `0xE032` | `"BrowserHome"` | `"BrowserHome"` |
| `0xE033`, `0xE034` | `"Unidentified"` | `""` |
| `0xE035` | `"NumpadDivide"` | `"NumpadDivide"` |
| `0xE036` | `"Unidentified"` | `""` |
| `0xE037` | `"PrintScreen"` | `"PrintScreen"` |
| `0xE038` | `"AltRight"` | `"AltRight"` |
| `0xE039`, `0xE03A` | `"Unidentified"` | `""` |
| `0xE03B` | `"Unidentified"` (❌ Missing) | `"Help"` (⚠ Not the same on Firefox) |
| `0xE03C`～ `0xE044` | `"Unidentified"` | `""` |
| `0xE045` | `"NumLock"` | `"NumLock"` |
| `0xE046` (`Ctrl` + `Pause`) | `"Pause"` | `"Pause"` |
| `0xE047` | `"Home"` | `"Home"` |
| `0xE048` | `"ArrowUp"` | `"ArrowUp"` |
| `0xE049` | `"PageUp"` | `"PageUp"` |
| `0xE04A` | `"Unidentified"` | `""` |
| `0xE04B` | `"ArrowLeft"` | `"ArrowLeft"` |
| `0xE04C` | `"Unidentified"` | `""` |
| `0xE04D` | `"ArrowRight"` | `"ArrowRight"` |
| `0xE04E` | `"Unidentified"` | `""` |
| `0xE04F` | `"End"` | `"End"` |
| `0xE050` | `"ArrowDown"` | `"ArrowDown"` |
| `0xE051` | `"PageDown"` | `"PageDown"` |
| `0xE052` | `"Insert"` | `"Insert"` |
| `0xE053` | `"Delete"` | `"Delete"` |
| `0xE054` ～ `0xE05A` | `"Unidentified"` | `""` |
| `0xE05B` | `"MetaLeft"` (was `"OSLeft"` prior to Firefox 118) | `"MetaLeft"` (was `"OSLeft"` prior to Chrome 52) |
| `0xE05C` | `"MetaRight"` (was `"OSRight"` prior to Firefox 118) | `"MetaRight"` (was `"OSRight"` prior to Chrome 52) |
| `0xE05D` | `"ContextMenu"` | `"ContextMenu"` |
| `0xE05E` | `"Power"` | `"Power"` (was `""` prior to Chrome 48) |
| `0xE05F` | `"Unidentified"` (❌ Missing) | `"Sleep"` (was `""` prior to Chrome 48) (⚠ Not the same on Firefox) |
| `0xE060` ～ `0xE062` | `"Unidentified"` | `""` |
| `0xE063` | `"Unidentified"` (❌ Missing) | `"WakeUp"` (was `""` prior to Chrome 48) (⚠ Not the same on Firefox) |
| `0xE064` | `"Unidentified"` | `""` |
| `0xE065` | `"BrowserSearch"` | `"BrowserSearch"` |
| `0xE066` | `"BrowserFavorites"` | `"BrowserFavorites"` |
| `0xE067` | `"BrowserRefresh"` | `"BrowserRefresh"` |
| `0xE068` | `"BrowserStop"` | `"BrowserStop"` |
| `0xE069` | `"BrowserForward"` | `"BrowserForward"` |
| `0xE06A` | `"BrowserBack"` | `"BrowserBack"` |
| `0xE06B` | `"LaunchApp1"` | `"LaunchApp1"` (was `""` prior to Chrome 48) |
| `0xE06C` | `"LaunchMail"` | `"LaunchMail"` (was `""` prior to Chrome 48) |
| `0xE06D` | `"MediaSelect"` | `"MediaSelect"` (was `""` prior to Chrome 48) |
| `0xE06E ～ 0xE0F0` | `"Unidentified"` | `""` |
| `0xE0F1` (`Hanja` key with Korean keyboard layout) | `"Lang2"` (⚠ Not the same on Chrome) | `""` (❌ Missing) |
| `0xE0F2` (`Han/Yeong` key with Korean keyboard
 layout)
  | `"Lang1"` (⚠ Not the same on Chrome) | `""` (❌ Missing) |

Code values on Mac
------------------

 On macOS, it's hard to get scancode or something which can distinguish a physical key from a key event.
 Therefore, Firefox always maps `code` value from the virtual keycode.

In the cells,

* "(❌ Missing)" means that this code value cannot be detected on this browser;
* "(⚠ Not the same on xyz)" means that this string represents a different code value on the browser xyz and that special care has to be done
 when using it;
* "(⚠ Same string for `0xab`)" means that you cannot distinguished this key with the one matching `0xab`;
* "(⚠ No events fired actually)" means that even if technically you have a specific string for this code, no event will be dispatched;

| Virtual keycode | Firefox | Chromium |
| --- | --- | --- |
| `kVK_ANSI_A (0x00)` | `"KeyA"` | `"KeyA"` |
| `kVK_ANSI_S (0x01)` | `"KeyS"` | `"KeyS"` |
| `kVK_ANSI_D (0x02)` | `"KeyD"` | `"KeyD"` |
| `kVK_ANSI_F (0x03)` | `"KeyF"` | `"KeyF"` |
| `kVK_ANSI_H (0x04)` | `"KeyH"` | `"KeyH"` |
| `kVK_ANSI_G (0x05)` | `"KeyG"` | `"KeyG"` |
| `kVK_ANSI_Z (0x06)` | `"KeyZ"` | `"KeyZ"` |
| `kVK_ANSI_X (0x07)` | `"KeyX"` | `"KeyX"` |
| `kVK_ANSI_C (0x08)` | `"KeyC"` | `"KeyC"` |
| `kVK_ANSI_V (0x09)` | `"KeyV"` | `"KeyV"` |
| `kVK_ISO_Section (0x0A)` | `"IntlBackslash"` | `"IntlBackslash"` |
| `kVK_ANSI_B (0x0B)` | `"KeyB"` | `"KeyB"` |
| `kVK_ANSI_Q (0x0C)` | `"KeyQ"` | `"KeyQ"` |
| `kVK_ANSI_W (0x0D)` | `"KeyW"` | `"KeyW"` |
| `kVK_ANSI_E (0x0E)` | `"KeyE"` | `"KeyE"` |
| `kVK_ANSI_R (0x0F)` | `"KeyR"` | `"KeyR"` |
| `kVK_ANSI_Y (0x10)` | `"KeyY"` | `"KeyY"` |
| `kVK_ANSI_T (0x11)` | `"KeyT"` | `"KeyT"` |
| `kVK_ANSI_1 (0x12)` | `"Digit1"` | `"Digit1"` |
| `kVK_ANSI_2 (0x13)` | `"Digit2"` | `"Digit2"` |
| `kVK_ANSI_3 (0x14)` | `"Digit3"` | `"Digit3"` |
| `kVK_ANSI_4 (0x15)` | `"Digit4"` | `"Digit4"` |
| `kVK_ANSI_6 (0x16)` | `"Digit6"` | `"Digit6"` |
| `kVK_ANSI_5 (0x17)` | `"Digit5"` | `"Digit5"` |
| `kVK_ANSI_Equal (0x18)` | `"Equal"` | `"Equal"` |
| `kVK_ANSI_9 (0x19)` | `"Digit9"` | `"Digit9"` |
| `kVK_ANSI_7 (0x1A)` | `"Digit7"` | `"Digit7"` |
| `kVK_ANSI_Minus (0x1B)` | `"Minus"` | `"Minus"` |
| `kVK_ANSI_8 (0x1C)` | `"Digit8"` | `"Digit8"` |
| `kVK_ANSI_0 (0x1D)` | `"Digit0"` | `"Digit0"` |
| `kVK_ANSI_RightBracket (0x1E)` | `"BracketRight"` | `"BracketRight"` |
| `kVK_ANSI_O (0x1F)` | `"KeyO"` | `"KeyO"` |
| `kVK_ANSI_U (0x20)` | `"KeyU"` | `"KeyU"` |
| `kVK_ANSI_LeftBracket (0x21)` | `"BracketLeft"` | `"BracketLeft"` |
| `kVK_ANSI_I (0x22)` | `"KeyI"` | `"KeyI"` |
| `kVK_ANSI_P (0x23)` | `"KeyP"` | `"KeyP"` |
| `kVK_Return (0x24)` | `"Enter"` | `"Enter"` |
| `kVK_ANSI_L (0x25)` | `"KeyL"` | `"KeyL"` |
| `kVK_ANSI_J (0x26)` | `"KeyJ"` | `"KeyJ"` |
| `kVK_ANSI_Quote (0x27)` | `"Quote"` | `"Quote"` |
| `kVK_ANSI_K (0x28)` | `"KeyK"` | `"KeyK"` |
| `kVK_ANSI_Semicolon (0x29)` | `"Semicolon"` | `"Semicolon"` |
| `kVK_ANSI_Backslash (0x2A)` | `"Backslash"` | `"Backslash"` |
| `kVK_ANSI_Comma (0x2B)` | `"Comma"` | `"Comma"` |
| `kVK_ANSI_Slash (0x2C)` | `"Slash"` | `"Slash"` |
| `kVK_ANSI_N (0x2D)` | `"KeyN"` | `"KeyN"` |
| `kVK_ANSI_M (0x2E)` | `"KeyM"` | `"KeyM"` |
| `kVK_ANSI_Period (0x2F)` | `"Period"` | `"Period"` |
| `kVK_Tab (0x30)` | `"Tab"` | `"Tab"` |
| `kVK_Space (0x31)` | `"Space"` | `"Space"` |
| `kVK_ANSI_Grave (0x32)` | `"Backquote"` | `"Backquote"` |
| `kVK_Delete (0x33)` | `"Backspace"` | `"Backspace"` |
| Enter key on keypad of PowerBook (`0x34`) | `"NumpadEnter"`(⚠ Same string for `0x4C`) (⚠ Not the same on Chromium) | `""` (❌ Missing) |
| `kVK_Escape (0x35)` | `"Escape"` | `"Escape"` |
| right-command key (`0x36`) | `"MetaRight"` (was `"OSRight"` prior to Firefox 118) | `"MetaRight"` (was `"OSRight"` prior to Chromium 52) |
| `kVK_Command (0x37)` | `"MetaLeft"` (was `"OSLeft"` prior to Firefox 118) | `"MetaLeft"` (was `"OSLeft"` prior to Chromium 52) |
| `kVK_Shift (0x38)` | `"ShiftLeft"` | `"ShiftLeft"` |
| `kVK_CapsLock (0x39)` | `"CapsLock"` | `"CapsLock"` |
| `kVK_Option (0x3A)` | `"AltLeft"` | `"AltLeft"` |
| `kVK_Control (0x3B)` | `"ControlLeft"` | `"ControlLeft"` |
| `kVK_RightShift (0x3C)` | `"ShiftRight"` | `"ShiftRight"` |
| `kVK_RightOption (0x3D)` | `"AltRight"` | `"AltRight"` |
| `kVK_RightControl (0x3E)` | `"ControlRight"` | `"ControlRight"` |
| `kVK_Function (0x3F)` | `"Fn"` (⚠ No events fired actually) | `""` (❌ Missing) (⚠ No events fired actually) |
| `kVK_F17 (0x40)` | `"F17"` | `"F17"` |
| `kVK_ANSI_KeypadDecimal (0x41)` | `"NumpadDecimal"` | `"NumpadDecimal"` |
| `kVK_ANSI_KeypadMultiply (0x43)` | `"NumpadMultiply"` | `"NumpadMultiply"` |
| `kVK_ANSI_KeypadPlus (0x45)` | `"NumpadAdd"` | `"NumpadAdd"` |
| `kVK_ANSI_KeypadClear (0x47)` | `"NumLock"` | `"NumLock"` |
| `kVK_VolumeUp (0x48)` | `"VolumeUp"` (⚠ Not the same on Chromium) | `"AudioVolumeUp"` (was `"VolumeUp"` prior to Chromium
 1) (⚠ Not the same on Firefox)
  |
| `kVK_VolumeDown (0x49)` | `"VolumeDown"` (⚠ Not the same on Chromium) | `"AudioVolumeDown"` (was `"VolumeDown"` prior to
 Chromium 52) (⚠ Not the same on Firefox)
  |
| `kVK_Mute (0x4A)` | `"VolumeMute"` (⚠ Not the same on Chromium) | `"AudioVolumeMute"` (was `"VolumeMute"` prior to
 Chromium 52) (⚠ Not the same on Firefox)
  |
| `kVK_ANSI_KeypadDivide (0x4B)` | `"NumpadDivide"` | `"NumpadDivide"` |
| `kVK_ANSI_KeypadEnter (0x4C)` | `"NumpadEnter"` | `"NumpadEnter"` |
| `kVK_ANSI_KeypadMinus (0x4E)` | `"NumpadSubtract"` | `"NumpadSubtract"` |
| `kVK_F18 (0x4F)` | `"F18"` | `"F18"` |
| `kVK_F19 (0x50)` | `"F19"` | `"F19"` |
| `kVK_ANSI_KeypadEquals (0x51)` | `"NumpadEqual"` | `"NumpadEqual"` |
| `kVK_ANSI_Keypad0 (0x52)` | `"Numpad0"` | `"Numpad0"` |
| `kVK_ANSI_Keypad1 (0x53)` | `"Numpad1"` | `"Numpad1"` |
| `kVK_ANSI_Keypad2 (0x54)` | `"Numpad2"` | `"Numpad2"` |
| `kVK_ANSI_Keypad3 (0x55)` | `"Numpad3"` | `"Numpad3"` |
| `kVK_ANSI_Keypad4 (0x56)` | `"Numpad4"` | `"Numpad4"` |
| `kVK_ANSI_Keypad5 (0x57)` | `"Numpad5"` | `"Numpad5"` |
| `kVK_ANSI_Keypad6 (0x58)` | `"Numpad6"` | `"Numpad6"` |
| `kVK_ANSI_Keypad7 (0x59)` | `"Numpad7"` | `"Numpad7"` |
| `kVK_F20 (0x5A)` | `"F20"` | `"F20"` |
| `kVK_ANSI_Keypad8 (0x5B)` | `"Numpad8"` | `"Numpad8"` |
| `kVK_ANSI_Keypad9 (0x5C)` | `"Numpad9"` | `"Numpad9"` |
| `kVK_JIS_Yen (0x5D)` | `"IntlYen"` | `"IntlYen"` |
| `kVK_JIS_Underscore (0x5E)` | `"IntlRo"` | `"IntlRo"` |
| `kVK_JIS_KeypadComma (0x5F)` | `"NumpadComma"` | `"NumpadComma"` |
| `kVK_F5 (0x60)` | `"F5"` | `"F5"` |
| `kVK_F6 (0x61)` | `"F6"` | `"F6"` |
| `kVK_F7 (0x62)` | `"F7"` | `"F7"` |
| `kVK_F3 (0x63)` | `"F3"` | `"F3"` |
| `kVK_F8 (0x64)` | `"F8"` | `"F8"` |
| `kVK_F9 (0x65)` | `"F9"` | `"F9"` |
| `kVK_JIS_Eisu (0x66)` | `"Lang2"` | `"Lang2"` (was `""` prior to Chromium 82) (⚠ No events fired actually) |
| `kVK_F11 (0x67)` | `"F11"` | `"F11"` |
| `kVK_JIS_Kana (0x68)` | `"Lang1"` | `"Lang1"` (was `"KanaMode"` prior to Chromium 82) (⚠ No events fired actually) |
| `kVK_F13 (0x69)` | `"F13"` | `"F13"` |
| `kVK_F16 (0x6A)` | `"F16"` | `"F16"` |
| `kVK_F14 (0x6B)` | `"F14"` | `"F14"` |
| `kVK_F10 (0x6D)` | `"F10"` | `"F10"` |
| context menu key (`0x6E`) | `"ContextMenu"` | `"ContextMenu"` |
| `kVK_F12 (0x6F)` | `"F12"` | `"F12"` |
| `kVK_F15 (0x71)` | `"F15"` | `"F15"` |
| `kVK_Help (0x72)` | `"Help"` (⚠ Not the same on Chromium) | `"Insert"` (⚠ Not the same on Firefox) |
| `kVK_Home (0x73)` | `"Home"` | `"Home"` |
| `kVK_PageUp (0x74)` | `"PageUp"` | `"PageUp"` |
| `kVK_ForwardDelete (0x75)` | `"Delete"` | `"Delete"` |
| `kVK_F4 (0x76)` | `"F4"` | `"F4"` |
| `kVK_End (0x77)` | `"End"` | `"End"` |
| `kVK_F2 (0x78)` | `"F2"` | `"F2"` |
| `kVK_PageDown (0x79)` | `"PageDown"` | `"PageDown"` |
| `kVK_F1 (0x7A)` | `"F1"` | `"F1"` |
| `kVK_LeftArrow (0x7B)` | `"ArrowLeft"` | `"ArrowLeft"` |
| `kVK_RightArrow (0x7C)` | `"ArrowRight"` | `"ArrowRight"` |
| `kVK_DownArrow (0x7D)` | `"ArrowDown"` | `"ArrowDown"` |
| `kVK_UpArrow (0x7E)` | `"ArrowUp"` | `"ArrowUp"` |

Code values on Linux (X11)
--------------------------

Note that X has too many keys and some of them are not testable with usual keyboard. So, following table is created from source code which maps from scancode to code value.

In the cells, "(❌ Missing)" means that this code value cannot be detected on this browser.

| scancode (hardware\_keycode) | Firefox | Chromium |
| --- | --- | --- |
| `0x0009` | `"Escape"` | `"Escape"` |
| `0x000A` | `"Digit1"` | `"Digit1"` |
| `0x000B` | `"Digit2"` | `"Digit2"` |
| `0x000C` | `"Digit3"` | `"Digit3"` |
| `0x000D` | `"Digit4"` | `"Digit4"` |
| `0x000E` | `"Digit5"` | `"Digit5"` |
| `0x000F` | `"Digit6"` | `"Digit6"` |
| `0x0010` | `"Digit7"` | `"Digit7"` |
| `0x0011` | `"Digit8"` | `"Digit8"` |
| `0x0012` | `"Digit9"` | `"Digit9"` |
| `0x0013` | `"Digit0"` | `"Digit0"` |
| `0x0014` | `"Minus"` | `"Minus"` |
| `0x0015` | `"Equal"` | `"Equal"` |
| `0x0016` | `"Backspace"` | `"Backspace"` |
| `0x0017` | `"Tab"` | `"Tab"` |
| `0x0018` | `"KeyQ"` | `"KeyQ"` |
| `0x0019` | `"KeyW"` | `"KeyW"` |
| `0x001A` | `"KeyE"` | `"KeyE"` |
| `0x001B` | `"KeyR"` | `"KeyR"` |
| `0x001C` | `"KeyT"` | `"KeyT"` |
| `0x001D` | `"KeyY"` | `"KeyY"` |
| `0x001E` | `"KeyU"` | `"KeyU"` |
| `0x001F` | `"KeyI"` | `"KeyI"` |
| `0x0020` | `"KeyO"` | `"KeyO"` |
| `0x0021` | `"KeyP"` | `"KeyP"` |
| `0x0022` | `"BracketLeft"` | `"BracketLeft"` |
| `0x0023` | `"BracketRight"` | `"BracketRight"` |
| `0x0024` | `"Enter"` | `"Enter"` |
| `0x0025` | `"ControlLeft"` | `"ControlLeft"` |
| `0x0026` | `"KeyA"` | `"KeyA"` |
| `0x0027` | `"KeyS"` | `"KeyS"` |
| `0x0028` | `"KeyD"` | `"KeyD"` |
| `0x0029` | `"KeyF"` | `"KeyF"` |
| `0x002A` | `"KeyG"` | `"KeyG"` |
| `0x002B` | `"KeyH"` | `"KeyH"` |
| `0x002C` | `"KeyJ"` | `"KeyJ"` |
| `0x002D` | `"KeyK"` | `"KeyK"` |
| `0x002E` | `"KeyL"` | `"KeyL"` |
| `0x002F` | `"Semicolon"` | `"Semicolon"` |
| `0x0030` | `"Quote"` | `"Quote"` |
| `0x0031` | `"Backquote"` | `"Backquote"` |
| `0x0032` | `"ShiftLeft"` | `"ShiftLeft"` |
| `0x0033` | `"Backslash"` | `"Backslash"` |
| `0x0034` | `"KeyZ"` | `"KeyZ"` |
| `0x0035` | `"KeyX"` | `"KeyX"` |
| `0x0036` | `"KeyC"` | `"KeyC"` |
| `0x0037` | `"KeyV"` | `"KeyV"` |
| `0x0038` | `"KeyB"` | `"KeyB"` |
| `0x0039` | `"KeyN"` | `"KeyN"` |
| `0x003A` | `"KeyM"` | `"KeyM"` |
| `0x003B` | `"Comma"` | `"Comma"` |
| `0x003C` | `"Period"` | `"Period"` |
| `0x003D` | `"Slash"` | `"Slash"` |
| `0x003E` | `"ShiftRight"` | `"ShiftRight"` |
| `0x003F` | `"NumpadMultiply"` | `"NumpadMultiply"` |
| `0x0040` | `"AltLeft"` | `"AltLeft"` |
| `0x0041` | `"Space"` | `"Space"` |
| `0x0042` | `"CapsLock"` | `"CapsLock"` |
| `0x0043` | `"F1"` | `"F1"` |
| `0x0044` | `"F2"` | `"F2"` |
| `0x0045` | `"F3"` | `"F3"` |
| `0x0046` | `"F4"` | `"F4"` |
| `0x0047` | `"F5"` | `"F5"` |
| `0x0048` | `"F6"` | `"F6"` |
| `0x0049` | `"F7"` | `"F7"` |
| `0x004A` | `"F8"` | `"F8"` |
| `0x004B` | `"F9"` | `"F9"` |
| `0x004C` | `"F10"` | `"F10"` |
| `0x004D` | `"NumLock"` | `"NumLock"` |
| `0x004E` | `"ScrollLock"` | `"ScrollLock"` |
| `0x004F` | `"Numpad7"` | `"Numpad7"` |
| `0x0050` | `"Numpad8"` | `"Numpad8"` |
| `0x0051` | `"Numpad9"` | `"Numpad9"` |
| `0x0052` | `"NumpadSubtract"` | `"NumpadSubtract"` |
| `0x0053` | `"Numpad4"` | `"Numpad4"` |
| `0x0054` | `"Numpad5"` | `"Numpad5"` |
| `0x0055` | `"Numpad6"` | `"Numpad6"` |
| `0x0056` | `"NumpadAdd"` | `"NumpadAdd"` |
| `0x0057` | `"Numpad1"` | `"Numpad1"` |
| `0x0058` | `"Numpad2"` | `"Numpad2"` |
| `0x0059` | `"Numpad3"` | `"Numpad3"` |
| `0x005A` | `"Numpad0"` | `"Numpad0"` |
| `0x005B` | `"NumpadDecimal"` | `"NumpadDecimal"` |
| `0x005C` | `"Unidentified"` | `""` |
| `0x005D` | `"Unidentified"` (❌ Missing) | `"Lang5"` (was `""` prior to Chromium 48) (⚠ Not the same on Firefox) |
| `0x005E` | `"IntlBackslash"` | `"IntlBackslash"` |
| `0x005F` | `"F11"` | `"F11"` |
| `0x0060` | `"F12"` | `"F12"` |
| `0x0061` | `"IntlRo"` | `"IntlRo"` |
| `0x0062` | `"Unidentified"` (❌ Missing) | `"Lang3"` (⚠ Not the same on Firefox) |
| `0x0063` | `"Unidentified"` (❌ Missing) | `"Lang4"` (⚠ Not the same on Firefox) |
| `0x0064` | `"Convert"` | `"Convert"` |
| `0x0065` | `"KanaMode"` | `"KanaMode"` |
| `0x0066` | `"NonConvert"` | `"NonConvert"` |
| `0x0067` | `"Unidentified"` | `""` |
| `0x0068` | `"NumpadEnter"` | `"NumpadEnter"` |
| `0x0069` | `"ControlRight"` | `"ControlRight"` |
| `0x006A` | `"NumpadDivide"` | `"NumpadDivide"` |
| `0x006B` | `"PrintScreen"` | `"PrintScreen"` |
| `0x006C` | `"AltRight"` | `"AltRight"` |
| `0x006D` | `"Unidentified"` | `""` |
| `0x006E` | `"Home"` | `"Home"` |
| `0x006F` | `"ArrowUp"` | `"ArrowUp"` |
| `0x0070` | `"PageUp"` | `"PageUp"` |
| `0x0071` | `"ArrowLeft"` | `"ArrowLeft"` |
| `0x0072` | `"ArrowRight"` | `"ArrowRight"` |
| `0x0073` | `"End"` | `"End"` |
| `0x0074` | `"ArrowDown"` | `"ArrowDown"` |
| `0x0075` | `"PageDown"` | `"PageDown"` |
| `0x0076` | `"Insert"` | `"Insert"` |
| `0x0077` | `"Delete"` | `"Delete"` |
| `0x0078` | `"Unidentified"` | `""` |
| `0x0079` | `"VolumeMute"` (⚠ Not the same on Chromium) | `"AudioVolumeMute"` (was `"VolumeMute"` prior to
 Chromium 52) (⚠ Not the same on Firefox)
  |
| `0x007A` | `"VolumeDown"` (⚠ Not the same on Chromium) | `"AudioVolumeDown"` (was `"VolumeDown"` prior to
 Chromium 52) (⚠ Not the same on Firefox)
  |
| `0x007B` | `"VolumeUp"` (⚠ Not the same on Chromium) | `"AudioVolumeUp"` (was `"VolumeUp"` prior to Chromium
 52) (⚠ Not the same on Firefox)
  |
| `0x007C` | `"Unidentified"` (❌ Missing) | `"Power"` (⚠ Not the same on Firefox) |
| `0x007D` | `"NumpadEqual"` | `"NumpadEqual"` |
| `0x007E` | `"Unidentified"` | `""` |
| `0x007F` | `"Pause"` | `"Pause"` |
| `0x0080` | `"Unidentified"` | `""` |
| `0x0081` | `"NumpadComma"` | `"NumpadComma"` |
| `0x0082` | `"Lang1"` | `"Lang1"` |
| `0x0083` | `"Lang2"` | `"Lang2"` |
| `0x0084` | `"IntlYen"` | `"IntlYen"` |
| `0x0085` | `"MetaLeft"` (was `"OSLeft"` prior to Firefox 118) | `"MetaLeft"` (was `"OSLeft"` prior to Chromium 52) |
| `0x0086` | `"MetaRight"` (was `"OSRight"` prior to Firefox 118) | `"MetaRight"` (was `"OSRight"` prior to Chromium 52) |
| `0x0087` | `"ContextMenu"` | `"ContextMenu"` |
| `0x0088` | `"BrowserStop"` | `"BrowserStop"` (was `"Abort"` prior to Chromium 48) |
| `0x0089` | `"Again"` | `"Again"` |
| `0x008A` | `"Props"` (⚠ Not the same on Chromium) | `""` (❌ Missing) |
| `0x008B` | `"Undo"` | `"Undo"` |
| `0x008C` | `"Select"` | `"Select"` (was `""` prior to Chromium 48) |
| `0x008D` | `"Copy"` | `"Copy"` |
| `0x008E` | `"Open"` | `"Open"` (was `""` prior to Chromium 48) |
| `0x008F` | `"Paste"` | `"Paste"` |
| `0x0090` | `"Find"` | `"Find"` |
| `0x0091` | `"Cut"` | `"Cut"` |
| `0x0092` | `"Help"` | `"Help"` |
| `0x0093` | `"Unidentified"` | `""` |
| `0x0094` | `"LaunchApp2"` | `"LaunchApp2"` |
| `0x0095` | `"Unidentified"` | `""` |
| `0x0096` | `"Unidentified"` (❌ Missing) | `"Sleep"` (⚠ Not the same on Firefox) |
| `0x0097` | `"WakeUp"` | `"WakeUp"` |
| `0x0098` | `"LaunchApp1"` | `"LaunchApp1"` (was `""` prior to Chromium 48) |
| `0x0099` ～ `0x00A2` | `"Unidentified"` | `""` |
| `0x00A3` | `"LaunchMail"` | `"LaunchMail"` (was `""` prior to Chromium 51) |
| `0x00A4` | `"BrowserFavorites"` | `"BrowserFavorites"` |
| `0x00A5` | `"Unidentified"` | `""` |
| `0x00A6` | `"BrowserBack"` | `"BrowserBack"` |
| `0x00A7` | `"BrowserForward"` | `"BrowserForward"` |
| `0x00A8` | `"Unidentified"` | `""` |
| `0x00A9` | `"Eject"` | `"Eject"` (was `""` prior to Chromium 48) |
| `0x00AA` | `"Unidentified"` | `""` |
| `0x00AB` | `"MediaTrackNext"` | `"MediaTrackNext"` (was `""` prior to Chromium 48) |
| `0x00AC` | `"MediaPlayPause"` | `"MediaPlayPause"` (was `""` prior to Chromium 48) |
| `0x00AD` | `"MediaTrackPrevious"` | `"MediaTrackPrevious"` (was `""` prior to Chromium 48) |
| `0x00AE` | `"MediaStop"` | `"MediaStop"` (was `""` prior to Chromium 48) |
| `0x00AF` ～ `0x00B2` | `"Unidentified"` | `""` |
| `0x00B3` | `"MediaSelect"` | `"MediaSelect"` (was `""` prior to Chromium 48) |
| `0x00B4` | `"BrowserHome"` | `"BrowserHome"` (was `""` prior to Chromium 48) |
| `0x00B5` | `"BrowserRefresh"` | `"BrowserRefresh"` |
| `0x00B6` ～ `0x00BA` | `"Unidentified"` | `""` |
| `0x00BB` | `"Unidentified"` (❌ Missing) | `"NumpadParenLeft"` (⚠ Not the same on Firefox) |
| `0x00BC` | `"Unidentified"` (❌ Missing) | `"NumpadParenRight"` (⚠ Not the same on Firefox) |
| `0x00BD`, `0x00BE` | `"Unidentified"` | `""` |
| `0x00BF` | `"F13"` | `"F13"` |
| `0x00C0` | `"F14"` | `"F14"` |
| `0x00C1` | `"F15"` | `"F15"` |
| `0x00C2` | `"F16"` | `"F16"` |
| `0x00C3` | `"F17"` | `"F17"` |
| `0x00C4` | `"F18"` | `"F18"` |
| `0x00C5` | `"F19"` | `"F19"` |
| `0x00C6` | `"F20"` | `"F20"` |
| `0x00C7` | `"F21"` | `"F21"` |
| `0x00C8` | `"F22"` | `"F22"` |
| `0x00C9` | `"F23"` | `"F23"` |
| `0x00CA` | `"F24"` | `"F24"` |
| `0x00CB ～ 0x00E0` | `"Unidentified"` | `""` |
| `0x00E1` | `"BrowserSearch"` (⚠ Not the same on Chromium) | `"BrowserSearch"` (was `"BrightnessUp"` prior to Chromium 48) |

Code values on Firefox for Android
----------------------------------

| scancode | Firefox |
| --- | --- |
| `0x0001` | `"Escape"` |
| `0x0002` | `"Digit1"` |
| `0x0003` | `"Digit2"` |
| `0x0004` | `"Digit3"` |
| `0x0005` | `"Digit4"` |
| `0x0006` | `"Digit5"` |
| `0x0007` | `"Digit6"` |
| `0x0008` | `"Digit7"` |
| `0x0009` | `"Digit8"` |
| `0x000A` | `"Digit9"` |
| `0x000B` | `"Digit0"` |
| `0x000C` | `"Minus"` |
| `0x000D` | `"Equal"` |
| `0x000E` | `"Backspace"` |
| `0x000F` | `"Tab"` |
| `0x0010` | `"KeyQ"` |
| `0x0011` | `"KeyW"` |
| `0x0012` | `"KeyE"` |
| `0x0013` | `"KeyR"` |
| `0x0014` | `"KeyT"` |
| `0x0015` | `"KeyY"` |
| `0x0016` | `"KeyU"` |
| `0x0017` | `"KeyI"` |
| `0x0018` | `"KeyO"` |
| `0x0019` | `"KeyP"` |
| `0x001A` | `"BracketLeft"` |
| `0x001B` | `"BracketRight"` |
| `0x001C` | `"Enter"` |
| `0x001D` | `"ControlLeft"` |
| `0x001E` | `"KeyA"` |
| `0x001F` | `"KeyS"` |
| `0x0020` | `"KeyD"` |
| `0x0021` | `"KeyF"` |
| `0x0022` | `"KeyG"` |
| `0x0023` | `"KeyH"` |
| `0x0024` | `"KeyJ"` |
| `0x0025` | `"KeyK"` |
| `0x0026` | `"KeyL"` |
| `0x0027` | `"Semicolon"` |
| `0x0028` | `"Quote"` |
| `0x0029` | `"Backquote"` |
| `0x002A` | `"ShiftLeft"` |
| `0x002B` | `"Backslash"` |
| `0x002C` | `"KeyZ"` |
| `0x002D` | `"KeyX"` |
| `0x002E` | `"KeyC"` |
| `0x002F` | `"KeyV"` |
| `0x0030` | `"KeyB"` |
| `0x0031` | `"KeyN"` |
| `0x0032` | `"KeyM"` |
| `0x0033` | `"Comma"` |
| `0x0034` | `"Period"` |
| `0x0035` | `"Slash"` |
| `0x0036` | `"ShiftRight"` |
| `0x0037` | `"NumpadMultiply"` |
| `0x0038` | `"AltLeft"` |
| `0x0039` | `"Space"` |
| `0x003A` | `"CapsLock"` |
| `0x003B` | `"F1"` |
| `0x003C` | `"F2"` |
| `0x003D` | `"F3"` |
| `0x003E` | `"F4"` |
| `0x003F` | `"F5"` |
| `0x0040` | `"F6"` |
| `0x0041` | `"F7"` |
| `0x0042` | `"F8"` |
| `0x0043` | `"F9"` |
| `0x0044` | `"F10"` |
| `0x0045` | `"NumLock"` |
| `0x0046` | `"ScrollLock"` |
| `0x0047` | `"Numpad7"` |
| `0x0048` | `"Numpad8"` |
| `0x0049` | `"Numpad9"` |
| `0x004A` | `"NumpadSubtract"` |
| `0x004B` | `"Numpad4"` |
| `0x004C` | `"Numpad5"` |
| `0x004D` | `"Numpad6"` |
| `0x004E` | `"NumpadAdd"` |
| `0x004F` | `"Numpad1"` |
| `0x0050` | `"Numpad2"` |
| `0x0051` | `"Numpad3"` |
| `0x0052` | `"Numpad0"` |
| `0x0053` | `"NumpadDecimal"` |
| `0x0054`, `0x0055` | `"Unidentified"` |
| `0x0056` | `"IntlBackslash"` |
| `0x0057` | `"F11"` |
| `0x0058` | `"F12"` |
| `0x0059` | `"IntlRo"` |
| `0x005A`, `0x005B` | `"Unidentified"` |
| `0x005C` | `"Convert"` |
| `0x005D` | `"KanaMode"` |
| `0x005E` | `"NonConvert"` |
| `0x005F` | `"Unidentified"` |
| `0x0060` | `"NumpadEnter"` |
| `0x0061` | `"ControlRight"` |
| `0x0062` | `"NumpadDivide"` |
| `0x0063` | `"PrintScreen"` |
| `0x0064` | `"AltRight"` |
| `0x0065` | `"Unidentified"` |
| `0x0066` | `"Home"` |
| `0x0067` | `"ArrowUp"` |
| `0x0068` | `"PageUp"` |
| `0x0069` | `"ArrowLeft"` |
| `0x006A` | `"ArrowRight"` |
| `0x006B` | `"End"` |
| `0x006C` | `"ArrowDown"` |
| `0x006D` | `"PageDown"` |
| `0x006E` | `"Insert"` |
| `0x006F` | `"Delete"` |
| `0x0070` | `"Unidentified"` |
| `0x0071` | `"VolumeMute"` |
| `0x0072` | `"VolumeDown"` |
| `0x0073` | `"VolumeUp"` |
| `0x0074` | `"Power"` |
| `0x0075` | `"NumpadEqual"` |
| `0x0076` | `"Unidentified"` |
| `0x0077` | `"Pause"` |
| `0x0078` | `"Unidentified"` |
| `0x0079` | `"NumpadComma"` |
| `0x007A` | `"Lang1"` |
| `0x007B` | `"Lang2"` |
| `0x007C` | `"IntlYen"` |
| `0x007D` | `"MetaLeft"` (was `"OSLeft"` prior to Firefox 118) |
| `0x007E` | `"MetaRight"` (was `"OSRight"` prior to Firefox 118) |
| `0x007F` | `"ContextMenu"` |
| `0x0080` | `"BrowserStop"` |
| `0x0081` | "Again" |
| `0x0082` | `"Props"` |
| `0x0083` | `"Undo"` |
| `0x0084` | `"Select"` |
| `0x0085` | `"Copy"` |
| `0x0086` | `"Open"` |
| `0x0087` | `"Paste"` |
| `0x0088` | `"Find"` |
| `0x0089` | `"Cut"` |
| `0x008A` | `"Help"` |
| `0x008B` ～ `0x008D` | `"Unidentified"` |
| `0x008E` | `"Sleep"` |
| `0x008F` | `"WakeUp"` |
| `0x0090` | `"LaunchApp1"` |
| `0x0091` ～ `0x009B` | `"Unidentified"` |
| `0x009C` | `"BrowserFavorites"` |
| `0x009D` | `"Unidentified"` |
| `0x009E` | `"BrowserBack"` |
| `0x009F` | `"BrowserForward"` |
| `0x00A0` | `"Unidentified"` |
| `0x00A1` | `"Eject"` |
| `0x00A2` | `"Unidentified"` |
| `0x00A3` | `"MediaTrackNext"` |
| `0x00A4` | `"MediaPlayPause"` |
| `0x00A5` | `"MediaTrackPrevious"` |
| `0x00A6` | `"MediaStop"` |
| `0x00A7` ～ `0x00AC` | `"Unidentified"` |
| `0x00AD` | `"BrowserRefresh"` |
| `0x00AE` ～ `0x00B6` | "Unidentified" |
| `0x00B7` | `"F13"` |
| `0x00B8` | `"F14"` |
| `0x00B9` | `"F15"` |
| `0x00BA` | `"F16"` |
| `0x00BB` | `"F17"` |
| `0x00BC` | `"F18"` |
| `0x00BD` | `"F19"` |
| `0x00BE` | `"F20"` |
| `0x00BF` | `"F21"` |
| `0x00C0` | `"F22"` |
| `0x00C1` | `"F23"` |
| `0x00C2` | `"F24"` |
| `0x00C3` ～ `0x00D8` | `"Unidentified"` |
| `0x00D9` | `"BrowserSearch"` |
| `0x00DA` ～ `0x01CF` | `"Unidentified"` |
| `0x01D0` | `"Fn"` |


TrustedScriptURL: toJSON() method - Web APIs

TrustedScriptURL: toJSON() method
=================================

The **`toJSON()`** method of the `TrustedScriptURL` interface returns a JSON representation of the stored data.

Syntax
------

```js
toJSON()
```

### Parameters

None.

### Return value

A string containing a JSON representation of the stored data.

Examples
--------

The constant `sanitized` is an object created via a Trusted Types policy. The `toString()` method returns a string to safely use to load a third party script.

```js
const sanitized = scriptPolicy.createScriptURL(
  "https://example.com/my-script.js",
);
console.log(sanitized.toJSON());
```

Specifications
--------------

| Specification |
| --- |
| Trusted Types # dom-trustedscripturl-tojson |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TrustedScriptURL: toString() method - Web APIs

TrustedScriptURL: toString() method
===================================

The **`toString()`** method of the `TrustedScriptURL` interface returns a string which may safely inserted into an injection sink.

Syntax
------

```js
toString()
```

### Parameters

None.

### Return value

A string containing the sanitized URL

Examples
--------

The constant `sanitized` is an object created via a Trusted Types policy. The `toString()` method returns a string to safely use to load a third party script.

```js
const sanitized = scriptPolicy.createScriptURL(
  "https://example.com/my-script.js",
);
console.log(sanitized.toString());
```

Specifications
--------------

| Specification |
| --- |
| Trusted Types # trustedscripturl-stringification-behavior |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


IDBRequest: error property - Web APIs

IDBRequest: error property
==========================

 The **`error`** read-only property of the
 `IDBRequest` interface returns the error in the event of an unsuccessful
 request.

**Note:** This feature is available in Web Workers

Value
-----

 A `DOMException` or `null` if there is no error. The following error names are returned
 in the exception object:

`AbortError`

If you abort the transaction, then all requests still in progress receive this error.

`ConstraintError`

 If you insert data that doesn't conform to a constraint.
 It's an exception type for creating stores and indexes.
 You get this error, for example, if you try to add a new key that already exists in the record.

`QuotaExceededError`

If you run out of disk quota and the user declined to grant you more space.

`UnknownError`

 If the operation failed for reasons unrelated to the database itself.
 A failure due to disk IO errors is such an example.

`VersionError`

If you try to open a database with a version lower than the one it already has.

 In addition to the error codes sent to the `IDBRequest` object,
 asynchronous operations can also raise exceptions. The list describes problems that
 could occur when the request is being executed, but you might also encounter other
 problems when the request is being made. For example, if the result is accessed
 while the request is not completed, the `InvalidStateError` exception is thrown.

Examples
--------

 The following example requests a given record title, `onsuccess` gets the
 associated record from the `IDBObjectStore` (made available as
 `objectStoreTitleRequest.result`), updates one property of the record, and then puts the
 updated record back into the object store. Also included at the bottom is an
 `onerror` function that reports what the error was if the request fails.
 For a full working example, see our To-do Notifications app (View the example live).

```js
const title = "Walk dog";

// Open up a transaction as usual
const objectStore = db
  .transaction(["toDoList"], "readwrite")
  .objectStore("toDoList");

// Get the to-do list with the specified title
const objectStoreTitleRequest = objectStore.get(title);

objectStoreTitleRequest.onsuccess = () => {
  // Grab the data object returned as the result
  const data = objectStoreTitleRequest.result;

  // Update the notified value in the object to "yes"
  data.notified = "yes";

  // Create another request that inserts the item
  // back into the database
  const updateTitleRequest = objectStore.put(data);

  // When this new request succeeds, run the displayData()
  // function again to update the display
  updateTitleRequest.onsuccess = () => {
    displayData();
  };
};

objectStoreTitleRequest.onerror = () => {
  // If an error occurs with the request, log what it is
  console.log(
    `There has been an error with retrieving your data: ${objectStoreTitleRequest.error}`,
  );
};
```

Specifications
--------------

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbrequest-error① |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using IndexedDB
* Starting transactions: `IDBDatabase`
* Using transactions: `IDBTransaction`
* Setting a range of keys: `IDBKeyRange`
* Retrieving and making changes to your data: `IDBObjectStore`
* Using cursors: `IDBCursor`
* Reference example: To-do Notifications (View the example live).


IDBRequest: error event - Web APIs

IDBRequest: error event
=======================

The `error` handler is executed when an error caused a request to fail.

This event is not cancelable and does not bubble.

Syntax
------

Use the event name in methods like `addEventListener()`, or set an event handler property.

```js
addEventListener("error", (event) => {});

onerror = (event) => {};
```

Event type
----------

A generic `Event`.

Examples
--------

This example opens a database and tries to add a record, listening for the `error` event for the `add()` operation (this will occur if, for example, a record with the given `taskTitle` already exists):

```js
// Open the database
const DBOpenRequest = window.indexedDB.open("toDoList", 4);

DBOpenRequest.addEventListener("upgradeneeded", (event) => {
  const db = event.target.result;

  db.onerror = () => {
    console.log("Error creating database");
  };

  // Create an objectStore for this database
  const objectStore = db.createObjectStore("toDoList", {
    keyPath: "taskTitle",
  });

  // define what data items the objectStore will contain
  objectStore.createIndex("hours", "hours", { unique: false });
  objectStore.createIndex("minutes", "minutes", { unique: false });
  objectStore.createIndex("day", "day", { unique: false });
  objectStore.createIndex("month", "month", { unique: false });
  objectStore.createIndex("year", "year", { unique: false });
});

DBOpenRequest.addEventListener("success", (event) => {
  const db = DBOpenRequest.result;

  // open a read/write db transaction, ready for adding the data
  const transaction = db.transaction(["toDoList"], "readwrite");
  const objectStore = transaction.objectStore("toDoList");
  const newItem = {
    taskTitle: "my task",
    hours: 10,
    minutes: 10,
    day: 10,
    month: "January",
    year: 2020,
  };

  const objectStoreRequest = objectStore.add(newItem);
  objectStoreRequest.addEventListener("error", () => {
    console.log(`Error adding new item: ${newItem.taskTitle}`);
  });
});
```

The same example, using the `onerror` property instead of `addEventListener()`:

```js
// Open the database
const DBOpenRequest = window.indexedDB.open("toDoList", 4);

DBOpenRequest.onupgradeneeded = (event) => {
  const db = event.target.result;

  db.onerror = () => {
    console.log("Error creating database");
  };

  // Create an objectStore for this database
  const objectStore = db.createObjectStore("toDoList", {
    keyPath: "taskTitle",
  });

  // define what data items the objectStore will contain
  objectStore.createIndex("hours", "hours", { unique: false });
  objectStore.createIndex("minutes", "minutes", { unique: false });
  objectStore.createIndex("day", "day", { unique: false });
  objectStore.createIndex("month", "month", { unique: false });
  objectStore.createIndex("year", "year", { unique: false });
};

DBOpenRequest.onsuccess = (event) => {
  const db = DBOpenRequest.result;

  // open a read/write db transaction, ready for adding the data
  const transaction = db.transaction(["toDoList"], "readwrite");
  const objectStore = transaction.objectStore("toDoList");
  const newItem = {
    taskTitle: "my task",
    hours: 10,
    minutes: 10,
    day: 10,
    month: "January",
    year: 2020,
  };

  const objectStoreRequest = objectStore.add(newItem);
  objectStoreRequest.onerror = () => {
    console.log(`Error adding new item: ${newItem.taskTitle}`);
  };
};
```

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using IndexedDB


IDBRequest: result property - Web APIs

IDBRequest: result property
===========================

 The **`result`** read-only property of the
 `IDBRequest` interface returns the result of the request. If the request
 is not completed, the result is not available and an `InvalidStateError` exception is
 thrown.

**Note:** This feature is available in Web Workers

Value
-----

any

Examples
--------

 The following example requests a given record title, `onsuccess` gets the
 associated record from the `IDBObjectStore` (made available
 as `objectStoreTitleRequest.result`), updates
 one property of the record, and then puts the updated record back into the object
 store. For a full working example, see our To-do Notifications app (View the example live).

```js
const title = "Walk dog";

// Open up a transaction as usual
const objectStore = db
  .transaction(["toDoList"], "readwrite")
  .objectStore("toDoList");

// Get the to-do list object that has this title as it's title
const objectStoreTitleRequest = objectStore.get(title);

objectStoreTitleRequest.onsuccess = () => {
  // Grab the data object returned as the result
  const data = objectStoreTitleRequest.result;

  // Update the notified value in the object to "yes"
  data.notified = "yes";

  // Create another request that inserts the item
  // back into the database
  const updateTitleRequest = objectStore.put(data);

  // When this new request succeeds, run the displayData()
  // function again to update the display
  updateTitleRequest.onsuccess = () => {
    displayData();
  };
};
```

Specifications
--------------

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbrequest-result① |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using IndexedDB
* Starting transactions: `IDBDatabase`
* Using transactions: `IDBTransaction`
* Setting a range of keys: `IDBKeyRange`
* Retrieving and making changes to your data: `IDBObjectStore`
* Using cursors: `IDBCursor`
* Reference example: To-do Notifications (View the example live).


IDBRequest: readyState property - Web APIs

IDBRequest: readyState property
===============================

 The **`readyState`** read-only property of the
 `IDBRequest` interface returns the state of the request.

 Every request starts in the `pending` state. The state changes to
 `done` when the request completes successfully or when an error
 occurs.

**Note:** This feature is available in Web Workers

Value
-----

One of the following strings:

`pending`

Returned if the request is still ongoing.

`done`

Returned if the request has already completed.

Examples
--------

 The following example requests a given record title, `onsuccess` gets the
 associated record from the `IDBObjectStore` (made available
 as `objectStoreTitleRequest.result`), updates
 one property of the record, and then puts the updated record back into the object
 store in another request. The `readyState` of the 2nd request is logged to
 the developer console. For a full working example, see our
 To-do Notifications app
 (View the example live).

```js
const title = "Walk dog";

// Open up a transaction as usual
const objectStore = db
  .transaction(["toDoList"], "readwrite")
  .objectStore("toDoList");

// Get the to-do list object that has this title as it's title
const objectStoreTitleRequest = objectStore.get(title);

objectStoreTitleRequest.onsuccess = () => {
  // Grab the data object returned as the result
  const data = objectStoreTitleRequest.result;

  // Update the notified value in the object to "yes"
  data.notified = "yes";

  // Create another request that inserts the item
  // back into the database
  const updateTitleRequest = objectStore.put(data);

  // Log the readyState of this request
  console.log(
    `The readyState of this request is ${updateTitleRequest.readyState}`,
  );

  // When this new request succeeds, run the displayData()
  // function again to update the display
  updateTitleRequest.onsuccess = () => {
    displayData();
  };
};
```

Specifications
--------------

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbrequest-readystate① |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using IndexedDB
* Starting transactions: `IDBDatabase`
* Using transactions: `IDBTransaction`
* Setting a range of keys: `IDBKeyRange`
* Retrieving and making changes to your data: `IDBObjectStore`
* Using cursors: `IDBCursor`
* Reference example: To-do Notifications (View the example live).


IDBRequest: source property - Web APIs

IDBRequest: source property
===========================

 The **`source`** read-only property of the
 `IDBRequest` interface returns the source of the request, such as an
 Index or an object store. If no source exists (such as when calling
 `IDBFactory.open`), it returns null.

**Note:** This feature is available in Web Workers

Value
-----

 An object representing the source of the request, such as an `IDBIndex`,
 `IDBObjectStore` or `IDBCursor`.

Examples
--------

 The following example requests a given record title, `onsuccess` gets the
 associated record from the `IDBObjectStore` (made available
 as `objectStoreTitleRequest.result`), updates
 one property of the record, and then puts the updated record back into the object
 store in another request. The source of the 2nd request is logged to the developer
 console. For a full working example, see our To-do Notifications app (View the example live).

```js
const title = "Walk dog";

// Open up a transaction as usual
const objectStore = db
  .transaction(["toDoList"], "readwrite")
  .objectStore("toDoList");

// Get the to-do list object that has this title as its title
const objectStoreTitleRequest = objectStore.get(title);

objectStoreTitleRequest.onsuccess = () => {
  // Grab the data object returned as the result
  const data = objectStoreTitleRequest.result;

  // Update the notified value in the object to "yes"
  data.notified = "yes";

  // Create another request that inserts the item
  // back into the database
  const updateTitleRequest = objectStore.put(data);

  // Log the source of this request
  console.log(`The source of this request is ${updateTitleRequest.source}`);
  // When this new request succeeds, run the displayData()
  // function again to update the display
  updateTitleRequest.onsuccess = () => {
    displayData();
  };
};
```

Specifications
--------------

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbrequest-source① |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using IndexedDB
* Starting transactions: `IDBDatabase`
* Using transactions: `IDBTransaction`
* Setting a range of keys: `IDBKeyRange`
* Retrieving and making changes to your data: `IDBObjectStore`
* Using cursors: `IDBCursor`
* Reference example: To-do Notifications (View the example live).


IDBRequest: transaction property - Web APIs

IDBRequest: transaction property
================================

 The **`transaction`** read-only property of the IDBRequest
 interface returns the transaction for the request, that is, the transaction the
 request is being made inside.

 This property can be `null` for requests not made within transactions,
 such as for requests returned from `IDBFactory.open` — in this case
 you're just connecting to a database, so there is no transaction to return. If a
 version upgrade is needed when opening a database then during the
 `upgradeneeded` event handler the
 **`transaction`** property will be an
 `IDBTransaction` with `mode` equal
 to `"versionchange"`, and can be used to access existing object stores and
 indexes, or abort the upgrade. Following the upgrade, the
 **`transaction`** property will again be `null`.

**Note:** This feature is available in Web Workers

Value
-----

An `IDBTransaction`.

Examples
--------

 The following example requests a given record title, `onsuccess` gets the
 associated record from the `IDBObjectStore` (made available
 as `objectStoreTitleRequest.result`), updates
 one property of the record, and then puts the updated record back into the object
 store in another request. The source of the requests is logged to the developer
 console — both originate from the same transaction. For a full working example, see
 our To-do Notifications app
 (View the example live).

```js
const title = "Walk dog";

// Open up a transaction as usual
const objectStore = db
  .transaction(["toDoList"], "readwrite")
  .objectStore("toDoList");

// Get the to-do list object that has this title as it's title
const objectStoreTitleRequest = objectStore.get(title);

objectStoreTitleRequest.onsuccess = () => {
  // Grab the data object returned as the result
  const data = objectStoreTitleRequest.result;

  // Update the notified value in the object to "yes"
  data.notified = "yes";

  // Create another request that inserts the item back
  // into the database
  const updateTitleRequest = objectStore.put(data);

  // Log the transaction that originated this request
  console.log(
    `The transaction that originated this request is ${updateTitleRequest.transaction}`,
  );

  // When this new request succeeds, run the displayData()
  // function again to update the display
  updateTitleRequest.onsuccess = () => {
    displayData();
  };
};
```

 This example shows how a the **`transaction`** property can be
 used during a version upgrade to access existing object stores:

```js
const openRequest = indexedDB.open("db", 2);
console.log(openRequest.transaction); // Will log "null".

openRequest.onupgradeneeded = (event) => {
  console.log(openRequest.transaction.mode); // Will log "versionchange".
  const db = openRequest.result;
  if (event.oldVersion < 1) {
    // New database, create "books" object store.
    db.createObjectStore("books");
  }
  if (event.oldVersion < 2) {
    // Upgrading from v1 database: add index on "title" to "books" store.
    const bookStore = openRequest.transaction.objectStore("books");
    bookStore.createIndex("by\_title", "title");
  }
};

openRequest.onsuccess = () => {
  console.log(openRequest.transaction); // Will log "null".
};
```

Specifications
--------------

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbrequest-transaction① |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using IndexedDB
* Starting transactions: `IDBDatabase`
* Using transactions: `IDBTransaction`
* Setting a range of keys: `IDBKeyRange`
* Retrieving and making changes to your data: `IDBObjectStore`
* Using cursors: `IDBCursor`
* Reference example: To-do Notifications (View the example live).


IDBRequest: success event - Web APIs

IDBRequest: success event
=========================

The `success` event is fired when an `IDBRequest` succeeds.

This event is not cancelable and does not bubble.

Syntax
------

Use the event name in methods like `addEventListener()`, or set an event handler property.

```js
addEventListener("success", (event) => {});

onsuccess = (event) => {};
```

Event type
----------

A generic `Event`.

Examples
--------

This example tries to open a database and listens for the `success` event using `addEventListener()`:

```js
// Open the database
const openRequest = window.indexedDB.open("toDoList", 4);

openRequest.onupgradeneeded = (event) => {
  const db = event.target.result;

  db.onerror = () => {
    console.log("Error creating database");
  };

  // Create an objectStore for this database
  const objectStore = db.createObjectStore("toDoList", {
    keyPath: "taskTitle",
  });

  // define what data items the objectStore will contain
  objectStore.createIndex("hours", "hours", { unique: false });
  objectStore.createIndex("minutes", "minutes", { unique: false });
  objectStore.createIndex("day", "day", { unique: false });
  objectStore.createIndex("month", "month", { unique: false });
  objectStore.createIndex("year", "year", { unique: false });
};

openRequest.addEventListener("success", (event) => {
  console.log("Database opened successfully!");
});
```

The same example, but using the `onsuccess` event handler property:

```js
// Open the database
const openRequest = window.indexedDB.open("toDoList", 4);

openRequest.onupgradeneeded = (event) => {
  const db = event.target.result;

  db.onerror = () => {
    console.log("Error creating database");
  };

  // Create an objectStore for this database
  const objectStore = db.createObjectStore("toDoList", {
    keyPath: "taskTitle",
  });

  // define what data items the objectStore will contain
  objectStore.createIndex("hours", "hours", { unique: false });
  objectStore.createIndex("minutes", "minutes", { unique: false });
  objectStore.createIndex("day", "day", { unique: false });
  objectStore.createIndex("month", "month", { unique: false });
  objectStore.createIndex("year", "year", { unique: false });
};

openRequest.onsuccess = (event) => {
  console.log("Database opened successfully!");
};
```

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using IndexedDB


HIDDevice: receiveFeatureReport() method - Web APIs

HIDDevice: receiveFeatureReport() method
========================================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`receiveFeatureReport()`** method of the `HIDDevice` interface receives a feature report from the HID device. Feature reports are a way for HID devices and applications to exchange non-standardized HID data.

The `reportId` for each of the report formats that this device supports can be retrieved from `HIDDevice.collections`.

Syntax
------

```js
receiveFeatureReport(reportId)
```

### Parameters

`reportId`

An 8-bit report ID. If the HID device does not use report IDs, send `0`.

### Return value

A `Promise` which resolves with a `DataView` object containing the feature report.

### Exceptions

`NotAllowedError` `DOMException`

Thrown if receiving the report fails for any reason.

Examples
--------

In the following example a report is received from a device using a `reportId` of `1`.

```js
const dataView = await device.receiveFeatureReport(1);
```

Specifications
--------------

| Specification |
| --- |
| WebHID API # dom-hiddevice-receivefeaturereport |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HIDDevice: close() method - Web APIs

HIDDevice: close() method
=========================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`close()`** method of the `HIDDevice` interface closes the connection to the HID device.

Syntax
------

```js
close()
```

### Parameters

None.

### Return value

A `Promise` that resolves with `undefined` once the connection is closed.

Examples
--------

In the following example we close the HID device, once all data has been sent and received.

```js
await device.close();
```

Specifications
--------------

| Specification |
| --- |
| WebHID API # dom-hiddevice-close |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HIDDevice: productId property - Web APIs

HIDDevice: productId property
=============================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`productId`** read-only property of the `HIDDevice` interface returns the product ID of the connected HID device.

Value
-----

An integer. If the device has no product ID, or the product ID cannot be accessed this will return `0`.

Examples
--------

The following example retrieves devices with `HID.getDevices()` and logs the value of `productId` to the console.

```js
document.addEventListener("DOMContentLoaded", async () => {
  let devices = await navigator.hid.getDevices();
  devices.forEach((device) => {
    console.log(`HID: ${device.productId}`);
  });
});
```

Specifications
--------------

| Specification |
| --- |
| WebHID API # dom-hiddevice-productid |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HIDDevice: inputreport event - Web APIs

HIDDevice: inputreport event
============================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`inputreport`** event of the `HIDDevice` interface fires when a new report is received from the HID device.

Syntax
------

Use the event name in methods like `addEventListener()`, or set an event handler property.

```js
addEventListener("inputreport", (event) => {});

oninputreport = (event) => {};
```

Event type
----------

An `HIDInputReportEvent`. Inherits from `Event`.

Event

HIDInputReportEventEvent properties
----------------

*This interface also inherits properties from `Event`.*

`HIDInputReportEvent.data` Read only

A `DataView` containing the data from the input report, excluding the `reportId` if the HID interface uses report IDs.

`HIDInputReportEvent.device` Read only

The `HIDDevice` instance that represents the HID interface that sent the input report.

`HIDInputReportEvent.reportId` Read only

The one-byte identification prefix for this report, or 0 if the HID interface does not use report IDs.

Example
-------

The following example demonstrates listening for an `inputreport` event that will allow the application to detect which button is pressed on a Joy-Con Right device. You can see more examples, and live demos in the article Connecting to uncommon HID devices.

```js
device.addEventListener("inputreport", (event) => {
  const { data, device, reportId } = event;

  // Handle only the Joy-Con Right device and a specific report ID.
  if (device.productId !== 0x2007 && reportId !== 0x3f) return;

  const value = data.getUint8(0);
  if (value === 0) return;

  const someButtons = { 1: "A", 2: "X", 4: "B", 8: "Y" };
  console.log(`User pressed button ${someButtons[value]}.`);
});
```

Specifications
--------------

| Specification |
| --- |
| WebHID API # dom-hiddevice-oninputreport |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HIDDevice: collections property - Web APIs

HIDDevice: collections property
===============================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`collections`** read-only property of the `HIDDevice` interface returns an array of report formats

Value
-----

An array of report formats. Each entry contains the following:

`usagePage`

An integer representing the usage page component of the HID usage associated with this collection. The usage for a top level collection is used to identify the device type.

Standard HID usage values can be found in the HID Usage Tables document

`usage`

An integer representing the usage ID component of the HID usage associated with this collection.

`type`

An 8-bit value representing the collection type, which describes a different relationship between the grouped items. One of:

`0x00`

Physical (group of axes)

`0x01`

Application (mouse, keyboard)

`0x02`

Logical (interrelated data)

`0x03`

Report

`0x04`

Named array

`0x05`

Usage switch

`0x06`

Usage modified

`0x07 to 0x7F`

Reserved for future use

`0x80 to 0xFF`

Vendor-defined

More information on these types can be found in the Device Class Definition document.

`children`

An array of sub-collections which takes the same format as a top-level collection.

`inputReports`

An array of `inputReport` items which represent individual input reports described in this collection.

`outputReports`

An array of `outputReport` items which represent individual output reports described in this collection.

`featureReports`

An array of `featureReport` items which represent individual feature reports described in this collection.

Examples
--------

The following example demonstrates how to access the various elements once the `collections` property has been returned. You can see more examples, and live demos in the article Connecting to uncommon HID devices.

```js
for (const collection of device.collections) {
  // A HID collection includes usage, usage page, reports, and subcollections.
  console.log(`Usage: ${collection.usage}`);
  console.log(`Usage page: ${collection.usagePage}`);

  for (const inputReport of collection.inputReports) {
    console.log(`Input report: ${inputReport.reportId}`);
    // Loop through inputReport.items
  }

  for (const outputReport of collection.outputReports) {
    console.log(`Output report: ${outputReport.reportId}`);
    // Loop through outputReport.items
  }

  for (const featureReport of collection.featureReports) {
    console.log(`Feature report: ${featureReport.reportId}`);
    // Loop through featureReport.items
  }

  // Loop through subcollections with collection.children
}
```

Specifications
--------------

| Specification |
| --- |
| WebHID API # dom-hiddevice-collections |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HIDDevice: sendFeatureReport() method - Web APIs

HIDDevice: sendFeatureReport() method
=====================================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`sendFeatureReport()`** method of the `HIDDevice` interface sends a feature report to the HID device. Feature reports are a way for HID devices and applications to exchange non-standardized HID data.

The `reportId` for each of the report formats that this device supports can be retrieved from `HIDDevice.collections`.

Syntax
------

```js
sendFeatureReport(reportId, data)
```

### Parameters

`reportId`

An 8-bit report ID. If the HID device does not use report IDs, send `0`.

`data`

Bytes as an `ArrayBuffer`, a `TypedArray`, or a `DataView`.

### Return value

A `Promise` that resolves with `undefined` once the report has been sent.

### Exceptions

`NotAllowedError` `DOMException`

Thrown if sending the report fails for any reason.

Examples
--------

In the following example `sendFeatureReport()` makes a device blink. You can see more examples and live demos in the article Connecting to uncommon HID devices.

```js
const reportId = 1;
for (let i = 0; i < 10; i++) {
  // Turn off
  await device.sendFeatureReport(reportId, Uint32Array.from([0, 0]));
  await waitFor(100);
  // Turn on
  await device.sendFeatureReport(reportId, Uint32Array.from([512, 0]));
  await waitFor(100);
}
```

Specifications
--------------

| Specification |
| --- |
| WebHID API # dom-hiddevice-sendfeaturereport |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HIDDevice: vendorId property - Web APIs

HIDDevice: vendorId property
============================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`vendorId`** read-only property of the `HIDDevice` interface returns the vendor ID of the connected HID device. This identifies the vendor of the device.

Value
-----

An integer. If the device has no vendor ID, or the vendor ID cannot be accessed this will return `0`.

Examples
--------

The following example retrieves devices with `HID.getDevices()` and logs the value of `vendorId` to the console.

```js
document.addEventListener("DOMContentLoaded", async () => {
  let devices = await navigator.hid.getDevices();
  devices.forEach((device) => {
    console.log(`HID: ${device.vendorId}`);
  });
});
```

Specifications
--------------

| Specification |
| --- |
| WebHID API # dom-hiddevice-vendorid |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HIDDevice: forget() method - Web APIs

HIDDevice: forget() method
==========================

**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`forget()`** method of the `HIDDevice` interface closes the connection to the HID device and forgets the device.

Syntax
------

```js
forget()
```

### Parameters

None.

### Return value

A `Promise` that resolves with `undefined` once the connection is closed, the device is forgotten, and the permission is reset.

Example
-------

In the following example we connect to a Nintendo Switch Joy-Con Right HID device, blink once, and disconnect from it.

```js
async function blink() {
  const devices = await navigator.hid.requestDevice({
    filters: [
      {
        vendorId: 0x057e, // Nintendo Co., Ltd
        productId: 0x2007, // Joy-Con Right
      },
    ],
  });
  const device = devices[0];
  await device.open();
  // Turn off
  await device.sendFeatureReport(reportId, Uint32Array.from([0, 0]));
  await waitFor(100);
  // Turn on
  await device.sendFeatureReport(reportId, Uint32Array.from([512, 0]));
  await new Promise((resolve) => setTimeout(resolve, 100));
  // Finally, disconnect from it
  await device.forget();
}
blink();
```

Specifications
--------------

| Specification |
| --- |
| WebHID API # dom-hiddevice-forget |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HIDDevice: open() method - Web APIs

HIDDevice: open() method
========================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`open()`** method of the `HIDDevice` interface requests that the operating system opens the HID device.

**Note:** HID devices are not opened automatically. Therefore, a `HIDDevice` returned by `HID.requestDevice()` must be opened with this method before it is available to transfer data.

Syntax
------

```js
open()
```

### Parameters

None.

### Return value

A `Promise` that resolves with `undefined` once the connection is opened.

### Exceptions

`InvalidStateError` `DOMException`

Thrown if the connection is already open.

`NotAllowedError` `DOMException`

Thrown if the attempt to open the connection fails for any reason.

Examples
--------

In the following example, we wait for the HID connection to open before attempting to send or receive data.

```js
await device.open();
```

Specifications
--------------

| Specification |
| --- |
| WebHID API # dom-hiddevice-open |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HIDDevice: opened property - Web APIs

HIDDevice: opened property
==========================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`opened`** read-only property of the `HIDDevice` interface returns true if the connection to the `HIDDevice` is open and ready to transfer data.

Value
-----

A boolean value, true if the connection is open.

Examples
--------

The following example retrieves devices with `HID.getDevices()` and logs the value of `opened` to the console.

```js
document.addEventListener("DOMContentLoaded", async () => {
  let devices = await navigator.hid.getDevices();
  devices.forEach((device) => {
    console.log(`HID: ${device.opened}`);
  });
});
```

Specifications
--------------

| Specification |
| --- |
| WebHID API # dom-hiddevice-opened |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HIDDevice: sendReport() method - Web APIs

HIDDevice: sendReport() method
==============================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`sendReport()`** method of the `HIDDevice` interface sends an output report to the HID device.

The `reportId` for each of the report formats that this device supports can be retrieved from `HIDDevice.collections`.

Syntax
------

```js
sendReport(reportId, data)
```

### Parameters

`reportId`

An 8-bit report ID. If the HID device does not use report IDs, send `0`.

`data`

Bytes as an `ArrayBuffer`, a `TypedArray`, or a `DataView`.

### Return value

A `Promise` that resolves with `undefined` once the report has been sent.

### Exceptions

`NotAllowedError` `DOMException`

Thrown if sending the report fails for any reason.

Examples
--------

The example below shows how to make a Joy-Con device rumble using output reports. You can see more examples, and live demos in the article Connecting to uncommon HID devices.

```js
// First, send a command to enable vibration.
// Magical bytes come from https://github.com/mzyy94/joycon-toolweb
const enableVibrationData = [1, 0, 1, 64, 64, 0, 1, 64, 64, 0x48, 0x01];
await device.sendReport(0x01, new Uint8Array(enableVibrationData));

// Then, send a command to make the Joy-Con device rumble.
// Actual bytes are available in the sample.
const rumbleData = [
  /\* … \*/
];
await device.sendReport(0x10, new Uint8Array(rumbleData));
```

Specifications
--------------

| Specification |
| --- |
| WebHID API # dom-hiddevice-sendreport |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HIDDevice: productName property - Web APIs

HIDDevice: productName property
===============================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`productName`** read-only property of the `HIDDevice` interface returns the product name of the connected HID device.

Value
-----

A string.

Examples
--------

The following example retrieves devices with `HID.getDevices()` and logs the value of `productName` to the console.

```js
document.addEventListener("DOMContentLoaded", async () => {
  let devices = await navigator.hid.getDevices();
  devices.forEach((device) => {
    console.log(`HID: ${device.productName}`);
  });
});
```

Specifications
--------------

| Specification |
| --- |
| WebHID API # dom-hiddevice-productname |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TrustedTypePolicy: createScriptURL() method - Web APIs

TrustedTypePolicy: createScriptURL() method
===========================================

The **`createScriptURL()`** method of the `TrustedTypePolicy` interface creates a `TrustedScriptURL` object using a policy created by `TrustedTypePolicyFactory.createPolicy()`.

Syntax
------

```js
createScriptURL(input)
createScriptURL(input, args)
```

### Parameters

`input`

A string containing the string to be sanitized by the policy.

`args` Optional

Additional arguments to be passed to the function represented by `TrustedTypePolicy`.

### Return value

A `TrustedScriptURL` object.

### Exceptions

`TypeError`

Thrown if `TrustedTypePolicy` does not contain a function to run on the input.

Examples
--------

In the below example a string containing the URL to an external resource is used as the input for `createScriptURL()`. The policy can check that this is an allowed URL before inserting it into an injection sink that could cause this external script to be executed.

```js
const escaped = escapeURLPolicy.createScriptURL(
  "https://example.com/my-script.js",
);
```

Specifications
--------------

| Specification |
| --- |
| Trusted Types # dom-trustedtypepolicy-createscripturl |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TrustedTypePolicy: createHTML() method - Web APIs

TrustedTypePolicy: createHTML() method
======================================

The **`createHTML()`** method of the `TrustedTypePolicy` interface creates a `TrustedHTML` object using a policy created by `TrustedTypePolicyFactory.createPolicy()`.

Syntax
------

```js
createHTML(input)
createHTML(input, args)
```

### Parameters

`input`

A string containing the string to be sanitized by the policy.

`args` Optional

Additional arguments to be passed to the function represented by `TrustedTypePolicy`.

### Return value

A `TrustedHTML` object.

### Exceptions

`TypeError`

Thrown if `TrustedTypePolicy` does not contain a function to run on the input.

Examples
--------

In the below example a string containing a potentially dangerous script is used as the input for `createHTML()`. Dangerous code inserted by a user could then be sanitized before insertion into any injection sink.

```js
const escaped = escapeHTMLPolicy.createHTML("<img src=x onerror=alert(1)>");
```

Specifications
--------------

| Specification |
| --- |
| Trusted Types # dom-trustedtypepolicy-createhtml |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TrustedTypePolicy: createScript() method - Web APIs

TrustedTypePolicy: createScript() method
========================================

The **`createScript()`** method of the `TrustedTypePolicy` interface creates a `TrustedScript` object using a policy created by `TrustedTypePolicyFactory.createPolicy()`.

Syntax
------

```js
createScript(input)
createScript(input, args)
```

### Parameters

`input`

A string containing the string to be sanitized by the policy.

`args` Optional

Additional arguments to be passed to the function represented by `TrustedTypePolicy`.

### Return value

A `TrustedScript` object.

### Exceptions

`TypeError`

Thrown if `TrustedTypePolicy` does not contain a function to run on the input.

Examples
--------

In the below example a string containing a potentially risky script is used as the input for `createScript()`. The policy can sanitize this script before inserting it into an injection sink that could cause it to be executed.

```js
const sanitized = scriptPolicy.createScript("eval('2 + 2')");
```

Specifications
--------------

| Specification |
| --- |
| Trusted Types # dom-trustedtypepolicy-createscript |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TrustedTypePolicy: name property - Web APIs

TrustedTypePolicy: name property
================================

The **`name`** read-only property of the `TrustedTypePolicy` interface returns the name of the policy.

Value
-----

A string containing the name of the policy.

Examples
--------

In the below example a policy called `myEscapePolicy` is created using `TrustedTypePolicyFactory.createPolicy()` and is represented by the object `escapeHTMLPolicy`. Calling `name` on this object returns the string "myEscapePolicy".

```js
const escapeHTMLPolicy = trustedTypes.createPolicy("myEscapePolicy", {
  createHTML: (string) => string.replace(/>/g, "<"),
});

console.log(escapeHTMLPolicy.name); /\* "myEscapePolicy" \*/
```

Specifications
--------------

| Specification |
| --- |
| Trusted Types # dom-trustedtypepolicy-name |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLVideoElement: requestPictureInPicture() method - Web APIs

HTMLVideoElement: requestPictureInPicture() method
==================================================

 The **`HTMLVideoElement`** method
 **`requestPictureInPicture()`** issues an asynchronous request
 to display the video in picture-in-picture mode.

 It's not guaranteed that the video will be put into picture-in-picture. If permission
 to enter that mode is granted, the returned `Promise` will resolve and the
 video will receive a `enterpictureinpicture` event to let it know that it's now in picture-in-picture.

Syntax
------

```js
requestPictureInPicture()
```

### Parameters

None.

### Return value

 A `Promise` that will resolve to a `PictureInPictureWindow`
 object that can be used to listen when a user will resize that floating window.

### Exceptions

`NotSupportedError` `DOMException`

Thrown if the feature is not supported (for example, disabled by a user preference or by a platform limitation).

`SecurityError` `DOMException`

Thrown if the feature is blocked by a Permissions Policy.

`InvalidStateError` `DOMException`

Thrown if the video element's `readState` is `HAVE_NOTHING`, or if the video element has no video track, or if the video element's `disablePictureInPicture` attribute is `true`.

`NotAllowedError` `DOMException`

Thrown if `document.pictureInPictureElement` is `null` and the document does not have transient activation.

Security
--------

Transient user activation is required. The user has to interact with the page or a UI element for this feature to work.

Examples
--------

 This example requests that the video enters Picture-in-Picture mode, and sets an event
 listener to handle the floating window resizing.

```js
function enterPictureInPicture() {
  videoElement.requestPictureInPicture().then((pictureInPictureWindow) => {
    pictureInPictureWindow.addEventListener(
      "resize",
      () => onPipWindowResize(),
      false,
    );
  });
}
```

Specifications
--------------

| Specification |
| --- |
| Picture-in-Picture # request-pip |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* The `<video>` element
* `HTMLVideoElement.disablePictureInPicture`
* `Document.pictureInPictureEnabled`
* `Document.exitPictureInPicture()`
* `Document.pictureInPictureElement`
* `:picture-in-picture`


HTMLVideoElement: leavepictureinpicture event - Web APIs

HTMLVideoElement: leavepictureinpicture event
=============================================

The `leavepictureinpicture` event is fired when the `HTMLVideoElement` leaves picture-in-picture mode successfully.

This event is not cancelable and does not bubble.

Syntax
------

Use the event name in methods like `addEventListener()`, or set an event handler property.

```js
addEventListener("leavepictureinpicture", (event) => {});

onleavepictureinpicture = (event) => {};
```

Event type
----------

A `PictureInPictureEvent`. Inherits from `Event`.

Event

PictureInPictureEventEvent properties
----------------

This interface also inherits properties from its parent `Event`.

Examples
--------

These examples add an event listener for the HTMLVideoElement's `leavepictureinpicture` event, then post a message when that event handler has reacted to the event firing.

Using `addEventListener()`:

```js
const video = document.querySelector("#video");
const button = document.querySelector("#button");

function onExitPip() {
  console.log("Picture-in-Picture mode deactivated!");
}

video.addEventListener("leavepictureinpicture", onExitPip, false);

button.onclick = () => {
  if (document.pictureInPictureElement) {
    document.exitPictureInPicture();
  }
};
```

Using the `onleavepictureinpicture` event handler property:

```js
const video = document.querySelector("#video");
const button = document.querySelector("#button");

function onExitPip() {
  console.log("Picture-in-Picture mode deactivated!");
}

video.onleavepictureinpicture = onExitPip;

button.onclick = () => {
  if (document.pictureInPictureElement) {
    document.exitPictureInPicture();
  }
};
```

Specifications
--------------

| Specification |
| --- |
| Picture-in-Picture # eventdef-htmlvideoelement-leavepictureinpicture |
| Picture-in-Picture # dom-htmlvideoelement-onleavepictureinpicture |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `HTMLVideoElement`
* `Picture-in-Picture API`


HTMLVideoElement: disablePictureInPicture property - Web APIs

HTMLVideoElement: disablePictureInPicture property
==================================================

The `HTMLVideoElement` **`disablePictureInPicture`** property reflects the HTML attribute indicating whether the picture-in-picture feature is disabled for the current element.

Value
-----

A boolean value that is `true` if the picture-in-picture feature is disabled for this element. This means that the user agent should not suggest that feature to users, or request it automatically.

Specifications
--------------

| Specification |
| --- |
| Picture-in-Picture # disable-pip |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLVideoElement: getVideoPlaybackQuality() method - Web APIs

HTMLVideoElement: getVideoPlaybackQuality() method
==================================================

 The **`HTMLVideoElement`** method
 **`getVideoPlaybackQuality()`** creates and returns a
 `VideoPlaybackQuality` object containing metrics including how many
 frames have been lost.

The data returned can be used to evaluate the quality of the video stream.

Syntax
------

```js
getVideoPlaybackQuality()
```

### Parameters

None.

### Return value

 A `VideoPlaybackQuality` object providing information about the video
 element's current playback quality.

Examples
--------

 This example updates an element to indicate the total number of video frames that have
 elapsed so far in the playback process. This value includes any dropped or corrupted
 frames, so it's not the same as "total number of frames played."

```js
const videoElem = document.getElementById("my\_vid");
const counterElem = document.getElementById("counter");
const quality = videoElem.getVideoPlaybackQuality();

counterElem.innerText = quality.totalVideoFrames;
```

Specifications
--------------

| Specification |
| --- |
| Media Playback Quality # dom-htmlvideoelement-getvideoplaybackquality |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* The `<video>` element
* The `VideoPlaybackQuality` interface.


HTMLVideoElement: videoWidth property - Web APIs

HTMLVideoElement: videoWidth property
=====================================

 The `HTMLVideoElement` interface's read-only **`videoWidth`** property indicates the intrinsic width of the video, expressed in CSS pixels.
 In simple terms, this is the width of the media in its natural size.

See `HTMLVideoElement.videoHeight` > About intrinsic width and height for more details.

Value
-----

 An integer value specifying the intrinsic width of the video in CSS pixels.
 If the element's `readyState` is `HTMLMediaElement.HAVE_NOTHING`, then the value of this property is 0, because neither video nor poster frame size information is yet available.

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-video-videowidth-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLVideoElement: videoHeight property - Web APIs

HTMLVideoElement: videoHeight property
======================================

 The `HTMLVideoElement` interface's read-only **`videoHeight`** property indicates the intrinsic height of the video, expressed in CSS pixels.
 In simple terms, this is the height of the media in its natural size.

Value
-----

 An integer value specifying the intrinsic height of the video in CSS pixels.
 If the element's `readyState` is `HTMLMediaElement.HAVE_NOTHING`, then the value of this property is 0, because neither video nor poster frame size information is yet available.

### About intrinsic width and height

A user agent calculates the intrinsic width and height of the element's media by starting with the media's raw pixel width and height, then taking into account factors including:

* The media's aspect ratio.
* The media's clean aperture (the sub-rectangle centered within the media that matches
 the target aspect ratio).
* The target device's resolution.
* Any other factors required by the media format.

If the element is currently displaying the poster frame rather than rendered video, the poster frame's intrinsic size is considered to be the size of the `<video>` element.

 If at any time the intrinsic size of the media changes and the element's `readyState` isn't `HAVE_NOTHING`, a `resize` event will be sent to the `<video>` element.
 This can happen when the element switches from displaying the poster frame to displaying video content, or when the displayed video track changes.

Examples
--------

This example creates a handler for the `resize` event that resizes the `<video>` element to match the intrinsic size of its contents.

```js
let v = document.getElementById("myVideo");

v.addEventListener(
  "resize",
  (ev) => {
    let w = v.videoWidth;
    let h = v.videoHeight;

    if (w && h) {
      v.style.width = w;
      v.style.height = h;
    }
  },
  false,
);
```

 Note that this only applies the change if both the `videoWidth` and the `videoHeight` are non-zero.
 This avoids applying invalid changes when there's no true information available yet for dimensions.

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-video-videoheight-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLVideoElement: enterpictureinpicture event - Web APIs

HTMLVideoElement: enterpictureinpicture event
=============================================

The `enterpictureinpicture` event is fired when the `HTMLVideoElement` enters picture-in-picture mode successfully.

This event is not cancelable and does not bubble.

Syntax
------

Use the event name in methods like `addEventListener()`, or set an event handler property.

```js
addEventListener("enterpictureinpicture", (event) => {});

onenterpictureinpicture = (event) => {};
```

Event type
----------

A `PictureInPictureEvent`. Inherits from `Event`.

Event

PictureInPictureEventEvent properties
----------------

This interface also inherits properties from its parent `Event`.

Examples
--------

These examples add an event listener for the HTMLVideoElement's `enterpictureinpicture` event, then post a message when that event handler has reacted to the event firing.

Using `addEventListener()`:

```js
const video = document.querySelector("#video");
const button = document.querySelector("#button");

function onEnterPip() {
  console.log("Picture-in-Picture mode activated!");
}

video.addEventListener("enterpictureinpicture", onEnterPip, false);

button.onclick = () => {
  video.requestPictureInPicture();
};
```

Using the `onenterpictureinpicture` event handler property:

```js
const video = document.querySelector("#video");
const button = document.querySelector("#button");

function onEnterPip() {
  console.log("Picture-in-Picture mode activated!");
}

video.onenterpictureinpicture = onEnterPip;

button.onclick = () => {
  video.requestPictureInPicture();
};
```

Specifications
--------------

| Specification |
| --- |
| Picture-in-Picture # eventdef-htmlvideoelement-enterpictureinpicture |
| Picture-in-Picture # dom-htmlvideoelement-onenterpictureinpicture |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `HTMLVideoElement`
* `Picture-in-Picture API`


CSSNumericValue: add() method - Web APIs

CSSNumericValue: add() method
=============================

 The **`add()`** method of the
 `CSSNumericValue` interface adds a supplied number to the
 `CSSNumericValue`.

Syntax
------

```js
add(number)
```

### Parameters

`number`

Either a number or a `CSSNumericValue`.

### Return value

A `CSSMathSum`

### Exceptions

`TypeError`

Thrown if an invalid type was passed to the method.

Examples
--------

```js
let mathSum = CSS.px("23")
  .add(CSS.percent("4"))
  .add(CSS.cm("3"))
  .add(CSS.in("9"));
// Prints "calc(23px + 4% + 3cm + 9in)"
console.log(mathSum.toString());
```

Specifications
--------------

| Specification |
| --- |
| CSS Typed OM Level 1 # dom-cssnumericvalue-add |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSNumericValue: to() method - Web APIs

CSSNumericValue: to() method
============================

 The **`to()`** method of the
 `CSSNumericValue` interface converts a numeric value from one unit to
 another.

Syntax
------

```js
to(unit)
```

### Parameters

`unit`

The unit to which you want to convert.

### Return value

A `CSSMathSum`.

### Exceptions

`SyntaxError` `DOMException`

Thrown if an invalid type was passed to the method.

`TypeError`

Thrown if the passed values cannot be summed.

Examples
--------

```js
// Prints "0.608542cm"
console.log(CSS.px("23").to("cm").toString());
```

Specifications
--------------

| Specification |
| --- |
| CSS Typed OM Level 1 # dom-cssnumericvalue-to |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSNumericValue: max() method - Web APIs

CSSNumericValue: max() method
=============================

 The **`max()`** method of the
 `CSSNumericValue` interface returns the highest value from among the values
 passed. The passed values must be of the same type.

Syntax
------

```js
max(number1, /\* …, \*/ numberN)
```

### Parameters

`number1`, …, `numberN`

Either a number or a `CSSNumericValue`.

### Return value

A `CSSUnitValue`.

### Exceptions

`TypeError`

Thrown if an invalid type was passed to the method.

Examples
--------

 As stated earlier, all passed values must be of the same type and value. Some of the
 following examples illustrate what happens when they are not.

```js
// Prints "2cm"
console.log(CSS.cm("1").max(CSS.cm("2")).toString());

// Prints "max(1cm, 0.393701in)"
console.log(CSS.cm("1").max(CSS.in("0.393701")).toString());
```

Specifications
--------------

| Specification |
| --- |
| CSS Typed OM Level 1 # dom-cssnumericvalue-max |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSNumericValue: min() method - Web APIs

CSSNumericValue: min() method
=============================

 The **`min()`** method of the
 `CSSNumericValue` interface returns the lowest value from among those
 values passed. The passed values must be of the same type.

Syntax
------

```js
min(number1, /\* …, \*/ numberN)
```

### Parameters

`number1`, …, `numberN`

Either a number or a `CSSNumericValue`.

### Return value

A `CSSUnitValue`.

### Exceptions

`TypeError`

Thrown if an invalid type was passed to the method.

Examples
--------

 As stated earlier, all passed values must be of the same type and value. Some of the
 following examples illustrate what happens when they are not.

```js
// Prints "1cm"
console.log(CSS.cm("1").min(CSS.cm("2")).toString());

// Prints "max(1cm, 0.393701in)"
console.log(CSS.cm("1").max(CSS.in("0.393701")).toString());
```

Specifications
--------------

| Specification |
| --- |
| CSS Typed OM Level 1 # dom-cssnumericvalue-min |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSNumericValue: div() method - Web APIs

CSSNumericValue: div() method
=============================

 The **`div()`** method of the
 `CSSNumericValue` interface divides the `CSSNumericValue` by the
 supplied value.

Syntax
------

```js
div(number)
```

### Parameters

`number`

Either a number or a `CSSNumericValue`.

### Return value

A `CSSMathProduct`.

### Exceptions

`TypeError`

Thrown if an invalid type was passed to the method.

Examples
--------

```js
let mathProduct = CSS.px("24").div(CSS.percent("4"));
// Prints "calc(24px / 4%)"
mathProduct.toString();
```

Specifications
--------------

| Specification |
| --- |
| CSS Typed OM Level 1 # dom-cssnumericvalue-div |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.