Playwright’s keyboard API lets you simulate user input with a surprising amount of fidelity, going far beyond simple type() calls.

Let’s see Playwright’s keyboard in action. Imagine you’re testing a rich text editor where users can bold text using Ctrl+B (or Cmd+B on macOS).

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("your_rich_text_editor_url") # Replace with your actual URL

    # Focus on the editor
    editor_locator = page.locator(".rich-text-editor") # Example locator
    editor_locator.click()

    # Type some text
    editor_locator.type("This text will be bolded.")

    # Select the text
    editor_locator.press("Home")
    editor_locator.press("Shift+End") # Select the entire line

    # Simulate Ctrl+B (or Cmd+B)
    # Playwright automatically handles Cmd on macOS
    page.keyboard.press("Control+b")

    # Verify the text is bolded (you'd add assertions here)
    # For example, check for a <strong> tag or a CSS style

    browser.close()

This example demonstrates selecting text and then applying a keyboard shortcut. The keyboard.press() method is your primary tool for simulating individual key presses or combinations. It accepts a string representing the key, including special keys like Control, Shift, Alt, Meta (for Cmd on macOS), and function keys. You can combine modifiers with regular keys, like Control+c for copy, or Shift+ArrowRight for character-by-character selection.

Beyond press(), there’s keyboard.down() and keyboard.up() for holding down keys, which is crucial for more complex sequences. For instance, if you needed to simulate dragging and dropping by holding Shift while moving the mouse, you’d use keyboard.down('Shift') before your mouse movements and keyboard.up('Shift') afterward.

The keyboard.insert_text() method is a more direct way to input strings, and it handles character encoding and input methods more intelligently than repeated press() calls for individual characters. It’s generally preferred for typing longer pieces of text.

The real power comes from combining these with Playwright’s locator strategies. You can click an element to focus it, then use keyboard.press() to navigate within it, or apply shortcuts. For testing accessibility, you’d extensively use arrow keys, Tab, Enter, and Space to ensure keyboard-only users can interact with your application.

Consider a dropdown menu. A typical user might Tab to focus the input, press Enter to open it, use ArrowDown to navigate options, and Enter again to select. Playwright can precisely replicate this flow.

# Example: Testing a select element
page.goto("your_form_url")
select_locator = page.locator("#my-select")

# Focus the select element
select_locator.focus()

# Open the dropdown (simulating Enter press)
page.keyboard.press("Enter")

# Navigate to the third option
page.keyboard.press("ArrowDown")
page.keyboard.press("ArrowDown")

# Select the option (simulating Enter press)
page.keyboard.press("Enter")

# Verify the selected option

The page.keyboard.send_characters(text) method is another way to input text. It’s similar to insert_text but is designed to simulate typing character by character, respecting keyboard layouts and input methods. This can be useful for testing how your application handles rapid typing or specific character sequences.

When simulating shortcuts, Playwright intelligently maps Meta to Cmd on macOS and Control on other platforms, simplifying cross-platform testing. For example, page.keyboard.press('Meta+s') will correctly trigger Cmd+s on a Mac and Ctrl+s on Windows or Linux.

The keyboard object is a global object associated with the page. You access it via page.keyboard. This means all keyboard events are dispatched to the currently focused element on that page. If you need to ensure a specific element receives the input, you should focus it first using locator.focus() or locator.click().

One subtle but important point is how Playwright handles key events. When you use press(), it simulates both the keydown and keyup events for that key. For modifier keys like Control or Shift, if you just press('Control'), it sends both keydown and keyup. If you need to hold a modifier down while pressing another key, you must use down() and up() explicitly. For example, to simulate Ctrl+A (select all), you’d do page.keyboard.press('Control+a'). But if you wanted to select text and then copy it, you’d do:

# Select all text
page.keyboard.press("Control+a")
# Now, with Control still conceptually "held" for the copy action
# Playwright's press('Control+c') handles this internally by ensuring
# the Control key is down when 'c' is pressed.
# If you were doing more complex sequences, you might need:
# page.keyboard.down('Control')
# page.keyboard.press('c')
# page.keyboard.up('Control')

Playwright’s keyboard.press() is smart enough to manage modifier states for common shortcuts like Control+c or Shift+Arrow. It ensures the modifier key is held down for the duration of the shortcut press.

The next hurdle you’ll likely face is testing drag-and-drop operations, which heavily rely on precise mouse and keyboard interactions.

Want structured learning?

Take the full Playwright course →