100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Testing

Finding Elements: findElement vs findElements

How Selenium locates elements in the DOM, the difference between findElement and findElements, and how to choose the right locator strategy.

Element InteractionBeginner9 min readJul 10, 2026
Analogies

findElement vs findElements

Selenium's WebDriver exposes two core lookup methods: findElement(By) returns a single WebElement matching the locator, and throws NoSuchElementException if nothing matches. findElements(By) returns a List<WebElement> and never throws for a missing match — it simply returns an empty list. This distinction matters for control flow: findElement is appropriate when you're certain the element must exist and want a hard failure if it doesn't, while findElements is the safe way to probe for optional or conditional elements without wrapping every call in a try/catch.

🏏

Cricket analogy: Calling findElement is like a captain reviewing a single DRS replay for one delivery — if there's no clear edge, the umpire's decision stands as an error, effectively a NoSuchElementException; findElements is like reviewing the whole innings' shot chart, which just comes back empty if no boundaries were hit, no umpire call needed.

Locator Strategies

The By class offers several strategies: By.id (fastest, ideal when the id is unique and stable), By.name, By.className, By.tagName, By.linkText/partialLinkText for anchor elements, By.cssSelector, and By.xpath. Prefer By.id when available since browsers optimize id lookups natively. By.className and By.tagName tend to match multiple elements, which is exactly why they're commonly paired with findElements rather than findElement, since a class name like 'btn-primary' can appear on dozens of buttons across a page.

🏏

Cricket analogy: Using By.id is like calling a player by their unique jersey number on a scorecard — instant and unambiguous — while By.className is like searching by 'opening batsman', which could match several players like Rohit and Gill at once.

CSS Selectors vs XPath

CSS selectors are generally faster and more readable for straightforward parent-to-child or attribute matching, such as 'div.card > button[type=submit]'. XPath is more powerful for cases CSS can't express: selecting an element by its visible text (//button[text()='Submit']), or navigating upward from a child to a parent or ancestor (//span[@class='price']/ancestor::div[@class='product']). Choose CSS for simple structural lookups and reach for XPath specifically when you need text-based matching or upward/sideways traversal.

🏏

Cricket analogy: CSS selectors are like reading a scorecard top-to-bottom for the fastest lookup, while XPath is like being able to search backward from 'the bowler who took the last wicket' to find which over it happened in — traversing relationships CSS can't express.

java
// findElement throws if missing
WebElement loginBtn = driver.findElement(By.id("login-btn"));
loginBtn.click();

// findElements never throws; check size or isEmpty instead
List<WebElement> errorBanners = driver.findElements(By.cssSelector(".error-banner"));
if (!errorBanners.isEmpty()) {
    System.out.println("Validation error: " + errorBanners.get(0).getText());
}

// XPath: select by visible text, then walk up to the parent card
WebElement addToCartOnCard = driver.findElement(
    By.xpath("//span[text()='Wireless Mouse']/ancestor::div[@class='product-card']//button[@data-action='add-to-cart']")
);

Never wrap findElement() in a try/catch just to test whether an element exists — it's slow (the exception carries a full stack trace) and unclear. Use driver.findElements(locator).isEmpty() instead, which is the idiomatic existence check and doesn't rely on exception handling for normal control flow.

Locator priority for stability, from most to least preferred: unique id > data-testid/data-qa attributes > name > CSS class combinations > link text > absolute XPath. Absolute XPath (starting with /html/body/...) is the most brittle because it breaks the moment the DOM structure shifts even slightly.

  • findElement(By) returns one WebElement or throws NoSuchElementException.
  • findElements(By) returns a List<WebElement>, empty if nothing matches — no exception.
  • Use findElements().isEmpty() as the idiomatic existence check instead of try/catch.
  • By.id is fastest and most reliable when the id is unique and stable across builds.
  • By.className and By.tagName commonly match multiple elements; prefer findElements with them.
  • CSS selectors are faster and more readable for structural matches; XPath is needed for text-based or upward traversal.
  • Absolute XPath is the most brittle locator strategy and should be avoided in favor of relative, attribute-based locators.

Practice what you learned

Was this page helpful?

Topics covered

#Testing#SeleniumStudyNotes#TestingQA#FindingElementsFindElementVsFindElements#Finding#Elements#FindElement#FindElements#StudyNotes#SkillVeris