Keyboard Scancodes
This document provides a reference for the keyboard scancodes used by the SPICE
protocol's inputs channel. SPICE uses IBM PC XT-compatible scancodes (Set 1).
SPICE supports two scancode formats:
Simple Scancodes (key_down/key_up messages)
The key_down (ID 101) and key_up (ID 102) messages use a 32-bit scancode
field. For standard keys, only the low byte is used.
Raw Scancodes (key_scancode message)
The key_scancode (ID 104) message sends raw XT scancodes as a byte array.
This format is more efficient for extended keys and supports:
- Key press: Scancode byte as-is
- Key release: Scancode byte OR'd with 0x80 (high bit set)
- Extended keys: Prefixed with 0xE0 byte
For example:
- Press 'A': [0x1E]
- Release 'A': [0x9E] (0x1E | 0x80)
- Press Right Ctrl: [0xE0, 0x1D]
- Release Right Ctrl: [0xE0, 0x9D]
Standard Scancodes
Main Keyboard - Row 1 (Function Keys)
| Key |
Scancode |
Hex |
| Escape |
1 |
0x01 |
| F1 |
59 |
0x3B |
| F2 |
60 |
0x3C |
| F3 |
61 |
0x3D |
| F4 |
62 |
0x3E |
| F5 |
63 |
0x3F |
| F6 |
64 |
0x40 |
| F7 |
65 |
0x41 |
| F8 |
66 |
0x42 |
| F9 |
67 |
0x43 |
| F10 |
68 |
0x44 |
| F11 |
87 |
0x57 |
| F12 |
88 |
0x58 |
Main Keyboard - Row 2 (Number Row)
| Key |
Scancode |
Hex |
| ` (Backquote) |
41 |
0x29 |
| 1 |
2 |
0x02 |
| 2 |
3 |
0x03 |
| 3 |
4 |
0x04 |
| 4 |
5 |
0x05 |
| 5 |
6 |
0x06 |
| 6 |
7 |
0x07 |
| 7 |
8 |
0x08 |
| 8 |
9 |
0x09 |
| 9 |
10 |
0x0A |
| 0 |
11 |
0x0B |
| - (Minus) |
12 |
0x0C |
| = (Equal) |
13 |
0x0D |
| Backspace |
14 |
0x0E |
Main Keyboard - Row 3 (QWERTY)
| Key |
Scancode |
Hex |
| Tab |
15 |
0x0F |
| Q |
16 |
0x10 |
| W |
17 |
0x11 |
| E |
18 |
0x12 |
| R |
19 |
0x13 |
| T |
20 |
0x14 |
| Y |
21 |
0x15 |
| U |
22 |
0x16 |
| I |
23 |
0x17 |
| O |
24 |
0x18 |
| P |
25 |
0x19 |
| [ (BracketLeft) |
26 |
0x1A |
| ] (BracketRight) |
27 |
0x1B |
| \ (Backslash) |
43 |
0x2B |
Main Keyboard - Row 4 (ASDF)
| Key |
Scancode |
Hex |
| Caps Lock |
58 |
0x3A |
| A |
30 |
0x1E |
| S |
31 |
0x1F |
| D |
32 |
0x20 |
| F |
33 |
0x21 |
| G |
34 |
0x22 |
| H |
35 |
0x23 |
| J |
36 |
0x24 |
| K |
37 |
0x25 |
| L |
38 |
0x26 |
| ; (Semicolon) |
39 |
0x27 |
| ' (Quote) |
40 |
0x28 |
| Enter |
28 |
0x1C |
Main Keyboard - Row 5 (ZXCV)
| Key |
Scancode |
Hex |
| Left Shift |
42 |
0x2A |
| Z |
44 |
0x2C |
| X |
45 |
0x2D |
| C |
46 |
0x2E |
| V |
47 |
0x2F |
| B |
48 |
0x30 |
| N |
49 |
0x31 |
| M |
50 |
0x32 |
| , (Comma) |
51 |
0x33 |
| . (Period) |
52 |
0x34 |
| / (Slash) |
53 |
0x35 |
| Right Shift |
54 |
0x36 |
Main Keyboard - Row 6 (Bottom)
| Key |
Scancode |
Hex |
| Left Ctrl |
29 |
0x1D |
| Left Alt |
56 |
0x38 |
| Space |
57 |
0x39 |
Numeric Keypad
| Key |
Scancode |
Hex |
| Numpad 7 (Home) |
71 |
0x47 |
| Numpad 8 (Up) |
72 |
0x48 |
| Numpad 9 (PgUp) |
73 |
0x49 |
| Numpad - |
74 |
0x4A |
| Numpad 4 (Left) |
75 |
0x4B |
| Numpad 5 |
76 |
0x4C |
| Numpad 6 (Right) |
77 |
0x4D |
| Numpad + |
78 |
0x4E |
| Numpad 1 (End) |
79 |
0x4F |
| Numpad 2 (Down) |
80 |
0x50 |
| Numpad 3 (PgDn) |
81 |
0x51 |
| Numpad 0 (Ins) |
82 |
0x52 |
| Numpad . (Del) |
83 |
0x53 |
| Numpad * |
55 |
0x37 |
| Numpad = |
89 |
0x59 |
| Numpad , |
126 |
0x7E |
Lock Keys
| Key |
Scancode |
Hex |
| Caps Lock |
58 |
0x3A |
| Scroll Lock |
70 |
0x46 |
| Pause |
69 |
0x45 |
Extended Function Keys (F13-F24)
| Key |
Scancode |
Hex |
| F13 |
100 |
0x64 |
| F14 |
101 |
0x65 |
| F15 |
102 |
0x66 |
| F16 |
103 |
0x67 |
| F17 |
104 |
0x68 |
| F18 |
105 |
0x69 |
| F19 |
106 |
0x6A |
| F20 |
107 |
0x6B |
| F21 |
108 |
0x6C |
| F22 |
109 |
0x6D |
| F23 |
110 |
0x6E |
| F24 |
118 |
0x76 |
International Keys
| Key |
Scancode |
Hex |
| IntlBackslash |
86 |
0x56 |
| IntlRo |
115 |
0x73 |
| IntlYen |
125 |
0x7D |
| KanaMode |
112 |
0x70 |
| Convert |
121 |
0x79 |
| NonConvert |
123 |
0x7B |
Extended Scancodes (E0 Prefix)
Extended keys require a 0xE0 prefix byte. When using the key_scancode message,
send [0xE0, scancode] for press and [0xE0, scancode | 0x80] for release.
When using key_down/key_up messages, the scancode is encoded as:
0xE0 | (scancode << 8)
Navigation Keys
| Key |
Extended Code |
Bytes (Press) |
| Insert |
0x52 |
E0 52 |
| Delete |
0x53 |
E0 53 |
| Home |
0x47 |
E0 47 |
| End |
0x4F |
E0 4F |
| Page Up |
0x49 |
E0 49 |
| Page Down |
0x51 |
E0 51 |
Arrow Keys
| Key |
Extended Code |
Bytes (Press) |
| Up Arrow |
0x48 |
E0 48 |
| Down Arrow |
0x50 |
E0 50 |
| Left Arrow |
0x4B |
E0 4B |
| Right Arrow |
0x4D |
E0 4D |
Right-Side Modifier Keys
| Key |
Extended Code |
Bytes (Press) |
| Right Ctrl |
0x1D |
E0 1D |
| Right Alt |
0x38 |
E0 38 |
| Left Meta (Windows) |
0x5B |
E0 5B |
| Right Meta (Windows) |
0x5C |
E0 5C |
| Context Menu |
0x5D |
E0 5D |
Numpad Extended Keys
| Key |
Extended Code |
Bytes (Press) |
| Numpad Enter |
0x1C |
E0 1C |
| Numpad / |
0x35 |
E0 35 |
| Num Lock |
0x45 |
E0 45 |
| Pause |
0x46 |
E0 46 |
| Print Screen |
0x37 |
E0 37 |
| Key |
Extended Code |
Bytes (Press) |
| Volume Mute |
0x20 |
E0 20 |
| Volume Down |
0x2E |
E0 2E |
| Volume Up |
0x30 |
E0 30 |
| Media Play/Pause |
0x22 |
E0 22 |
| Media Stop |
0x24 |
E0 24 |
| Media Previous |
0x10 |
E0 10 |
| Media Next |
0x19 |
E0 19 |
| Media Select |
0x6D |
E0 6D |
Browser Keys
| Key |
Extended Code |
Bytes (Press) |
| Browser Home |
0x32 |
E0 32 |
| Browser Back |
0x6A |
E0 6A |
| Browser Forward |
0x69 |
E0 69 |
| Browser Refresh |
0x67 |
E0 67 |
| Browser Stop |
0x68 |
E0 68 |
| Browser Search |
0x65 |
E0 65 |
| Browser Favorites |
0x66 |
E0 66 |
Application Launch Keys
| Key |
Extended Code |
Bytes (Press) |
| Launch App 1 (My Computer) |
0x6B |
E0 6B |
| Launch App 2 (Calculator) |
0x21 |
E0 21 |
| Launch Mail |
0x6C |
E0 6C |
| Power |
0x5E |
E0 5E |
Example: Typing "Hello"
Using key_scancode messages:
H press: [0x2A, 0x23] (Shift down, H down)
H release: [0xA3, 0xAA] (H up, Shift up)
e press: [0x12] (E down)
e release: [0x92] (E up)
l press: [0x26] (L down)
l release: [0xA6] (L up)
l press: [0x26] (L down)
l release: [0xA6] (L up)
o press: [0x18] (O down)
o release: [0x98] (O up)
References