ScreenshotNeo

BlogHow-to

How to Execute JavaScript in Selenium with Python

Use Selenium’s execute_script to run JavaScript from Python, return values, pass arguments safely, and handle asynchronous work and common errors.

By the ScreenshotNeo team4 October 20266 min read

Use Selenium’s driver.execute_script(script, *args) to run synchronous JavaScript in the browser’s currently selected window or frame. Return a value from the JavaScript with return; Selenium gives that value back to Python. For browser-side work that finishes later, use driver.execute_async_script and call Selenium’s injected completion callback.

1. Set up Selenium and a browser

Install Selenium with pip. Selenium Manager can obtain and configure a compatible browser driver for many standard setups when you create a driver.

python -m pip install selenium

Here is a complete script that opens a page, executes JavaScript to read its title, and closes the browser even if an error occurs:

from selenium import webdriver

with webdriver.Chrome() as driver:
    driver.get("https://example.com")
    title = driver.execute_script("return document.title")
    print(title)

This example assumes Chrome is installed and available to Selenium. For Firefox, use webdriver.Firefox(). See the Selenium documentation for browser setup details. You can also run JavaScript with a remote WebDriver session; the execution call is the same once driver is a configured WebDriver instance.

2. Run synchronous JavaScript and get a result

execute_script runs the supplied JavaScript in the current browsing context. The final expression is not automatically returned: use a JavaScript return statement when you need a result in Python.

from selenium import webdriver

with webdriver.Chrome() as driver:
    driver.get("https://example.com")
    result = driver.execute_script("return document.title")
    print(result)

For example, locate an element with Selenium and pass it to the script to read a property:

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

with webdriver.Chrome() as driver:
    driver.get("https://example.com")
    heading = driver.find_element(By.CSS_SELECTOR, "h1")
    text = driver.execute_script("return arguments[0].innerText", heading)
    print(text)

The WebElement becomes arguments[0] inside the JavaScript. This pattern is documented in Selenium’s WebDriver interactions guide.

3. Pass Python values safely

Pass changing values as arguments rather than interpolating them into the JavaScript source. Selenium maps each argument to arguments[n], avoiding quoting mistakes and keeping data separate from code.

from selenium import webdriver

with webdriver.Chrome() as driver:
    driver.get("https://example.com")
    element_id = "username"
    value = "test_user"
    driver.execute_script(
        "document.getElementById(arguments[0]).value = arguments[1];",
        element_id,
        value,
    )

Arguments can include ordinary values and WebElements. Keep in mind that setting a field’s DOM value directly may not trigger the same events as typing through Selenium’s normal element interaction methods. If the application depends on keyboard or input events, use send_keys or dispatch the events the application expects.

4. Choose synchronous or asynchronous execution

Method Use it when Completion
execute_script The useful result is ready when the snippet finishes. Returns the script’s value immediately.
execute_async_script The result depends on a callback, timer, or other later browser-side operation. Your script must call Selenium’s injected callback.

For asynchronous execution, Selenium appends a callback as the script’s last argument. Call it with the result when the work is done:

from selenium import webdriver

with webdriver.Chrome() as driver:
    driver.set_script_timeout(10)
    driver.get("https://example.com")
    result = driver.execute_async_script("""
        const callback = arguments[arguments.length - 1];
        window.setTimeout(() => callback("done"), 1000);
    """)
    print(result)

set_script_timeout(10) sets the maximum time Selenium waits for an asynchronous script. It is separate from the page-load timeout. If the callback is never called, the async execution reaches the script timeout and raises an error. Call the callback once with the result you want Python to receive.

5. Understand context, results, and limitations

  • Current window and frame: Scripts execute in the selected browsing context. Switch to the intended window or frame before running the script.
  • Cross-origin boundaries: Browser security policies can prevent JavaScript from accessing content across origins, even when Selenium can switch to a frame.
  • Return values: Return a value explicitly. Selenium serializes supported JavaScript values into Python values; browser objects such as DOM nodes are generally best handled as WebElements or converted to simple values in the script.
  • Stale elements: If the page replaces an element after you locate it, passing the old WebElement can fail. Locate it again after the update.
  • Testing behavior: JavaScript can change page state without reproducing normal user interaction. Prefer Selenium’s click, typing, and selection methods when the test should verify user-visible behavior.

The Python WebDriver API documents script arguments, return behavior, and script timeout configuration. The shared WebDriver JavaScript executor documentation also describes execution in the current frame and cross-domain access caveats: Python WebDriver API and JavascriptExecutor API.

6. Troubleshoot common errors

Symptom Likely cause Fix
Python gets None The script has no return statement, or its returned value is undefined. Return the value explicitly, such as return document.title.
Async script times out The callback was not called, or the operation took longer than the script timeout. Ensure every completion path calls the callback and set a timeout appropriate to the operation with set_script_timeout.
JavaScript syntax error The script string has invalid JavaScript, or Python quoting changed the intended source. Check the browser-side syntax and use Python triple-quoted strings for multiline scripts.
Element argument is stale or invalid The page replaced the element, or it was found in a different context. Switch to the correct frame and locate the element again immediately before execution.
Cannot access a frame or document The selected frame/window is wrong or browser same-origin restrictions apply. Switch to the intended context. If access is cross-origin, interact through supported browser context changes rather than reaching across the boundary in page JavaScript.
Script runs but the application does not react Directly changing the DOM may skip events or framework state updates. Use Selenium’s normal interaction methods, or dispatch the specific events required by the application.

When the failure is unclear, reduce the script to a simple expression such as return document.readyState, confirm the selected window and frame, and inspect the browser console for page-side exceptions.

7. Performance, reliability, and cost

Each WebDriver script execution requires a browser-driver command, so combine closely related reads or DOM updates into one script when doing so keeps the test understandable. Avoid repeatedly polling JavaScript in a tight loop; use Selenium waits or a bounded asynchronous operation. Always close the driver, as the context manager does above, to release browser resources.

JavaScript execution itself does not add a separate Selenium API charge. Your costs come from the browser or execution environment you choose, such as local compute or a hosted WebDriver service. Reliability depends on the page being in the right state and the right frame being selected; wait for the relevant page condition before reading or changing the DOM.

8. Or skip the browser setup

If your goal is a page screenshot rather than testing arbitrary browser-side JavaScript, ScreenshotNeo captures a URL through one API request and returns PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation.

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)

Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An 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. Sign up for 1,000 free screenshots a month, with no card required.

9. FAQ

Can I execute JavaScript before the page loads?

You can issue the command, but page elements may not exist yet. Navigate and wait for the needed condition before querying or changing the page.

Does execute_script run JavaScript in Python?

No. Selenium sends the script to the browser, where it executes in the selected window or frame. Python receives the serialized return value.

Should I use execute_script to click a button?

Use Selenium’s normal click method when you want a realistic user interaction. Use JavaScript for cases that specifically require page-side execution or inspection.