Confused by complex code? Let our AI-powered Code Explainer demystify it for you. Try it out!
Python can simulate keyboard input, register global shortcuts, expand abbreviations, and listen for key events. This is useful for desktop automation, small productivity tools, accessibility helpers, game tooling, testing workflows, and scripts that fill repetitive forms.
In this tutorial, we will use the keyboard package to control the keyboard in Python. The original examples still work in many setups, but a few things are worth saying up front:
keyboard package is most convenient on Windows and Linux. On Linux, global hooks usually need root privileges or access to /dev/input.pynput or PyAutoGUI may be a smoother choice.We will cover pressing keys, typing text, holding keys, registering hotkeys, expanding text snippets, recording keyboard events, replaying macros, and a safer complete script that uses dry-run mode by default.
Related: How to Control your Mouse in Python.
Install it with pip:
pip install keyboard
On Linux, if you get permission errors while listening for global events, try running your script with sudo or configure proper input-device permissions for your user:
sudo python script.py
Then import it:
import keyboard
The simplest action is pressing and releasing one key:
import keyboard
keyboard.press_and_release("space")
keyboard.press_and_release("enter")
press_and_release() is explicit and easy to read. The shorter send() function does the same thing:
keyboard.send("space")
You can also send keyboard shortcuts:
keyboard.send("ctrl+c")
keyboard.send("ctrl+v")
keyboard.send("windows+d") # show desktop on Windows
For multi-step shortcuts, separate steps with a comma. For example, this sends Alt+F4, then Enter:
# Careful: this can close the active window.
keyboard.send("alt+f4, enter")
When automating real applications, always make sure the correct window is focused before sending keys. Keyboard automation sends events to the active application, not to a hidden window you choose by name.
Sometimes you need to hold a key, do something else, then release it. Use press() and release():
import time
import keyboard
keyboard.press("shift")
time.sleep(0.5)
keyboard.release("shift")
You can also use send() with do_press and do_release:
keyboard.send("ctrl", do_release=False)
# do something while Ctrl is held
keyboard.send("ctrl", do_press=False)
To type text, use write():
import keyboard
keyboard.write("Python keyboard automation is useful.", delay=0.03)
The delay argument is the delay between characters. A small delay often makes automation more reliable because some apps do not handle very fast artificial input well.
For example, this waits three seconds so you can focus a text editor, then types a short message:
import time
import keyboard
print("Focus your text editor. Typing starts in 3 seconds...")
time.sleep(3)
keyboard.write("Hello from Python!", delay=0.05)
You can check the state of a key with is_pressed():
import keyboard
if keyboard.is_pressed("ctrl"):
print("Ctrl is currently pressed")
A common pattern is a small loop that runs until the user presses Esc:
import time
import keyboard
print("Press Esc to stop.")
while not keyboard.is_pressed("esc"):
print("Working...")
time.sleep(1)
For a cleaner one-time wait, use wait():
keyboard.wait("esc")
print("Esc was pressed")
add_hotkey() lets you run a callback whenever a key combination is pressed:
import keyboard
keyboard.add_hotkey("ctrl+alt+h", lambda: print("Hello from a hotkey!"))
print("Press Ctrl+Alt+H, or press Esc to exit.")
keyboard.wait("esc")
keyboard.unhook_all()
The callback runs in a separate thread. Keep hotkey callbacks short. If your callback needs to do heavy work, put that work into a queue or start another thread/process yourself.
You can also remove one hotkey by keeping the handler returned by add_hotkey():
handler = keyboard.add_hotkey("ctrl+shift+x", lambda: print("Shortcut fired"))
# later
keyboard.remove_hotkey(handler)
Text expansion is one of the handiest features. The following expands @email into an email address after you type it and press Space:
import keyboard
keyboard.add_abbreviation("@email", "name@example.com")
keyboard.add_abbreviation("@addr", "221B Baker Street, London")
print("Type @email or @addr followed by Space. Press Esc to quit.")
keyboard.wait("esc")
keyboard.unhook_all()
This is useful for snippets you type often: email addresses, canned replies, signatures, support links, or test data.
You can listen for press and release events. For example, this prints released key names until you press Esc:
import keyboard
def on_key_release(event):
print(event.name)
if event.name == "esc":
keyboard.unhook_all()
keyboard.on_release(on_key_release)
keyboard.wait("esc")
Again, only do this in programs where the user understands what is being captured. Keyboard listeners can see sensitive input if you write them carelessly.
record() captures keyboard events until a stop key is pressed. play() replays them:
import keyboard
print("Recording. Press Esc to stop.")
events = keyboard.record("esc")
print("Typed strings:", list(keyboard.get_typed_strings(events)))
answer = input("Replay the recorded events? [y/N] ").strip().lower()
if answer == "y":
keyboard.play(events)
Replaying events is powerful, but it can also do the wrong thing very quickly if the wrong window is focused. In real scripts, add a countdown and ask for confirmation before replaying a macro.
The complete code below is written to be safer for learning and testing. By default, it runs in dry-run mode, meaning it only prints what it would do. Add --execute on your own desktop when you actually want to send or listen to keyboard events.
Save it as keyboard_controller_2026.py:
# Preview actions only
python keyboard_controller_2026.py typing
python keyboard_controller_2026.py hotkeys
python keyboard_controller_2026.py record
# Actually run on your local desktop
python keyboard_controller_2026.py typing --execute
python keyboard_controller_2026.py hotkeys --execute
python keyboard_controller_2026.py record --execute
The script is available in the full code section at the end of the tutorial.
The keyboard package is convenient for global hotkeys and quick scripts. Still, it is not the only choice:
pynput if you want a maintained library for monitoring and controlling keyboard/mouse input, especially across platforms.PyAutoGUI if your goal is broader GUI automation: clicking, screenshots, locating images on screen, and typing into active windows.Here is the basic pynput style for typing:
from pynput.keyboard import Controller, Key
keyboard = Controller()
keyboard.type("Hello from pynput!")
keyboard.press(Key.enter)
keyboard.release(Key.enter)
And here is the basic PyAutoGUI style:
import pyautogui
pyautogui.write("Hello from PyAutoGUI!", interval=0.03)
pyautogui.hotkey("ctrl", "s")
If you need global hotkeys and abbreviation expansion, keyboard is pleasant to use. If you need cross-platform input control with a more actively maintained package, check pynput. If you need full GUI automation, use PyAutoGUI.
Make sure the target application is focused. Try adding a short countdown before sending keys:
import time
print("Focus the target window...")
time.sleep(3)
Global keyboard hooks usually need root privileges or access to input devices. For a quick test, run with sudo. For a proper setup, configure input group permissions for your environment.
That is expected. Keyboard automation needs access to the local desktop session. Run it as a normal Python script on your machine.
Print the event names first:
import keyboard
keyboard.on_press(lambda event: print(event.name))
keyboard.wait("esc")
Then use the printed names in send(), press_and_release(), or add_hotkey().
The keyboard package makes it easy to automate keyboard input in Python: press keys, type text, hold modifiers, register shortcuts, expand snippets, and record simple macros. Use it for your own automation tasks, keep scripts easy to stop, and be careful with recording or replaying events.
For larger desktop automation projects, also look at PyAutoGUI and pynput.
Learn also: How to Convert Python Files into Executables.
Happy Coding ♥
Save time and energy with our Python Code Generator. Why start from scratch when you can generate? Give it a try!
View Full Code Generate Python Code
Got a coding query or need some guidance before you comment? Check out this Python Code Assistant for expert advice and handy tips. It's like having a coding tutor right in your fingertips!