It can be done using ctypes:

import ctypes
from ctypes import wintypes
import time

user32 = ctypes.WinDLL('user32', use_last_error=True)

INPUT_MOUSE    = 0
INPUT_KEYBOARD = 1
INPUT_HARDWARE = 2

KEYEVENTF_EXTENDEDKEY = 0x0001
KEYEVENTF_KEYUP       = 0x0002
KEYEVENTF_UNICODE     = 0x0004
KEYEVENTF_SCANCODE    = 0x0008

MAPVK_VK_TO_VSC = 0

# msdn.microsoft.com/en-us/library/dd375731
VK_TAB  = 0x09
VK_MENU = 0x12

# C struct definitions

wintypes.ULONG_PTR = wintypes.WPARAM

class MOUSEINPUT(ctypes.Structure):
    _fields_ = (("dx",          wintypes.LONG),
                ("dy",          wintypes.LONG),
                ("mouseData",   wintypes.DWORD),
                ("dwFlags",     wintypes.DWORD),
                ("time",        wintypes.DWORD),
                ("dwExtraInfo", wintypes.ULONG_PTR))

class KEYBDINPUT(ctypes.Structure):
    _fields_ = (("wVk",         wintypes.WORD),
                ("wScan",       wintypes.WORD),
                ("dwFlags",     wintypes.DWORD),
                ("time",        wintypes.DWORD),
                ("dwExtraInfo", wintypes.ULONG_PTR))

    def __init__(self, *args, **kwds):
        super(KEYBDINPUT, self).__init__(*args, **kwds)
        # some programs use the scan code even if KEYEVENTF_SCANCODE
        # isn't set in dwFflags, so attempt to map the correct code.
        if not self.dwFlags & KEYEVENTF_UNICODE:
            self.wScan = user32.MapVirtualKeyExW(self.wVk,
                                                 MAPVK_VK_TO_VSC, 0)

class HARDWAREINPUT(ctypes.Structure):
    _fields_ = (("uMsg",    wintypes.DWORD),
                ("wParamL", wintypes.WORD),
                ("wParamH", wintypes.WORD))

class INPUT(ctypes.Structure):
    class _INPUT(ctypes.Union):
        _fields_ = (("ki", KEYBDINPUT),
                    ("mi", MOUSEINPUT),
                    ("hi", HARDWAREINPUT))
    _anonymous_ = ("_input",)
    _fields_ = (("type",   wintypes.DWORD),
                ("_input", _INPUT))

LPINPUT = ctypes.POINTER(INPUT)

def _check_count(result, func, args):
    if result == 0:
        raise ctypes.WinError(ctypes.get_last_error())
    return args

user32.SendInput.errcheck = _check_count
user32.SendInput.argtypes = (wintypes.UINT, # nInputs
                             LPINPUT,       # pInputs
                             ctypes.c_int)  # cbSize

# Functions

def PressKey(hexKeyCode):
    x = INPUT(type=INPUT_KEYBOARD,
              ki=KEYBDINPUT(wVk=hexKeyCode))
    user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))

def ReleaseKey(hexKeyCode):
    x = INPUT(type=INPUT_KEYBOARD,
              ki=KEYBDINPUT(wVk=hexKeyCode,
                            dwFlags=KEYEVENTF_KEYUP))
    user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))

def AltTab():
    """Press Alt+Tab and hold Alt key for 2 seconds
    in order to see the overlay.
    """
    PressKey(VK_MENU)   # Alt
    PressKey(VK_TAB)    # Tab
    ReleaseKey(VK_TAB)  # Tab~
    time.sleep(2)
    ReleaseKey(VK_MENU) # Alt~

if __name__ == "__main__":
    AltTab()

hexKeyCode is the virtual keyboard mapping as defined by the Windows API. The list of codes is available on MSDN: Virtual-Key Codes (Windows)

Answer from lucasg on Stack Overflow
🌐
PyPI
pypi.org › project › keyboard
keyboard · PyPI
Take full control of your keyboard with this small Python library. Hook global events, register hotkeys, simulate key presses and much more. Global event hook on all keyboards (captures keys regardless of focus). Listen and send keyboard events.
      » pip install keyboard
    
Published   Mar 23, 2020
Version   0.13.5
Top answer
1 of 12
150

It can be done using ctypes:

import ctypes
from ctypes import wintypes
import time

user32 = ctypes.WinDLL('user32', use_last_error=True)

INPUT_MOUSE    = 0
INPUT_KEYBOARD = 1
INPUT_HARDWARE = 2

KEYEVENTF_EXTENDEDKEY = 0x0001
KEYEVENTF_KEYUP       = 0x0002
KEYEVENTF_UNICODE     = 0x0004
KEYEVENTF_SCANCODE    = 0x0008

MAPVK_VK_TO_VSC = 0

# msdn.microsoft.com/en-us/library/dd375731
VK_TAB  = 0x09
VK_MENU = 0x12

# C struct definitions

wintypes.ULONG_PTR = wintypes.WPARAM

class MOUSEINPUT(ctypes.Structure):
    _fields_ = (("dx",          wintypes.LONG),
                ("dy",          wintypes.LONG),
                ("mouseData",   wintypes.DWORD),
                ("dwFlags",     wintypes.DWORD),
                ("time",        wintypes.DWORD),
                ("dwExtraInfo", wintypes.ULONG_PTR))

class KEYBDINPUT(ctypes.Structure):
    _fields_ = (("wVk",         wintypes.WORD),
                ("wScan",       wintypes.WORD),
                ("dwFlags",     wintypes.DWORD),
                ("time",        wintypes.DWORD),
                ("dwExtraInfo", wintypes.ULONG_PTR))

    def __init__(self, *args, **kwds):
        super(KEYBDINPUT, self).__init__(*args, **kwds)
        # some programs use the scan code even if KEYEVENTF_SCANCODE
        # isn't set in dwFflags, so attempt to map the correct code.
        if not self.dwFlags & KEYEVENTF_UNICODE:
            self.wScan = user32.MapVirtualKeyExW(self.wVk,
                                                 MAPVK_VK_TO_VSC, 0)

class HARDWAREINPUT(ctypes.Structure):
    _fields_ = (("uMsg",    wintypes.DWORD),
                ("wParamL", wintypes.WORD),
                ("wParamH", wintypes.WORD))

class INPUT(ctypes.Structure):
    class _INPUT(ctypes.Union):
        _fields_ = (("ki", KEYBDINPUT),
                    ("mi", MOUSEINPUT),
                    ("hi", HARDWAREINPUT))
    _anonymous_ = ("_input",)
    _fields_ = (("type",   wintypes.DWORD),
                ("_input", _INPUT))

LPINPUT = ctypes.POINTER(INPUT)

def _check_count(result, func, args):
    if result == 0:
        raise ctypes.WinError(ctypes.get_last_error())
    return args

user32.SendInput.errcheck = _check_count
user32.SendInput.argtypes = (wintypes.UINT, # nInputs
                             LPINPUT,       # pInputs
                             ctypes.c_int)  # cbSize

# Functions

def PressKey(hexKeyCode):
    x = INPUT(type=INPUT_KEYBOARD,
              ki=KEYBDINPUT(wVk=hexKeyCode))
    user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))

def ReleaseKey(hexKeyCode):
    x = INPUT(type=INPUT_KEYBOARD,
              ki=KEYBDINPUT(wVk=hexKeyCode,
                            dwFlags=KEYEVENTF_KEYUP))
    user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))

def AltTab():
    """Press Alt+Tab and hold Alt key for 2 seconds
    in order to see the overlay.
    """
    PressKey(VK_MENU)   # Alt
    PressKey(VK_TAB)    # Tab
    ReleaseKey(VK_TAB)  # Tab~
    time.sleep(2)
    ReleaseKey(VK_MENU) # Alt~

if __name__ == "__main__":
    AltTab()

hexKeyCode is the virtual keyboard mapping as defined by the Windows API. The list of codes is available on MSDN: Virtual-Key Codes (Windows)

2 of 12
111

For both python3 and python2 you can use pyautogui (pip install pyautogui)

from pyautogui import press, typewrite, hotkey

press('a')
typewrite('quick brown fox')
hotkey('ctrl', 'w')

It's also crossplatform with Windows, OSX, and Ubuntu LTS.

Discussions

keyboard.send_keys(output) adds an unwanted enter (with Python 3)
commandstr="date "+%Y-%m-%d" --date="next sun"" output = system.exec_command(commandstr) keyboard.send_keys(output) But since i've upgraded from Autokey to Autokey with Python 3*, keyboard.send_keys(output) also gives an enter. I've also scripts where the (output) is in the middle of a script, ... More on github.com
🌐 github.com
8
July 22, 2017
keyboard - Send key combination with python - Stack Overflow
So far I was able to send CTRL + . (dot) like this : ... ... To specify that a combination of SHIFT, CTRL, and ALT should be held down while several other keys are pressed, create a compound string argument with the modified keystrokes enclosed in parentheses. More on stackoverflow.com
🌐 stackoverflow.com
python - How to make pywinauto faster (keyboard.send_keys)? - Stack Overflow
pwa.keyboard.send_keys ("StackOverflow") with this code, the text is printed 1 letter at a time (long) how to make it so that the text is entered completely at once? (works with 1000+ More on stackoverflow.com
🌐 stackoverflow.com
python - set the cursor inside the function "keyboard.send_keys" - Stack Overflow
Communities for your favorite technologies. Explore all Collectives · Ask questions, find answers and collaborate at work with Stack Overflow for Teams More on stackoverflow.com
🌐 stackoverflow.com
February 18, 2018
🌐
Readthedocs
pywinauto.readthedocs.io › en › latest › code › pywinauto.keyboard.html
pywinauto.keyboard — pywinauto 0.6.8 documentation
Automate typing keys or individual key actions (viz. press and hold, release) to an active window by calling send_keys method.
🌐
Nitratine
nitratine.net › blog › post › simulate-keypresses-in-python
Simulate Keypresses In Python - Nitratine
December 16, 2017 - Make a variable called keyboard and set it to an instance of Controller. Now using the keyboard variable we can press and release keys.
🌐
GitHub
github.com › boppreh › keyboard
GitHub - boppreh/keyboard: Hook and simulate global keyboard events on Windows and Linux. · GitHub
February 13, 2026 - Take full control of your keyboard with this small Python library. Hook global events, register hotkeys, simulate key presses and much more. Global event hook on all keyboards (captures keys regardless of focus). Listen and send keyboard events.
Starred by 4K users
Forked by 454 users
Languages   Python 99.7% | Makefile 0.3%
🌐
GitHub
github.com › gauthsvenkat › pyKey
GitHub - gauthsvenkat/pyKey: A python library to simulate keyboard presses · GitHub
December 27, 2023 - A python wrapper for SendInput function (on windows) and xdotool (on linux) to synthesize keystrokes.
Starred by 56 users
Forked by 6 users
Languages   Python
Find elsewhere
🌐
The Python Code
thepythoncode.com › article › control-keyboard-python
Keyboard module: Controlling your Keyboard in Python - The Python Code
Controlling computer mouse in python. Hooking events, registering hotkeys, simulating mouse movements and click, and much more. Creating and implementing a keylogger from scratch that records key strokes from keyboard and send them to email or save them as log files using Python and keyboard ...
🌐
GitHub
github.com › autokey › autokey › issues › 92
keyboard.send_keys(output) adds an unwanted enter (with Python 3) · Issue #92 · autokey/autokey
July 22, 2017 - commandstr="date "+%Y-%m-%d" --date="next sun"" output = system.exec_command(commandstr) keyboard.send_keys(output) But since i've upgraded from Autokey to Autokey with Python 3*, keyboard.send_keys(output) also gives an enter. I've also scripts where the (output) is in the middle of a script, ...
Published   Jul 22, 2017
🌐
Delft Stack
delftstack.com › home › howto › python › python simulate keyboard input
How to Simulate Keyboard Inputs in Python | Delft Stack
February 2, 2024 - We will talk about two open-source Python libraries, keyboard and PyAutoGUI, letting us control our keyboard using Python scripts. The keyboard library is an open-source library to take control of your keyboard. This library can listen to and send keyboard events, use hotkeys, support internationalization, and provide mouse support with the help of the mouse library, which we can download using pip install mouse or pip3 install mouse.
🌐
Playwright
playwright.dev › keyboard
Keyboard | Playwright Python
Modifier keys DO NOT effect keyboard.type. Holding down Shift will not type the text in upper case. ... For characters that are not on a US keyboard, only an input event will be sent.
🌐
Stack Overflow
stackoverflow.com › questions › 48852259 › set-the-cursor-inside-the-function-keyboard-send-keys
python - set the cursor inside the function "keyboard.send_keys" - Stack Overflow
February 18, 2018 - import time t = time.strftime("%d.%m.%Y") length = "-.pdf" keyboard.send_keys(t+length) keyboard.send_key("<left>", len(length)-1)
🌐
Read the Docs
pynput.readthedocs.io › en › latest › keyboard.html
Handling the keyboard — pynput 1.7.6 documentation
To register a number of global ... '<ctrl>+<alt>+h': on_activate_h, '<ctrl>+<alt>+i': on_activate_i}) as h: h.join() ... A controller for sending virtual keyboard events to the system....
🌐
Python Forum
python-forum.io › thread-16881.html
Send Key press for a game?
I'm just trying to send simple key commands to a video game. I've tried a few different pypi options and pywin32 to send keystrokes. pynput send mouseclicks but not keystrokes. Though all of these will send to something like notepad, keystrokes aren'...
🌐
Stack Abuse
stackabuse.com › guide-to-pythons-keyboard-module
Guide to Python's keyboard Module
October 24, 2023 - Whether it's repeatable (ethical) ... sending mundane e-mails, Python has a lot of modules that make your life easier. One of these is a module called keyboard, and it takes full control of your keyboard. With this module, you can type out anything, create hot-keys, create ...
🌐
Google Groups
groups.google.com › g › autokey-users › c › Y-bFYy8FB_I
how to keyboard.send_keys((the contents of a string))
On Jun 24, 8:16 am, Christiaan Dekter <cdek...@gmail.com> wrote: > To get you out of trouble quickly: > > keyboard.send_keys(finalitem + "<enter>") > > A script in AutoKey is a Python script - the two are equivalent. So anything > you could do in a separate Python script, you can do within an AutoKey > script.
🌐
Python
python-list.python.narkive.com › AtcTVILZ › sending-keystrokes-to-windows-exe-programs
Sending keystrokes to Windows exe programs
To send keys to a GUI Window, you can use win32com (from the pywin32 extensions) to execute WScript commands: import time import win32com import win32com.client shell = win32com.client.Dispatch('WScript.Shell') shell.Run('notepad') time.sleep(0.1) shell.AppActivate('notepad') shell.SendKeys("Hello World", 0) shell.SendKeys("{Enter}", 0) shell.SendKeys("{F5}", 0) # F5 prints the time/date Documentation for SendKeys: http://msdn.microsoft.com/en-us/library/8c6yea83 SendKeys only sends to the active Window.