2026, Jan 03 03:00

Speed Up Selenium Bulk Input: Replace send_keys with JavaScript value assignment and an input event

Struggling with Selenium send_keys on large inputs? Avoid timeouts by setting the field via JavaScript and dispatching an input event to boost speed now.

Automating bulk input in a web form with Selenium looks trivial until scale hits. Typing or pasting 3000 comma-separated IDs into a single input field, triggering a download, waiting for about 40 seconds, clearing the field, and repeating—manually this takes a couple of seconds per batch. With Selenium, however, send_keys stalls and eventually times out (e.g., HttpsConnectionPool-style failures after 120 seconds) when the payload grows beyond a few hundred values. Here’s how to reproduce, why it happens, and how to fix it without fighting the browser’s keystroke emulation.

Minimal example that reproduces the issue

The flow logs in, navigates, focuses the input, and tries to insert a large comma-separated string via send_keys. This works for a few dozen or a couple hundred IDs, but becomes painfully slow and times out around 3000.

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
browser = webdriver.Chrome()
browser.get("MY URL")
gate = WebDriverWait(browser, 10)
try:
    dismiss_btn = gate.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.toast-close-button")))
    dismiss_btn.click()
    print("Popup Closed")
except Exception as err:
    print("No Popup appeared. or popup closed")
    print("Error:", err)
try:
    user_box = gate.until(EC.presence_of_element_located((By.ID, "username")))
    user_box.send_keys("email_id@something.com")
    print("UserName Entered")
except Exception as err:
    print("Failed to enter Username")
    print("Error:", err)
try:
    pass_box = gate.until(EC.presence_of_element_located((By.ID, "password")))
    pass_box.send_keys("some_password")
    print("Password Entered")
except Exception as err:
    print("Failed to enter Password")
    print("Error:", err)
try:
    login_btn = gate.until(EC.element_to_be_clickable((By.ID, "loginSubmit")))
    login_btn.click()
    print("Submit Button Clicked")
except Exception as err:
    print("Failed to click submit button")
    print("Error:", err)
ids_selector = WebDriverWait(browser, 10).until(
    EC.element_to_be_clickable((By.XPATH, '//*[@id="root"]/div/div/div[2]/div[2]/div[2]/div/div/div[1]/div/div/div/div/div[1]/div'))
)
ids_selector.click()
chosen_opt = WebDriverWait(browser, 10).until(
    EC.element_to_be_clickable((By.XPATH, '//div[text()="Option for Id selected"]'))
)
chosen_opt.click()
paste_target = WebDriverWait(browser, 10).until(
    EC.element_to_be_clickable((By.XPATH, '//*[@id="root"]/div/div/div[2]/div[2]/div[2]/div/div/div[2]/div/div[1]/div/div/div[1]/div[1]'))
)
paste_target.click()
active_field = WebDriverWait(browser, 10).until(
    lambda b: b.execute_script("return document.activeElement")
)
from selenium.webdriver.common.keys import Keys
# ids_blob is a long comma-separated string, e.g., "1,2,3,..."
active_field.send_keys(ids_blob)
active_field.send_keys(Keys.ENTER)

Why this happens

The bottleneck isn’t your network; it’s the way send_keys works and how the page reacts. Simulating thousands of keystrokes is inherently slow. The browser can lag when flooded with text events, and the field may run revalidation or change handlers on every keystroke. That can fan out to XHR/fetch calls per change, which is fine for small inputs but becomes a problem when the UI churns on every character during a large paste. Once the main thread is saturated, you hit timeouts even though the manual paste takes only a couple of seconds.

The fix: set value via JavaScript and trigger an input event

Bypass keystroke simulation entirely. Inject the full value into the input with execute_script, then dispatch a synthetic input event so the app logic that listens to input changes still runs. This preserves the behavior the UI expects without paying the cost of thousands of send_keys calls.

# Replace the slow send_keys section with JavaScript injection
# active_field is the focused input element
# ids_blob is your comma-separated string of ~3000 IDs
browser.execute_script("arguments[0].value = arguments[1];", active_field, ids_blob)
# If the app relies on input events (e.g., to enable buttons or validate), fire one
browser.execute_script("""
var el = arguments[0];
var prev = el.value;
el.value = arguments[1];
var evt = new Event('input', { bubbles: true });
evt.simulated = true;
el._valueTracker && el._valueTracker.setValue(prev);
el.dispatchEvent(evt);
""", active_field, ids_blob)
# Then proceed with the action that starts the download (e.g., click the download control)
# download_btn.click()

Why this matters

Large payloads through send_keys don’t scale. Switching to JavaScript value assignment avoids UI thread thrash from thousands of key events and prevents 120-second timeouts that appear only at scale. Manually dispatching an input event keeps downstream UI logic intact, so validations, button states, and any data binding continue to work as if a user pasted the text.

Conclusion

For high-volume text input in Selenium, don’t fight keystrokes. Set the field value via JavaScript and emit a single input event, then trigger the intended action. This approach keeps the page responsive, avoids network operations firing on every keypress, and brings input performance back in line with what you see when pasting manually.