ScreenshotNeo

BlogHow-to

How to Handle Keyboard Actions in Selenium WebDriver

Learn when to use Selenium’s send_keys and Actions APIs, with runnable examples for text, special keys, held modifiers, shortcuts, and troubleshooting.

By the ScreenshotNeo team4 October 20268 min read

Use an element’s send_keys method to type ordinary text into an editable, keyboard-interactable field. Use Selenium’s Actions API when you need to keep a modifier held across multiple actions, target the active element, or combine keyboard input with other actions. Call perform() to run a built Actions sequence.

This guide shows the pattern in Python, Java, and JavaScript, explains special keys and platform shortcuts, and covers focus, interactability, and common failures. Selenium’s official references are the Keyboard actions, Actions API, and element interactions documentation.

1. Choose the right keyboard API

Need Use Target
Type text into a known input or editable element Element send_keys The element you located
Send keys to the focused element or include typing in a sequence Actions sendKeys Active element, or a designated element where the binding supports it
Hold Shift, Control, or another modifier across actions Actions keyDown / keyUp Active input source, optionally coordinated with other actions

Selenium describes keyboard input in terms of pressing a key down and releasing a pressed key. Actions sendKeys is convenient for text and ordinary key input; each key is pressed and released. A modifier that must remain down needs its own keyDown followed later by keyUp.

2. Type text into an element

Locate the field, ensure it is ready for input, and call send_keys. The following Python example is runnable with Selenium installed and a compatible ChromeDriver available to Selenium. Replace the example URL and locator with the page under test.

from selenium import webdriver
from selenium.webdriver.common.by import By

 driver = webdriver.Chrome()
try:
    driver.get("https://example.com/form")
    field = driver.find_element(By.NAME, "email")
    field.clear()
    field.send_keys("developer@example.com")
    print(field.get_attribute("value"))
finally:
    driver.quit()

Remove the accidental leading space before driver = if copying the snippet into a file; the complete correctly indented version is:

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
try:
    driver.get("https://example.com/form")
    field = driver.find_element(By.NAME, "email")
    field.clear()
    field.send_keys("developer@example.com")
    print(field.get_attribute("value"))
finally:
    driver.quit()

Typical targets include text inputs and elements with contenteditable. A button, hidden input, disabled field, or other non-keyboard-interactable element may reject input. For a contenteditable region, locate the editable node itself, rather than a decorative wrapper.

3. Press special keys

Use the key constants in your language binding for non-text keys. For example, Python uses Keys.ENTER, Keys.TAB, Keys.ESCAPE, Keys.ARROW_DOWN, Keys.SHIFT, and Keys.CONTROL. A field can receive text and a special key in one call:

from selenium.webdriver.common.keys import Keys

search = driver.find_element(By.NAME, "q")
search.send_keys("selenium keyboard actions", Keys.ENTER)

For a sequence on the active element, Python Actions syntax looks like this:

from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys

ActionChains(driver).send_keys("hello", Keys.TAB, "next field").perform()

Make focus intentional: click or otherwise focus the intended field before using an Actions sequence that sends keys to the active element. Selenium also documents Actions key input directed to a designated element; use the overload provided by your language binding if that makes the target clearer.

4. Hold a modifier across actions

To capitalize only one character using a held Shift, press Shift down, type the character, release Shift, and then type the next character:

from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys

ActionChains(driver) \
    .key_down(Keys.SHIFT) \
    .send_keys("a") \
    .key_up(Keys.SHIFT) \
    .send_keys("b") \
    .perform()

The result in a focused text field is Ab. Do not assume that passing SHIFT and a letter together to send_keys keeps Shift held: Selenium’s JavaScript Actions reference explains that each key gets its own down/up pair. Use explicit key-down and key-up calls when the held state matters.

5. Use keyboard shortcuts

Choose the modifier for the operating system used by the browser session: Selenium’s example uses Command on macOS and Control on other platforms. The browser and test environment still determine the exact behavior, so keep shortcut tests aligned with the platform where they run.

Python example to select all text and replace it:

import platform
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys

modifier = Keys.COMMAND if platform.system() == "Darwin" else Keys.CONTROL
field = driver.find_element(By.NAME, "q")
field.click()
ActionChains(driver) \
    .key_down(modifier) \
    .send_keys("a") \
    .key_up(modifier) \
    .send_keys("replacement text") \
    .perform()

For copy/paste or selection across several controls, verify focus first and make each state transition explicit. An Actions chain can also combine navigation, Shift selection, and a platform modifier; keep the chain small enough that a failure identifies which step did not behave as expected.

6. Runnable examples in Java and JavaScript

Java

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.WebElement;

public class KeyboardActions {
    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();
        try {
            driver.get("https://example.com/form");
            WebElement field = driver.findElement(By.name("email"));
            field.clear();
            field.sendKeys("developer@example.com");

            new Actions(driver)
                .keyDown(Keys.SHIFT)
                .sendKeys("a")
                .keyUp(Keys.SHIFT)
                .sendKeys("b")
                .perform();
        } finally {
            driver.quit();
        }
    }
}

The second sequence targets the active element, so focus it before running that sequence in a real test.

JavaScript

const { Builder, By, Key } = require('selenium-webdriver');

(async function keyboardActions() {
  const driver = await new Builder().forBrowser('chrome').build();
  try {
    await driver.get('https://example.com/form');
    const field = await driver.findElement(By.name('email'));
    await field.clear();
    await field.sendKeys('developer@example.com');

    await field.click();
    await driver.actions()
      .keyDown(Key.SHIFT)
      .sendKeys('a')
      .keyUp(Key.SHIFT)
      .sendKeys('b')
      .perform();
  } finally {
    await driver.quit();
  }
})();

Bindings vary in method casing and key-constant names. Python commonly uses ActionChains.key_down; Java uses Actions.keyDown; JavaScript uses driver.actions().keyDown and Key. Consult the official reference for the binding and Selenium version used by your project.

7. Special keys and interaction details

  • Enter: can submit a form or activate a focused control; assert the resulting page state rather than assuming submission succeeded.
  • Tab: moves focus according to the page’s focus order; inspect the next active element if focus matters.
  • Arrow keys: act on the focused widget, such as a select-like control or custom keyboard interface; the same key may scroll the page when focus is elsewhere.
  • Escape: may dismiss a dialog or menu only if that component handles it.
  • Modifier keys: use explicit down/up boundaries when the modifier spans multiple input events, and always release it in the chain.

Use constants such as Keys or Key for special keys rather than typing a key’s display name as text. Ordinary Unicode text can be passed as a string, subject to the target control and browser input behavior.

8. Troubleshooting

Symptom Likely cause Fix
Invalid element state or element is not interactable The target cannot receive keyboard input in its current state; it may be hidden, disabled, or not an editable control. Wait for the page state you need, locate the actual input or contenteditable node, and confirm it is enabled and visible before sending keys.
Text appears in the wrong field or nowhere The expected element is not focused, or an Actions call is using the active element. Click/focus the intended target, or use the element’s send_keys method / designated-element Actions overload.
Shifted letter is lowercase sendKeys(SHIFT, "a") released Shift before the letter, or the target did not receive the sequence. Use keyDown(SHIFT), send the letter, then keyUp(SHIFT); verify focus and resulting value.
Control shortcut behaves differently on a Mac The shortcut modifier is platform-specific. Use Command for macOS and Control elsewhere, and run the test in the browser environment it is meant to cover.
Enter did not submit The focused control or page does not bind Enter to submit, or focus was elsewhere. Confirm focus and the form’s expected behavior; assert navigation or a success state after pressing Enter.
Actions chain has no effect The chain was built but not executed, or its active target was not ready. Call perform(), establish the target state first, and split a long chain to isolate the failing action.
Keys continue affecting later input A modifier was pressed down without a matching release. Pair every keyDown with keyUp in the sequence and keep modifier scope as short as possible.

9. Reliability, speed, and cost

Keyboard actions are generally a small part of browser test runtime; reliability depends more on targeting the correct interactive element, establishing focus, and waiting for the page to reach the required state. Prefer the direct element method for simple typing because the intended recipient is explicit. Use an Actions sequence for the input behavior that requires it, and assert the resulting value, focus, or page state.

Keep waits tied to a meaningful condition such as the field being present and enabled instead of adding arbitrary delays. Clear a field when the test expects replacement rather than appending. Release modifiers explicitly, and avoid platform-specific shortcuts in tests that need to run unchanged across operating systems.

Selenium’s keyboard actions do not carry a per-key service charge; any cost comes from the browser, driver, and compute environment you use. This topic does not require a keyboard hardware purchase.

10. Or skip the browser setup

If your task is to inspect a rendered page rather than exercise its keyboard behavior, ScreenshotNeo can return a screenshot or PDF with one GET request. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Learn more at ScreenshotNeo.

Sign up for 1,000 free screenshots a month, with no card required.

11. Frequently asked questions

How do I press keyboard keys in Selenium?

Call send_keys on a focused, keyboard-interactable element for a straightforward key or text. Use the Actions API for a sequence or held modifier.

How do I use send_keys in Selenium WebDriver?

Find an editable element and call element.send_keys("text") (Python), element.sendKeys("text") (Java), or element.sendKeys("text") (JavaScript). For special keys, pass the binding’s key constant.

Do I need Actions for typing into a text box?

No. Element-level send_keys is the direct choice when the field is known and the task is plain text entry.

Why use keyDown and keyUp separately?

They define how long a modifier remains pressed across other actions. A combined key input may press and release each key individually.

Can Selenium type into a contenteditable element?

Yes, if you locate the editable element and it is keyboard-interactable and in the intended state.