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

In Selenium Java, cast your WebDriver to JavascriptExecutor, then call executeScript for immediate JavaScript or executeAsyncScript when browser-side work finishes later.

JavascriptExecutor js = (JavascriptExecutor) driver;
Object result = js.executeScript("return document.title;");

Both methods run in the currently selected browser window and frame. Switch to the required context first, pass values through the script arguments, and use normal WebDriver locators and actions whenever they express the user intent more accurately.

Get a JavascriptExecutor instance

JavascriptExecutor is an interface implemented by Selenium drivers. In Java, obtain it with a cast:

JavascriptExecutor js = (JavascriptExecutor) driver;

You can then execute JavaScript in the active browsing context:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Object title = js.executeScript("return document.title;");
System.out.println(title);

A JavaScript return value is converted to a Selenium Java value. Depending on what the script returns, the result can be null, Boolean, a numeric type, String, List, Map, or a WebElement.

Run synchronous JavaScript with executeScript

Use executeScript when the operation completes during the script call. The method returns after the JavaScript finishes, and the value in the JavaScript return statement becomes the method result.

Read browser state

String url = (String) js.executeScript("return window.location.href;");
String title = (String) js.executeScript("return document.title;");

Scroll an element into view

WebElement submit = driver.findElement(By.id("submit"));
js.executeScript("arguments[0].scrollIntoView({block: 'center'});", submit);

Pass a WebElement and a value

Arguments supplied after the script are available through JavaScript’s arguments object. Selenium converts a Java WebElement into the corresponding DOM element.

WebElement input = driver.findElement(By.id("username"));
js.executeScript(
    "arguments[0].value = arguments[1];",
    input,
    "test_user"
);

This sets the DOM property, but it may not fire the keyboard, input, or change events that a front-end framework expects. If the application reacts to user events, prefer input.sendKeys("test_user"), or dispatch the required events and verify the result.

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.

Pass primitive values and collections

Boolean visible = (Boolean) js.executeScript(
    "return arguments[0].getBoundingClientRect().width > 0;",
    input
);

String text = (String) js.executeScript(
    "return arguments[0];",
    "value from Java"
);

Supported arguments include numbers, booleans, strings, WebElement objects, and supported lists. Keep the script small and pass data as arguments rather than concatenating it into JavaScript source.

Run delayed work with executeAsyncScript

Use executeAsyncScript when completion depends on a timer, callback, promise, or another browser-side operation that finishes after the initial JavaScript call. Selenium appends a callback function as the final JavaScript argument. Your script must call that callback exactly when the operation is complete.

driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(10));

Object result = js.executeAsyncScript(
    "var done = arguments[arguments.length - 1];" +
    "window.setTimeout(function() { done('finished'); }, 1000);"
);

System.out.println((String) result);

The callback’s argument becomes the Java result. If the callback is never called, Selenium waits until the configured script timeout and then reports a timeout.

Why an async script hangs

  • The script forgot to retrieve the final argument as its callback.
  • An error path returns without calling the callback.
  • A promise or event listener never settles.
  • The script timeout is shorter than the real browser operation.
  • The code is running in the wrong frame or window and cannot reach the expected page state.

Make every success and failure path complete the callback, and set the timeout before starting the operation:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(15));

Object value = js.executeAsyncScript(
    "var done = arguments[arguments.length - 1];" +
    "fetch('/status')" +
    ".then(function(response) { return response.text(); })" +
    ".then(function(text) { done(text); })" +
    ".catch(function(error) { done('ERROR: ' + error.message); });"
);

Use an appropriate timeout rather than an indefinitely large one; a finite timeout exposes a page or test that failed to complete.

Choose executeScript or executeAsyncScript

Aspect executeScript executeAsyncScript
Completion model Returns when the JavaScript call finishes. Returns only after the injected callback is invoked.
JavaScript completion signal A normal JavaScript return. The final arguments item, used as a callback.
Typical use Read DOM state, return a value, scroll, or make an immediate property change. Wait for a timer, callback, promise, network-related browser operation, or other delayed work.
Timeout concern Must finish as a synchronous command. Must finish before the configured script timeout.

Work in the correct frame and window

JavaScript executes against Selenium’s currently selected frame or window, not automatically against every document. Select the target window and frame before calling the executor:

driver.switchTo().window(targetWindowHandle);
driver.switchTo().frame(driver.findElement(By.cssSelector("iframe.payment")));

String frameTitle = (String) js.executeScript("return document.title;");

Return to the top-level document when required:

driver.switchTo().defaultContent();

Cross-domain browser policies still apply. JavaScript cannot use the executor to bypass same-origin restrictions or freely inspect another origin’s frame. For unexpected failures involving frames, custom XHR requests, or cross-origin content, inspect the browser console and verify that the selected context is the one containing the target document.

When JavaScript is—and is not—the right tool

Good targeted uses

  • Reading browser state that WebDriver does not expose directly.
  • Scrolling an element or adjusting a narrowly defined DOM property.
  • Coordinating a browser-side asynchronous operation with an explicit callback.
  • Inspecting a value that is present in the page but not convenient to retrieve through a standard WebDriver API.

Prefer WebDriver when it expresses the intent

  • Locate elements with By strategies.
  • Use click, sendKeys, selections, and waits for user-facing interactions.
  • Use Selenium’s condition and timeout mechanisms for UI synchronization.

JavaScript changes the page from inside the browser, but it does not reproduce every event generated by a real user action. A property assignment can leave the application’s internal state unchanged. If you must modify a property, follow it with the events or WebDriver actions the application requires, then assert the visible or functional outcome.

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

Reuse scripts with Selenium’s pinning API

The Java JavascriptExecutor interface also provides pin(String), getPinnedScripts(), and execution using a ScriptKey. Pinning can avoid repeatedly sending a large, reused script to the browser.

ScriptKey key = js.pin("return document.querySelector(arguments[0]).textContent;");
Object text = js.executeScript(key, ".status");

Pinning is useful for a script called many times. For a one-off operation, ordinary executeScript is simpler and easier to read. Keep pinned scripts versioned with the test code and remove or update them when their page assumptions change.

Equivalent method names in other Selenium bindings

Language Synchronous method Asynchronous method
Java JavascriptExecutor.executeScript JavascriptExecutor.executeAsyncScript
Python driver.execute_script driver.execute_async_script
.NET IJavaScriptExecutor.ExecuteScript IJavaScriptExecutor.ExecuteAsyncScript

A practical checklist

  1. Create the executor with (JavascriptExecutor) driver.
  2. Switch to the correct window and frame.
  3. Use executeScript for immediate work and return the needed value.
  4. Use executeAsyncScript for delayed work, taking the final argument as the callback.
  5. Set scriptTimeout before asynchronous execution.
  6. Pass elements and values as arguments instead of building JavaScript with string concatenation.
  7. Prefer normal WebDriver actions when they model the user’s interaction.
  8. After a DOM change, trigger the events the application needs and verify the resulting behavior.

Frequently Asked Questions

What happens if executeAsyncScript never calls its callback?

Selenium waits until the configured script timeout and then raises a script-timeout error. Ensure every success and error path invokes the final callback.

Can JavascriptExecutor bypass same-origin policy?

No. It runs in the selected document and remains subject to browser security and cross-origin restrictions.

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

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.