Hook and simulate keyboard events on Windows and Linux
—
Programmatic keyboard input simulation for automating key presses, complex hotkey sequences, and text typing with full unicode support. The keyboard package provides precise control over timing, modifier states, and platform-specific character input methods.
Send individual keys or complex hotkey combinations programmatically.
def send(hotkey, do_press=True, do_release=True):
"""
Sends OS events that perform the given hotkey.
Parameters:
- hotkey: Key name, scan code, or multi-key combination (e.g. 'ctrl+alt+del')
- do_press: If True, send press events (default: True)
- do_release: If True, send release events (default: True)
Examples:
- send('space')
- send('ctrl+c')
- send('alt+F4, enter') # Multi-step sequence
"""
def press_and_release(hotkey, do_press=True, do_release=True):
"""Alias for send(). Sends complete press and release cycle."""
def press(hotkey):
"""
Presses and holds down a hotkey (see send).
Parameters:
- hotkey: Key or key combination to press
"""
def release(hotkey):
"""
Releases a hotkey (see send).
Parameters:
- hotkey: Key or key combination to release
"""Check the current state of keys and detect pressed key combinations.
def is_pressed(hotkey):
"""
Returns True if the key is pressed.
Parameters:
- hotkey: Key name, scan code, or combination to check
Returns:
bool: True if currently pressed
Examples:
- is_pressed('space') # Single key
- is_pressed('ctrl+c') # Key combination
"""Type text with comprehensive unicode support and keyboard layout awareness.
def write(text, delay=0, restore_state_after=True, exact=None):
"""
Sends artificial keyboard events to type the given text. Characters not
available on the keyboard are typed as explicit unicode characters using
OS-specific functionality.
Parameters:
- text: Text string to type
- delay: Seconds to wait between keypresses (default: 0)
- restore_state_after: Restore pressed keys after typing (default: True)
- exact: Force unicode typing for all characters (default: platform-dependent)
Notes:
- All currently pressed keys are released before typing
- Modifier keys are restored after typing if restore_state_after=True
- Uses platform-specific unicode input methods for special characters
"""Advanced state management for complex automation scenarios.
def stash_state():
"""
Builds a list of all currently pressed scan codes, releases them and returns
the list. Pairs well with restore_state() and restore_modifiers().
Returns:
list: Currently pressed scan codes
"""
def restore_state(scan_codes):
"""
Given a list of scan codes ensures these keys, and only these keys, are
pressed. Pairs well with stash_state().
Parameters:
- scan_codes: List of scan codes to press
"""
def restore_modifiers(scan_codes):
"""
Like restore_state(), but only restores modifier keys.
Parameters:
- scan_codes: List of scan codes to check for modifiers
"""Remap keys to different functions or key combinations.
def remap_key(src, dst):
"""
Whenever the key src is pressed or released, regardless of modifiers,
press or release the hotkey dst instead.
Parameters:
- src: Source key to remap
- dst: Destination hotkey to send instead
Returns:
Function to remove the remapping
"""import keyboard
# Simple key presses
keyboard.press_and_release('space')
keyboard.send('enter')
# Key combinations
keyboard.send('ctrl+c') # Copy
keyboard.send('ctrl+v') # Paste
keyboard.send('alt+tab') # Window switch
keyboard.send('ctrl+alt+del') # Secure attention sequence
# Multi-step sequences
keyboard.send('ctrl+f, hello, enter') # Find "hello"import keyboard
# Basic text input
keyboard.write('Hello, World!')
# Text with special characters
keyboard.write('Café, naïve, résumé') # Unicode characters
# Controlled typing speed
keyboard.write('Slow typing...', delay=0.1) # 100ms between characters
# Platform-specific unicode handling
keyboard.write('Mathematical: ∑, ∞, π', exact=True) # Force unicode methodimport keyboard
# Save current state
current_state = keyboard.stash_state()
# Perform some operations
keyboard.write('Some automated text')
keyboard.send('ctrl+s') # Save
# Restore original key state
keyboard.restore_state(current_state)import keyboard
# Remap Caps Lock to Ctrl
remove_remap = keyboard.remap_key('caps lock', 'ctrl')
print('Caps Lock now acts as Ctrl. Press ESC to exit.')
keyboard.wait('esc')
# Remove the remapping
remove_remap()import keyboard
def check_modifier_combo():
if keyboard.is_pressed('ctrl+shift'):
print('Ctrl+Shift is pressed!')
elif keyboard.is_pressed('ctrl'):
print('Ctrl is pressed')
elif keyboard.is_pressed('shift'):
print('Shift is pressed')
# Check continuously
while True:
check_modifier_combo()
if keyboard.is_pressed('esc'):
breakimport keyboard
import time
def automated_data_entry():
# Save current keyboard state
saved_state = keyboard.stash_state()
try:
# Type form data with delays
keyboard.write('John Doe', delay=0.05)
keyboard.send('tab')
time.sleep(0.1)
keyboard.write('john.doe@example.com', delay=0.03)
keyboard.send('tab')
time.sleep(0.1)
keyboard.write('555-123-4567', delay=0.05)
keyboard.send('tab')
# Submit form
keyboard.send('enter')
finally:
# Restore original keyboard state
keyboard.restore_modifiers(saved_state)
# Trigger automation with hotkey
keyboard.add_hotkey('ctrl+shift+f', automated_data_entry)
keyboard.wait('esc')def key_to_scan_codes(key, error_if_missing=True):
"""
Returns a list of scan codes associated with this key (name or scan code).
Parameters:
- key: Key name, scan code, or list of keys
- error_if_missing: Raise error if key not found (default: True)
Returns:
tuple: Scan codes for the key
"""
def parse_hotkey(hotkey):
"""
Parses a user-provided hotkey into nested tuples representing the
parsed structure, with the bottom values being lists of scan codes.
Parameters:
- hotkey: Hotkey string to parse (e.g., 'ctrl+shift+a, alt+b')
Returns:
tuple: Parsed hotkey structure
"""
def normalize_name(name):
"""
Given a key name, clean up the string and convert to canonical
representation if one is known.
Parameters:
- name: Key name to normalize
Returns:
str: Normalized key name
"""
def is_modifier(key):
"""
Returns True if key is a scan code or name of a modifier key.
Parameters:
- key: Key name or scan code to check
Returns:
bool: True if key is a modifier
"""
def parse_hotkey_combinations(hotkey):
"""
Parses a user-provided hotkey. Instead of each step being a list of the
different scan codes for each key, each step is a list of all possible
combinations of those scan codes.
Parameters:
- hotkey: Hotkey string to parse
Returns:
tuple: All possible scan code combinations for the hotkey
Note: This is used internally for hotkey matching optimization.
"""The keyboard package supports flexible hotkey string formats:
'a' - Letter key'space' - Named key'enter' - Special key57 - Scan code'ctrl+c' - Modifier + key'ctrl+shift+a' - Multiple modifiers'alt+F4' - Case insensitive'ctrl+c, ctrl+v' - Copy then paste'alt+tab, enter' - Switch window then confirm'win+r, notepad, enter' - Open Run, type "notepad", press Enter'ctrl+plus' - Use 'plus' for '+' symbol'ctrl+comma' - Use 'comma' for ',' symbol'ctrl+space' - Use 'space' for spacebarExecute functions with a delay without blocking the current thread.
def call_later(fn, args=(), delay=0.001):
"""
Calls the provided function in a new thread after waiting some time.
Useful for giving the system some time to process an event, without blocking
the current execution flow.
Parameters:
- fn: Function to call
- args: Arguments to pass to function (default: empty tuple)
- delay: Delay in seconds before calling function (default: 0.001)
Examples:
call_later(print, args=['Hello after delay'])
call_later(lambda: keyboard.send('enter'), delay=0.5)
"""Key simulation may fail due to:
The package will raise ValueError for invalid keys and OSError for platform-specific failures.
Install with Tessl CLI
npx tessl i tessl/pypi-keyboard