Selenium WebDriver core API for automating web browsers across different platforms and programming languages.
—
Interface for executing JavaScript code in the browser context with support for synchronous/asynchronous execution, script pinning, and argument passing.
Interface for executing JavaScript code within the browser context with parameter passing and return value handling.
/**
* JavascriptExecutor interface for executing JavaScript code in browser context
* Provides synchronous and asynchronous script execution with argument passing
*/
interface JavascriptExecutor {
/**
* Execute JavaScript synchronously in browser context
* @param script - JavaScript code to execute
* @param args - Arguments to pass to script (accessible as arguments[0], arguments[1], etc.)
* @return Result of script execution (may be null, primitive, WebElement, or List)
*/
Object executeScript(String script, Object... args);
/**
* Execute JavaScript asynchronously in browser context
* @param script - JavaScript code to execute (must call callback to complete)
* @param args - Arguments to pass to script
* @return Result of script execution
*/
Object executeAsyncScript(String script, Object... args);
/**
* Pin script for reuse with better performance
* @param script - JavaScript code to pin
* @return ScriptKey for referencing pinned script
*/
ScriptKey pin(String script);
/**
* Unpin previously pinned script
* @param key - ScriptKey of script to unpin
*/
void unpin(ScriptKey key);
/**
* Get all currently pinned scripts
* @return Set of ScriptKey objects for pinned scripts
*/
Set<ScriptKey> getPinnedScripts();
/**
* Execute pinned script by key
* @param key - ScriptKey of pinned script
* @param args - Arguments to pass to script
* @return Result of script execution
*/
Object executeScript(ScriptKey key, Object... args);
}Reference key for pinned JavaScript scripts enabling efficient reuse.
/**
* ScriptKey class representing a pinned JavaScript script
* Used for efficient execution of frequently used scripts
*/
class ScriptKey {
/**
* Get script identifier
* @return Unique identifier for the pinned script
*/
String getId();
/**
* Get original script content
* @return JavaScript code that was pinned
*/
String getScript();
}import org.openqa.selenium.WebDriver;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.chrome.ChromeDriver;
WebDriver driver = new ChromeDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;
try {
driver.get("https://example.com");
// Simple script execution
String title = (String) js.executeScript("return document.title;");
System.out.println("Page title: " + title);
// Execute script with return value
Long scrollHeight = (Long) js.executeScript("return document.body.scrollHeight;");
System.out.println("Page height: " + scrollHeight);
// Execute script that modifies the page
js.executeScript("document.body.style.backgroundColor = 'lightblue';");
// Execute script with no return value
js.executeScript("console.log('Hello from WebDriver!');");
} finally {
driver.quit();
}// Pass arguments to JavaScript
WebElement element = driver.findElement(By.id("myElement"));
String elementText = (String) js.executeScript(
"return arguments[0].textContent;",
element
);
// Multiple arguments
js.executeScript(
"arguments[0].style.backgroundColor = arguments[1]; arguments[0].style.color = arguments[2];",
element,
"yellow",
"red"
);
// Pass different types of arguments
js.executeScript(
"var element = arguments[0]; var show = arguments[1]; var delay = arguments[2]; " +
"if (show) { element.style.display = 'block'; } " +
"setTimeout(function() { element.style.opacity = '1'; }, delay);",
element,
true,
1000
);
// Return complex objects
Map<String, Object> elementInfo = (Map<String, Object>) js.executeScript(
"var elem = arguments[0]; " +
"return { " +
" tagName: elem.tagName, " +
" id: elem.id, " +
" className: elem.className, " +
" visible: elem.offsetWidth > 0 && elem.offsetHeight > 0 " +
"};",
element
);// Scroll to element
WebElement targetElement = driver.findElement(By.id("target"));
js.executeScript("arguments[0].scrollIntoView(true);", targetElement);
// Highlight element
js.executeScript(
"arguments[0].style.border = '3px solid red';" +
"arguments[0].style.backgroundColor = 'yellow';",
targetElement
);
// Get element position and size
Map<String, Object> elementBounds = (Map<String, Object>) js.executeScript(
"var rect = arguments[0].getBoundingClientRect(); " +
"return { " +
" x: rect.left, " +
" y: rect.top, " +
" width: rect.width, " +
" height: rect.height " +
"};",
targetElement
);
// Check if element is in viewport
Boolean isInViewport = (Boolean) js.executeScript(
"var rect = arguments[0].getBoundingClientRect(); " +
"return rect.top >= 0 && rect.left >= 0 && " +
"rect.bottom <= window.innerHeight && rect.right <= window.innerWidth;",
targetElement
);
// Find elements by complex criteria
List<WebElement> visibleElements = (List<WebElement>) js.executeScript(
"var elements = document.querySelectorAll(arguments[0]); " +
"var visible = []; " +
"for (var i = 0; i < elements.length; i++) { " +
" if (elements[i].offsetWidth > 0 && elements[i].offsetHeight > 0) { " +
" visible.push(elements[i]); " +
" } " +
"} " +
"return visible;",
".product-card"
);// Set script timeout for async operations
driver.manage().timeouts().setScriptTimeout(Duration.ofSeconds(30));
// Simple async script with callback
String result = (String) js.executeAsyncScript(
"var callback = arguments[arguments.length - 1]; " +
"setTimeout(function() { " +
" callback('Async operation completed'); " +
"}, 2000);"
);
// AJAX request with async script
String responseText = (String) js.executeAsyncScript(
"var callback = arguments[arguments.length - 1]; " +
"var xhr = new XMLHttpRequest(); " +
"xhr.open('GET', arguments[0], true); " +
"xhr.onreadystatechange = function() { " +
" if (xhr.readyState === 4) { " +
" callback(xhr.responseText); " +
" } " +
"}; " +
"xhr.send();",
"https://api.example.com/data"
);
// Wait for page element to load asynchronously
WebElement dynamicElement = (WebElement) js.executeAsyncScript(
"var callback = arguments[arguments.length - 1]; " +
"var checkElement = function() { " +
" var element = document.querySelector(arguments[0]); " +
" if (element) { " +
" callback(element); " +
" } else { " +
" setTimeout(checkElement, 100); " +
" } " +
"}; " +
"checkElement();",
"#dynamic-content"
);// Pin frequently used scripts
ScriptKey scrollScript = js.pin(
"window.scrollTo(0, arguments[0]);"
);
ScriptKey highlightScript = js.pin(
"arguments[0].style.border = '2px solid ' + arguments[1];" +
"arguments[0].style.backgroundColor = arguments[2];"
);
ScriptKey getElementInfoScript = js.pin(
"var elem = arguments[0]; " +
"return { " +
" text: elem.textContent, " +
" visible: elem.offsetWidth > 0 && elem.offsetHeight > 0, " +
" classes: elem.className.split(' '), " +
" attributes: Array.from(elem.attributes).map(attr => ({name: attr.name, value: attr.value})) " +
"};"
);
// Use pinned scripts multiple times
js.executeScript(scrollScript, 500);
js.executeScript(scrollScript, 1000);
WebElement button1 = driver.findElement(By.id("btn1"));
WebElement button2 = driver.findElement(By.id("btn2"));
js.executeScript(highlightScript, button1, "red", "yellow");
js.executeScript(highlightScript, button2, "blue", "lightgreen");
Map<String, Object> info1 = (Map<String, Object>) js.executeScript(getElementInfoScript, button1);
Map<String, Object> info2 = (Map<String, Object>) js.executeScript(getElementInfoScript, button2);
// Clean up pinned scripts when done
js.unpin(scrollScript);
js.unpin(highlightScript);
js.unpin(getElementInfoScript);
// Or get all pinned scripts and unpin them
Set<ScriptKey> pinnedScripts = js.getPinnedScripts();
pinnedScripts.forEach(js::unpin);// Performance metrics
Map<String, Object> performanceData = (Map<String, Object>) js.executeScript(
"var perf = window.performance; " +
"var timing = perf.timing; " +
"return { " +
" loadTime: timing.loadEventEnd - timing.navigationStart, " +
" domContentLoaded: timing.domContentLoadedEventEnd - timing.navigationStart, " +
" firstPaint: perf.getEntriesByType('paint')[0]?.startTime || null, " +
" memoryUsage: perf.memory ? perf.memory.usedJSHeapSize : null " +
"};"
);
// Accessibility checks
List<Map<String, Object>> accessibilityIssues = (List<Map<String, Object>>) js.executeScript(
"var issues = []; " +
"var images = document.querySelectorAll('img'); " +
"images.forEach(function(img, index) { " +
" if (!img.alt) { " +
" issues.push({type: 'missing-alt', element: 'img', index: index}); " +
" } " +
"}); " +
"var links = document.querySelectorAll('a'); " +
"links.forEach(function(link, index) { " +
" if (!link.textContent.trim() && !link.getAttribute('aria-label')) { " +
" issues.push({type: 'empty-link', element: 'a', index: index}); " +
" } " +
"}); " +
"return issues;"
);
// Form validation status
Boolean isFormValid = (Boolean) js.executeScript(
"var form = arguments[0]; " +
"return form.checkValidity();",
driver.findElement(By.id("myForm"))
);
// Get all form errors
List<String> formErrors = (List<String>) js.executeScript(
"var form = arguments[0]; " +
"var errors = []; " +
"var inputs = form.querySelectorAll('input, select, textarea'); " +
"inputs.forEach(function(input) { " +
" if (!input.checkValidity()) { " +
" errors.push(input.name + ': ' + input.validationMessage); " +
" } " +
"}); " +
"return errors;",
driver.findElement(By.id("myForm"))
);// Custom event triggering
js.executeScript(
"var event = new CustomEvent(arguments[1], {detail: arguments[2]}); " +
"arguments[0].dispatchEvent(event);",
targetElement,
"customEvent",
Map.of("data", "test")
);
// Cookie manipulation
js.executeScript("document.cookie = arguments[0] + '=' + arguments[1] + '; path=/';", "testCookie", "testValue");
String cookieValue = (String) js.executeScript(
"return document.cookie.split('; ').find(row => row.startsWith(arguments[0] + '=')).split('=')[1];",
"testCookie"
);
// Local storage operations
js.executeScript("localStorage.setItem(arguments[0], arguments[1]);", "key", "value");
String storedValue = (String) js.executeScript("return localStorage.getItem(arguments[0]);", "key");
// Session storage operations
js.executeScript("sessionStorage.setItem(arguments[0], JSON.stringify(arguments[1]));", "userData", Map.of("name", "John", "age", 30));
Map<String, Object> userData = (Map<String, Object>) js.executeScript(
"return JSON.parse(sessionStorage.getItem(arguments[0]));",
"userData"
);
// Dynamic CSS injection
js.executeScript(
"var style = document.createElement('style'); " +
"style.textContent = arguments[0]; " +
"document.head.appendChild(style);",
".highlight { background-color: yellow; border: 2px solid red; }"
);// Safe script execution with error handling
public Object safeExecuteScript(JavascriptExecutor js, String script, Object... args) {
try {
return js.executeScript(
"try { " +
" return (function() { " + script + " })(); " +
"} catch (e) { " +
" return {error: e.message, stack: e.stack}; " +
"}",
args
);
} catch (Exception e) {
System.err.println("Script execution failed: " + e.getMessage());
return null;
}
}
// Check if result is an error
public boolean isScriptError(Object result) {
if (result instanceof Map) {
Map<String, Object> resultMap = (Map<String, Object>) result;
return resultMap.containsKey("error");
}
return false;
}
// Usage
Object result = safeExecuteScript(js, "return document.querySelector('#nonexistent').textContent;");
if (isScriptError(result)) {
Map<String, Object> error = (Map<String, Object>) result;
System.err.println("JavaScript error: " + error.get("error"));
} else {
System.out.println("Result: " + result);
}
// Timeout handling for async scripts
public Object executeAsyncScriptWithTimeout(JavascriptExecutor js, String script, Duration timeout, Object... args) {
// Set script timeout
driver.manage().timeouts().setScriptTimeout(timeout);
try {
return js.executeAsyncScript(script, args);
} catch (ScriptTimeoutException e) {
System.err.println("Async script timed out after " + timeout.getSeconds() + " seconds");
return null;
} finally {
// Reset to default timeout
driver.manage().timeouts().setScriptTimeout(Duration.ofSeconds(30));
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-seleniumhq-selenium--selenium-api