Skip to main content

How to Locate Web Elements with Selenium WebDriver?

How to Locate Web Elements with Selenium WebDriver?

Key takeaways

  • In Selenium 4 you locate an element with driver.findElement(By...), where By offers eight strategies: id, name, class name, tag name, CSS selector, XPath, link text and partial link text.
  • selenium.dev’s order of preference is an id first, then a well-written CSS selector, with XPath for what CSS cannot express.
  • findElement throws NoSuchElementException when nothing matches; findElements returns an empty list.
  • Selenium 4 adds relative locators (above, below, toLeftOf, toRightOf, near) for elements that are easier to describe by position than by attribute.

To locate a web element with Selenium WebDriver, call driver.findElement() with a By locator, for example driver.findElement(By.id("email")). The element comes back as a WebElement you can click, type into or read. This guide covers every By strategy with Java code that compiles against Selenium 4.51.0, which is the current release on Maven Central (October 2026). The old findElementById style helpers from Selenium 2 are gone, so everything below uses By.

What locator strategies does Selenium WebDriver offer?

Selenium finds elements through the By class, which has one factory method for each strategy. selenium.dev lists eight (selenium.dev, October 2026):

StrategyJavaMatches
idBy.id("email")The element’s id attribute
nameBy.name("password")The name attribute
class nameBy.className("field")A single class. Compound class names are not permitted
tag nameBy.tagName("form")The HTML tag
CSS selectorBy.cssSelector("[data-test='submit']")Any CSS selector
XPathBy.xpath("//button[normalize-space()='Cancel']")An XPath expression
link textBy.linkText("Help center")Anchors whose visible text matches exactly
partial link textBy.partialLinkText("Help")Anchors whose visible text contains the value; the first match wins

Which locator should I use first?

Use an id when the element has one that is unique and stable, then a well-written CSS selector, and keep XPath for cases CSS cannot handle. That is the order selenium.dev gives in its encouraged practices: ids are “the preferred method for locating an element on a page”, and when ids are missing “a well-written CSS selector is the preferred method”. It calls XPath as capable as CSS but with syntax that is “complicated and frequently difficult to debug”, says link text strategies only work on links, and calls tag names “a dangerous way to locate elements” because pages repeat the same tag. It also advises keeping locators compact and readable.

A practical rule follows from that. If a locator needs a comment to explain it, it is describing where the element sits today, and the next layout change will break it. Ask the developers for a stable test attribute such as data-test="submit" and select on that.

Start from a page you can see. The examples in this post run against this small form (saved as form.html):

<form id="signup">
  <div><label id="lbl-email" for="email">Email</label>
  <input type="text" id="email" name="email" class="field"></div>
  <div><label for="password">Password</label>
  <input type="password" id="password" name="password" class="field" data-test="password"></div>
  <div><button type="button" id="cancel">Cancel</button>
  <button type="submit" id="submit" data-test="submit">Create account</button></div>
</form>
<a href="#help">Help center</a>
<div id="cave"><span class="gem">one</span><span class="gem">two</span></div>

The Java below creates a headless Chrome. With Selenium 4.6 and later, Selenium Manager finds a matching driver itself, so there is no manual chromedriver download and no System.setProperty line.

ChromeOptions options = new ChromeOptions();
options.addArguments("--headless=new");
WebDriver driver = new ChromeDriver(options);
driver.get("file:///path/to/form.html");

WebElement byId = driver.findElement(By.id("email"));
WebElement byName = driver.findElement(By.name("password"));
WebElement byClass = driver.findElement(By.className("field"));
WebElement byTag = driver.findElement(By.tagName("form"));
WebElement byLink = driver.findElement(By.linkText("Help center"));
WebElement byPartial = driver.findElement(By.partialLinkText("Help"));

By.className("field") matches two inputs, and findElement returns the first one in document order, which here is the email field. When you need all of them, use findElements.

How do you find an element by CSS selector or XPath?

Both take an expression. A CSS selector can use the id, class and attribute syntax you already know from stylesheets, which makes data-test attributes easy to target. XPath can do something CSS cannot, which is match on text content:

// CSS: an attribute selector on a test hook
WebElement submit = driver.findElement(By.cssSelector("[data-test='submit']"));

// CSS: descendants of an id
List<WebElement> gems = driver.findElements(By.cssSelector("#cave .gem"));

// XPath: select a button by its visible text
WebElement cancel = driver.findElement(By.xpath("//button[normalize-space()='Cancel']"));

I ran this against the page above in Chrome with Selenium 4.51.0: the CSS selector returned the “Create account” button, #cave .gem returned 2 elements, and the XPath returned the button with id cancel.

Pick CSS by default and reach for XPath when you must select on text, or climb from a child to a parent. For XPath that contains an apostrophe, see how to find by XPath text that contains a single quote, and for generating an expression from the browser, see how to find the XPath of your Selenium test using Chrome.

What is the difference between findElement and findElements?

findElement returns the first match and throws NoSuchElementException when there is none. findElements returns a list of every match, and an empty list when nothing matches, so it never throws for a missing element.

List<WebElement> inputs = driver.findElements(By.className("field")); // 2 elements
List<WebElement> none = driver.findElements(By.id("nope"));           // empty list, no exception

try {
    driver.findElement(By.id("nope"));
} catch (NoSuchElementException e) {
    // thrown: findElement has nothing to return
}

The empty list makes findElements(...).isEmpty() the clean way to ask “is this element on the page?” without catching an exception. To search inside one element instead of the whole page, call findElement on a WebElement: driver.findElement(By.id("signup")).findElements(By.className("field")) returned the 2 fields in my run. selenium.dev notes that a nested lookup takes two commands, so a single selector such as #signup .field can be more efficient.

What are relative locators in Selenium 4?

Relative locators find an element by where it sits next to another element. They arrived in Selenium 4 (first called friendly locators) and work from each element’s size and position, which Selenium reads with the browser’s getBoundingClientRect() (selenium.dev, October 2026). They help when an element has no good attribute but a neighbour does, such as an input beside a label.

import org.openqa.selenium.support.locators.RelativeLocator;

WebElement email = driver.findElement(
        RelativeLocator.with(By.tagName("input")).above(By.id("password")));
WebElement password = driver.findElement(
        RelativeLocator.with(By.tagName("input")).below(By.id("email")));
WebElement cancel = driver.findElement(
        RelativeLocator.with(By.tagName("button")).toLeftOf(By.id("submit")));
WebElement submit = driver.findElement(
        RelativeLocator.with(By.tagName("button")).toRightOf(By.id("cancel")));
WebElement field = driver.findElement(
        RelativeLocator.with(By.tagName("input")).near(By.id("lbl-email")));

near matches an element at most 50 pixels from the reference. On the form above these returned email, password, cancel, submit and email in that order. Relative locators can be chained, for example .below(By.id("email")).toRightOf(By.id("cancel")). They depend on layout, so use them when position is the stable fact on the page, and check them at the viewport sizes you test.

How do you locate elements that appear later?

An element created by JavaScript may not exist yet when your code looks for it, and findElement then throws. Wait for it with an explicit wait:

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement result = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("result")));

selenium.dev warns not to mix implicit and explicit waits, because the combination can cause unpredictable wait times. The post on explicit and implicit waits in Selenium with Java goes through both.

How can I test a locator before putting it in code?

Try it in the browser first. In the Chrome DevTools Console, $$("css selector") returns an array of the elements matching a CSS selector, and $x("xpath") returns the nodes matching an XPath expression (developer.chrome.com, October 2026). If the array has one item, the locator is unique. Firebug, which the first version of this post named, is no longer the tool to use for this: the built-in DevTools of Chrome, Firefox, Edge and Safari do the same job.

For more locator performance advice, read speeding up Selenium tests with efficient locators. Once your UI flow is stable, LoadFocus can run cloud load tests against the same site to see how it behaves under traffic.

Frequently Asked Questions

Which locator should I prefer in Selenium?

An id where one exists and is stable, then a well-written CSS selector, which is the order selenium.dev recommends. Add a dedicated test attribute such as data-test if the page has neither.

Is CSS or XPath better in Selenium?

CSS for most cases, because selenium.dev calls a well-written CSS selector the preferred method after ids and describes XPath syntax as difficult to debug. Use XPath when you need to match on text content or move from a child up to its parent.

Why do findElementById and findElementByXPath not compile?

Those helpers were removed in Selenium 4. Use driver.findElement(By.id("x")) or driver.findElement(By.xpath("...")) instead.

What does NoSuchElementException mean?

findElement found no element for your locator at that moment. The locator may be wrong, the element may not have rendered yet, or it may sit inside an iframe. Check the locator in DevTools, and wait for the element if the page builds it with JavaScript.

How do I check whether an element exists without an exception?

Call findElements and test whether the list is empty. driver.findElements(By.id("x")).isEmpty() is true when the element is absent.

How do I find an element by its visible text?

For links, use By.linkText or By.partialLinkText. For other elements, use XPath with the text, such as //button[normalize-space()='Cancel'], since CSS selectors cannot match on text.

Sources

  • Locator strategies, finders and relative locators: selenium.dev/documentation/webdriver/elements/locators, /finders (October 2026)
  • Locator preference: selenium.dev/documentation/test_practices/encouraged/locators (October 2026)
  • Waits: selenium.dev/documentation/webdriver/waits (October 2026)
  • Selenium 4.51.0 current release: repo1.maven.org/maven2/org/seleniumhq/selenium/selenium-java (October 2026)
  • Console utilities $$ and $x: developer.chrome.com/docs/devtools/console/utilities (October 2026)

Chris

Head of Content at LoadFocus

Chris leads content and oversees development across the services this blog covers. The guides and tool comparisons here come out of the same decisions that shape what ships.

Weekly tips right in your inbox.

Don’t miss out on the latest testing tips and tricks, tools and news related to software testing.

Already +20,000 members in the list.

The Load Testing Platform with AI That Explains Your Results

Load test websites and APIs from 25 cloud regions, monitor page speed and uptime, and get AI analysis that explains your results in plain English.

Cloud load testing, website speed and API monitoring in one place.

Hi there! Can I share a cool thing I'm working on with you?

A software testing newsletter that sparks joy.

Our goal is to create helpful content for software developers and testers.

If you're not into it, you can unsubscribe instantly.