Selenium Commands
A working reference for WebDriver across Java, Python, and JavaScript. Selenium's API is intentionally consistent across languages — once you know the surface, switching stacks is mostly syntax.
Setup
Java
pom.xml dependency:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.21.0</version>
</dependency>Driver initialisation (Selenium 4+ — WebDriverManager no longer required for modern versions):
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.edge.EdgeDriver;
WebDriver driver = new ChromeDriver(); // Chrome
// WebDriver driver = new FirefoxDriver(); // Firefox
// WebDriver driver = new EdgeDriver(); // Edge
driver.get("https://example.com");
// ... your test steps
driver.quit();Python
pip install seleniumfrom selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.firefox.service import Service as FirefoxService
driver = webdriver.Chrome() # Chrome
# driver = webdriver.Firefox() # Firefox
# driver = webdriver.Edge() # Edge
driver.get("https://example.com")
# ... your test steps
driver.quit()JavaScript (Node.js)
npm install selenium-webdriverconst { Builder } = require('selenium-webdriver');
const driver = await new Builder().forBrowser('chrome').build();
// .forBrowser('firefox') / .forBrowser('MicrosoftEdge')
await driver.get('https://example.com');
// ... your test steps
await driver.quit();Headless and common options
// Java
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless=new", "--window-size=1280,800", "--disable-gpu");
WebDriver driver = new ChromeDriver(options);# Python
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless=new")
options.add_argument("--window-size=1280,800")
driver = webdriver.Chrome(options=options)Locators
Selenium uses By strategies. Same names across languages.
By.id()
driver.findElement(By.id("submit")).click();from selenium.webdriver.common.by import By
driver.find_element(By.ID, "submit").click()By.name()
driver.findElement(By.name("email")).sendKeys("jane@example.com");driver.find_element(By.NAME, "email").send_keys("jane@example.com")By.className()
driver.findElement(By.className("btn-primary")).click();driver.find_element(By.CLASS_NAME, "btn-primary").click()By.cssSelector()
The most flexible default — matches CSS the rest of the web uses.
driver.findElement(By.cssSelector("[data-testid='login-submit']")).click();
driver.findElement(By.cssSelector("form#signup input[type='email']")).sendKeys("jane@example.com");driver.find_element(By.CSS_SELECTOR, "[data-testid='login-submit']").click()
driver.find_element(By.CSS_SELECTOR, "form#signup input[type='email']").send_keys("jane@example.com")By.xpath()
Reach for XPath when CSS can't express what you need (text matching, axes, parent traversal).
driver.findElement(By.xpath("//button[text()='Submit']")).click();
driver.findElement(By.xpath("//label[text()='Email']/following-sibling::input")).sendKeys("jane@example.com");driver.find_element(By.XPATH, "//button[text()='Submit']").click()
driver.find_element(By.XPATH, "//label[text()='Email']/following-sibling::input").send_keys("jane@example.com")By.linkText() / By.partialLinkText()
driver.findElement(By.linkText("Sign up")).click();
driver.findElement(By.partialLinkText("Forgot")).click();driver.find_element(By.LINK_TEXT, "Sign up").click()
driver.find_element(By.PARTIAL_LINK_TEXT, "Forgot").click()Finding multiple elements
List<WebElement> rows = driver.findElements(By.cssSelector("table tr"));rows = driver.find_elements(By.CSS_SELECTOR, "table tr")Actions
click()
driver.findElement(By.id("submit")).click();driver.find_element(By.ID, "submit").click()sendKeys() (send_keys in Python)
WebElement email = driver.findElement(By.id("email"));
email.sendKeys("jane@example.com");
email.sendKeys(Keys.TAB);
email.sendKeys(Keys.chord(Keys.CONTROL, "a"));from selenium.webdriver.common.keys import Keys
email = driver.find_element(By.ID, "email")
email.send_keys("jane@example.com")
email.send_keys(Keys.TAB)
email.send_keys(Keys.CONTROL, "a")clear()
Empty the field. Note: clear doesn't fire input events on every framework — for React/Vue inputs, fall back to Ctrl+A + Delete.
driver.findElement(By.id("email")).clear();driver.find_element(By.ID, "email").clear()submit()
Submit the form containing the element. Equivalent to pressing Enter on a form input.
driver.findElement(By.id("login-form")).submit();driver.find_element(By.ID, "login-form").submit()Mouse and keyboard via Actions
import org.openqa.selenium.interactions.Actions;
Actions actions = new Actions(driver);
actions
.moveToElement(driver.findElement(By.id("menu")))
.click(driver.findElement(By.id("submenu-item")))
.perform();
// Drag and drop
actions.dragAndDrop(source, target).perform();from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)
actions \
.move_to_element(driver.find_element(By.ID, "menu")) \
.click(driver.find_element(By.ID, "submenu-item")) \
.perform()
actions.drag_and_drop(source, target).perform()Waits
The single biggest source of Selenium flake is missing waits. Use explicit waits — implicit is a footgun.
Implicit wait (avoid mixing with explicit)
Sets a default poll for every findElement call.
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));driver.implicitly_wait(5)Don't combine implicit and explicit waits in the same suite — interactions between them produce unpredictable timeouts.
Explicit wait — WebDriverWait + ExpectedConditions
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement btn = wait.until(
ExpectedConditions.elementToBeClickable(By.id("submit"))
);
btn.click();
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".dashboard")));
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector(".spinner")));
wait.until(ExpectedConditions.urlContains("/dashboard"));
wait.until(ExpectedConditions.titleIs("Dashboard"));
wait.until(ExpectedConditions.textToBePresentInElementLocated(
By.id("status"), "Ready"
));from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
btn = wait.until(EC.element_to_be_clickable((By.ID, "submit")))
btn.click()
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".dashboard")))
wait.until(EC.invisibility_of_element_located((By.CSS_SELECTOR, ".spinner")))
wait.until(EC.url_contains("/dashboard"))
wait.until(EC.title_is("Dashboard"))
wait.until(EC.text_to_be_present_in_element((By.ID, "status"), "Ready"))Custom condition
wait.until(d -> d.findElements(By.cssSelector(".row")).size() == 5);wait.until(lambda d: len(d.find_elements(By.CSS_SELECTOR, ".row")) == 5)Navigation
get() and navigate()
driver.get("https://example.com/login");
driver.navigate().to("https://example.com/dashboard");
driver.navigate().back();
driver.navigate().forward();
driver.navigate().refresh();
String currentUrl = driver.getCurrentUrl();
String title = driver.getTitle();driver.get("https://example.com/login")
driver.back()
driver.forward()
driver.refresh()
current_url = driver.current_url
title = driver.titleAssertions
Selenium itself doesn't ship assertions — you pair it with TestNG, JUnit, or pytest.
TestNG (Java)
import org.testng.annotations.Test;
import static org.testng.Assert.*;
@Test
public void loginRedirectsToDashboard() {
driver.get("https://example.com/login");
driver.findElement(By.id("email")).sendKeys("jane@example.com");
driver.findElement(By.id("password")).sendKeys("Secret!23");
driver.findElement(By.id("submit")).click();
new WebDriverWait(driver, Duration.ofSeconds(10))
.until(ExpectedConditions.urlContains("/dashboard"));
assertEquals(driver.getCurrentUrl(), "https://example.com/dashboard");
assertTrue(driver.findElement(By.cssSelector("h1")).getText().contains("Welcome"));
}JUnit 5 (Java)
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
@Test
void loginRedirectsToDashboard() {
// ... same body, just different assertion library
assertTrue(driver.getCurrentUrl().contains("/dashboard"));
}pytest (Python)
def test_login_redirects_to_dashboard(driver, wait):
driver.get("https://example.com/login")
driver.find_element(By.ID, "email").send_keys("jane@example.com")
driver.find_element(By.ID, "password").send_keys("Secret!23")
driver.find_element(By.ID, "submit").click()
wait.until(EC.url_contains("/dashboard"))
assert driver.current_url == "https://example.com/dashboard"
assert "Welcome" in driver.find_element(By.CSS_SELECTOR, "h1").textSoft assertions (TestNG)
Collect failures across a test run and report them all at the end.
import org.testng.asserts.SoftAssert;
SoftAssert soft = new SoftAssert();
soft.assertEquals(driver.getTitle(), "Dashboard");
soft.assertTrue(driver.findElement(By.id("user")).isDisplayed());
soft.assertAll(); // call this last — fails the test if any assertion failedWindow handling
Switching between windows / tabs
String original = driver.getWindowHandle();
driver.findElement(By.linkText("Open in new tab")).click();
for (String handle : driver.getWindowHandles()) {
if (!handle.equals(original)) {
driver.switchTo().window(handle);
break;
}
}
// ... interact with the new window
driver.close(); // close current window
driver.switchTo().window(original); // back to originaloriginal = driver.current_window_handle
driver.find_element(By.LINK_TEXT, "Open in new tab").click()
for handle in driver.window_handles:
if handle != original:
driver.switch_to.window(handle)
break
driver.close()
driver.switch_to.window(original)Switching to iframes
driver.switchTo().frame("iframe-name");
driver.switchTo().frame(0); // by index
driver.switchTo().frame(driver.findElement(By.cssSelector("iframe.embed")));
// ... interact inside the frame
driver.switchTo().defaultContent(); // back to top-level page
driver.switchTo().parentFrame(); // up one leveldriver.switch_to.frame("iframe-name")
driver.switch_to.frame(0)
driver.switch_to.frame(driver.find_element(By.CSS_SELECTOR, "iframe.embed"))
driver.switch_to.default_content()
driver.switch_to.parent_frame()Handling alerts
import org.openqa.selenium.Alert;
driver.findElement(By.id("delete")).click();
Alert alert = driver.switchTo().alert();
String text = alert.getText();
alert.accept(); // OK
// alert.dismiss(); // Cancel
// alert.sendKeys("input value"); // for prompt() dialogsdriver.find_element(By.ID, "delete").click()
alert = driver.switch_to.alert
text = alert.text
alert.accept()
# alert.dismiss()
# alert.send_keys("input value")For modern web apps, native alerts are rare — most "alerts" are custom modals. Treat those as regular DOM elements with locators.