Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

If Selenium types into the wrong form field, first prove which element your locator returns and which element has focus immediately before typing. Then wait for the application state you need, reacquire fields replaced by a re-render, restore the intended window or iframe, and clear any stuck keyboard state. A page reaching its normal load state does not mean its JavaScript has stopped changing the DOM.

The practical fix is deterministic targeting plus state-aware synchronization—not adding arbitrary delays. The sections below separate wrong-target, timing, context, and keyboard-layout failures so you can test the right cause.

What “jumping between fields” usually means

The symptom can describe several different failures:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Wrong field receives all text: the selector matches a hidden duplicate, a container, a label, or another editable control.
  • It works sometimes: application JavaScript is still rendering or replacing controls when Selenium types.
  • It fails after navigation, a modal, or an iframe: the driver is in a different window or browsing context, or the original element reference is stale.
  • Characters disappear or change: an Actions sequence left a modifier key pressed, or (with ChromeDriver) the machine’s keyboard layout is not supported.

Selenium’s interaction documentation says send-keys is for text fields and other keyboard-interactable elements; the command does not choose a field for you. Your locator and current browser context determine the target (Selenium: Interacting with web elements).

1. Verify the locator identifies exactly one editable control

Use a field-specific locator

Prefer a stable id, a unique name, or a label relationship over a broad CSS class. Confirm the result is an input, textarea, or intended contenteditable element. A locator that happens to return the first match can silently target a hidden mobile/desktop duplicate.

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

browser = webdriver.Chrome()
browser.get("https://example.com/login")

email_locator = (By.ID, "email")
email_matches = browser.find_elements(*email_locator)
assert len(email_matches) == 1, f"Expected one email field, found {len(email_matches)}"
email = email_matches[0]
assert email.tag_name in ("input", "textarea")
email.send_keys("[email protected]")

During debugging, inspect the matched element’s tag, type, name, id, visibility, and enabled state. Selenium documents unsupported send-keys targets and interaction errors in its element-interaction guidance (official interaction documentation).

Check the active element immediately before typing

Focus is a useful diagnostic, not a substitute for targeting the element explicitly. Execute a small script just before send_keys and print identifying attributes:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
active = browser.execute_script("""
const e = document.activeElement;
return e ? {
  tag: e.tagName,
  id: e.id,
  name: e.getAttribute('name'),
  type: e.getAttribute('type'),
  aria: e.getAttribute('aria-label')
} : null;
""")
print("Active element before typing:", active)

If the active element is a different control, look for code that clicks another field, submits a form, opens a dialog, or moves focus as part of validation. If the active element is correct but text still lands elsewhere, verify that the object receiving send_keys is the same element you inspected and that no re-render occurs between those two lines.

2. Wait for the application state, not merely page load

Navigation’s ready state only describes the document load. Single-page applications and other JavaScript can continue to insert, enable, hide, or replace fields afterward. Selenium calls this race between browser state and command timing “one of the primary causes of flaky tests” (Selenium Waiting Strategies).

Wait for visibility and interactability

Use an explicit wait for the exact control you will use. The following Python example waits for one element to become visible and enabled, then types into that returned element:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(browser, 20)
email = wait.until(EC.element_to_be_clickable((By.ID, "email")))
email.clear()
email.send_keys("[email protected]")

Choose a condition that represents your application’s real readiness: a field becoming clickable, a loading overlay disappearing, a results panel appearing, or a network-driven update completing. Do not replace this with a fixed sleep unless you are deliberately reproducing a timing window; sleeps either waste time on fast runs or remain too short on slow ones.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Wait for a post-update condition when focus changes during validation

If selecting a country causes the form to rebuild its address fields, wait for the new field or a state marker before interacting:

country = wait.until(EC.element_to_be_clickable((By.ID, "country")))
country.send_keys("US")

address = wait.until(EC.element_to_be_clickable((By.ID, "street-address")))
address.send_keys("1 Main Street")

The important point is that the second wait is tied to the update caused by the first action. A successful click does not prove that the next control is already stable.

3. Reacquire elements after a DOM re-render

Modern front ends often replace an input node rather than modifying it in place. Selenium’s error guidance explains that the driver stores an element reference tied to a particular DOM location; when JavaScript removes and recreates that node, the old reference is no longer valid (Understanding Common Errors; Python exception reference).

Locate again after the update

Keep the locator, not a long-lived element object, as your source of truth:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from selenium.common.exceptions import StaleElementReferenceException

field_locator = (By.CSS_SELECTOR, "input[name='phone']")
for attempt in range(3):
    try:
        field = wait.until(EC.element_to_be_clickable(field_locator))
        field.clear()
        field.send_keys("+1 212 555 0100")
        break
    except StaleElementReferenceException:
        if attempt == 2:
            raise
        # The framework replaced the node; the next loop locates the replacement.

Do not blindly retry every Selenium exception. A stale reference indicates replacement; an incorrect locator, a different frame, or a disabled control needs a different fix. Reacquiring in the wrong browsing context will still fail.

4. Restore the correct window and iframe

Window or tab switches

After a link opens a new tab, Selenium remains associated with the window you selected. Save the original handle and explicitly switch to the intended one before locating the field:

original = browser.current_window_handle
handles_before = set(browser.window_handles)
# perform the action that may open a tab
browser.find_element(By.ID, "open-form").click()

wait.until(lambda d: len(d.window_handles) > len(handles_before))
new_handle = next(h for h in d.window_handles if h not in handles_before)
browser.switch_to.window(new_handle)

form_field = wait.until(EC.element_to_be_clickable((By.ID, "email")))
form_field.send_keys("[email protected]")
# Return later when the workflow requires it:
browser.switch_to.window(original)

Use the actual driver variable consistently; the corrected version of the selection line is:

new_handle = next(h for h in browser.window_handles if h not in handles_before)

That explicit handle check prevents an accidental switch to an unrelated tab.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Iframe switches

An element inside an iframe cannot be found from the top-level document. Wait for and enter the frame, locate the field there, then return to the parent document when finished:

frame = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "iframe.payment")))
browser.switch_to.frame(frame)
card = wait.until(EC.element_to_be_clickable((By.NAME, "cardnumber")))
card.send_keys("4111111111111111")
browser.switch_to.default_content()

If the frame itself is replaced, locate the iframe again before switching. Selenium’s common-error guidance covers context changes alongside stale references (official troubleshooting page).

5. Reset Actions input state

The Actions API maintains input-device state across commands. A prior key_down without a matching release can make later keystrokes behave as though Shift, Control, Alt, or another modifier is still held (Selenium Actions API).

Release modifiers and build a complete sequence

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

field = wait.until(EC.element_to_be_clickable((By.ID, "search")))
ActionChains(browser) \
    .key_up(Keys.SHIFT) \
    .key_up(Keys.CONTROL) \
    .key_up(Keys.ALT) \
    .click(field) \
    .send_keys("selenium") \
    .perform()

Prefer a self-contained action sequence for each interaction. If a test aborts halfway through an Actions chain, start the next interaction by releasing keys or by creating a fresh, complete chain. This symptom is different from a selector that consistently identifies the wrong field.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

6. Check ChromeDriver keyboard-layout support

When characters are lost or interpreted incorrectly rather than inserted into a different control, inspect the machine’s keyboard configuration. ChromeDriver’s keyboard-support guidance states: “At this time, ChromeDriver only supports systems that have a US keyboard configured” (ChromeDriver keyboard support).

Treat this as an environment check, not the default explanation for focus movement. Record the operating-system keyboard layout and reproduce with a US layout available when diagnosing ChromeDriver-only character problems. A layout mismatch will not explain a locator that targets the wrong element.

Use the symptom to choose the next test

Observed behavior First checks Likely correction
Text always appears in another field Count locator matches; inspect tag, visibility, and active element Make the selector unique and send keys to that element
Failure is intermittent after navigation or clicks Look for asynchronous rendering or overlays Wait for the specific field or application state
Failure starts after a component refresh Look for stale-element errors or replaced nodes Locate the field again after the update
Failure follows a tab or iframe action Print window handles and current frame context Switch to the intended window/frame before locating
Characters are missing or altered Review Actions key-down history and keyboard layout Release modifiers; check for a US layout with ChromeDriver

A minimal, reproducible diagnostic script

Reduce the test to navigation, one state wait, one locator, and one input. Capture browser and driver versions, Selenium binding version, the relevant markup, the locator, and the command immediately before the unexpected change. This isolates whether the defect is targeting, timing, context, or keyboard state.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

browser = webdriver.Chrome()
wait = WebDriverWait(browser, 20)
browser.get("https://example.com/form")

locator = (By.CSS_SELECTOR, "form#signup input[name='email']")
print("matches before wait:", len(browser.find_elements(*locator)))
field = wait.until(EC.element_to_be_clickable(locator))
print("active before click:", browser.execute_script("return document.activeElement && document.activeElement.outerHTML"))
field.click()
field.clear()
field.send_keys("[email protected]")
print("value after typing:", field.get_attribute("value"))

If the match count is greater than one, fix the page selector before investigating timing. If the count is one but the value is empty, inspect re-renders, frame/window context, and Actions state in that order.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting common errors

ElementNotInteractableException

The element may be hidden, disabled, covered, or not a keyboard-interactable target. Wait for clickability, verify the tag and attributes, and remove the duplicate or overlay that your locator selected. Do not “solve” it by sending keys to the body.

StaleElementReferenceException

The DOM node changed after you located it. Reacquire it from the locator after the triggering update, and wait for the replacement to become interactable.

NoSuchFrameException or a field that cannot be found

The field may be inside an iframe, or the iframe was replaced. Locate the frame in the current document, switch into it, then locate the field. Return to the default content before searching elsewhere.

Works locally but fails in CI

Compare browser and driver versions, viewport and keyboard layout, window/frame transitions, and the timing of asynchronous updates. Add diagnostics for match count, active element, current window handle, and the point at which the field becomes clickable rather than increasing global sleeps.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Or skip the browser setup

If your goal is a clean image or PDF of a page—not interactive form testing—ScreenshotNeo provides a single HTTP request. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

See the full parameter list in the ScreenshotNeo documentation. The same endpoint supports full-page lazy-image loading, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, PDF paper and margin controls, custom CSS/JavaScript, pre-capture clicks, selector or network-idle waits, request/resource blocking, headers, cookies, user agents, Authorization, timezone and geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

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)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Every feature is included on every plan: 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to get an API key.

Frequently Asked Questions

Should I keep a WebDriver element object for the whole test?

Keep the locator and reacquire the element after actions that can rebuild the DOM. A long-lived element reference is appropriate only while the same DOM node is guaranteed to remain in place.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What evidence makes a field-jumping bug actionable for a teammate?

Provide the browser and driver versions, Selenium binding, locator, relevant HTML, current window/frame sequence, and the command immediately before the wrong-field event, plus match-count and active-element output.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.