Locating elements is the first step in every Selenium test. Without it, actions like click or sendKeys cannot be executed. Selenium provides two methods for this: findElement, which returns a single matching element, and findElements, which returns a list of all matches. They may look similar but differ in behavior when no element is found.
findElement throws a NoSuchElementException, while findElements simply returns an empty list. A wrong choice can cause tests to fail unexpectedly or silently skip validations.
This article explains the difference between findElement and findElements in Selenium with syntax, usage, and examples.
findElement is the Selenium WebDriver command used to locate and return the first matching element on a webpage. It works with any supported locator strategy such as ID, Name, CSS Selector, XPath, or LinkText. Once the element is found, WebDriver allows you to perform actions on it like clicking, entering text, or retrieving its attributes.
If the specified locator does not match any element in the DOM, findElement throws a NoSuchElementException. This makes it useful when you need to validate the mandatory presence of an element before continuing with the test.
The findElement command requires a By locator as input and returns the first matching element. The general syntax is:
WebElement element = driver.findElement(By.locator("value"));
Where:
Example in Java:
WebElement loginButton = driver.findElement(By.id("loginBtn"));
loginButton.click();
This finds the element with ID loginBtn and performs a click action on it. If no such element exists, Selenium throws a NoSuchElementException.
findElements is the Selenium WebDriver command used to locate and return all elements that match a given locator. Unlike findElement, which stops after finding the first match, findElements collects every matching element and stores them in a list.
If no element matches the locator, findElements does not throw an exception. Instead, it returns an empty list. This behavior makes it safer when checking for optional or dynamic elements, because tests can continue even if nothing is found. You can then use list operations like size() to verify presence or loop through the returned elements to perform actions on each.
The findElements command requires a By locator and returns a list of all matching elements. The general syntax is:
List<WebElement> elements = driver.findElements(By.locator("value"));
Where:
Example in Java:
List<WebElement> links = driver.findElements(By.tagName("a"));
System.out.println("Number of links: " + links.size());
This finds all anchor tags on the page and prints the total count. If there are no links, Selenium simply returns an empty list.
Although both commands are used for locating elements, their behavior is different in several important ways.
Here’s a table that highlights the differences between findElement and findElements
The findElement method always works in combination with a locator. Selenium supports several locator strategies, each suited to different scenarios. Choosing the right one is what makes tests stable and maintainable.
Here are the main strategies, explained in detail with examples:
The id attribute is the most reliable and fastest way to locate elements, because IDs are expected to be unique within the HTML DOM. When available, this should be the first choice.
WebElement loginButton = driver.findElement(By.id("loginBtn"));
loginButton.click();
If IDs are dynamically generated or change frequently, tests may break. In such cases, fall back to CSS or XPath.
The name attribute is useful when IDs are not available. Unlike IDs, names are not guaranteed to be unique, so if multiple elements share the same name, Selenium interacts with the first one found.
WebElement emailField = driver.findElement(By.name("email"));
emailField.sendKeys("user@test.com");
This works well for forms where fields like “username” or “password” are named consistently.
The By.linkText locator is used specifically for <a> tags. Selenium matches the visible text of the link exactly.
WebElement forgotPwd = driver.findElement(By.linkText("Forgot Password?"));
forgotPwd.click();
This is simple and readable but can be brittle if link text changes often. Use partial link text or CSS/XPath if stability is a concern.
CSS selectors allow precise targeting of elements by attributes, classes, or hierarchical relationships. They are faster than XPath and widely used when IDs and names are not reliable.
WebElement submitBtn = driver.findElement(By.cssSelector("button[type='submit']"));
submitBtn.click();
Complex UI structures often require CSS selectors for flexibility, but long selectors should be avoided as they reduce readability.
XPath is the most flexible strategy and can locate elements based on hierarchy, attributes, or text content. It is especially useful for dynamic elements where other attributes are missing or inconsistent.
WebElement profileLink = driver.findElement(By.xpath("//a[contains(text(),'Profile')]"));
profileLink.click();
XPath expressions can handle complex DOM structures, but they are slower and harder to maintain compared to CSS selectors.
Selenium commands behave differently across browsers and devices because the underlying DOM, CSS handling, and rendering can change. For example, an element located by CSS in Chrome might not appear in Safari due to differences in how styles are applied. On mobile, the same element might be hidden behind a collapsed menu, making it unavailable to findElement.
Local desktop testing cannot uncover these issues. Running tests on real devices verifies that locators work under the same conditions end users face. It also exposes problems like overlapping elements, responsive design shifts, or different attribute values that only appear on specific devices or browser versions
Cloud testing platforms like BrowserStack provide instant access to hundreds of browsers and real devices without local setup. With Selenium Grid integration, you can run tests in parallel across multiple environments, capture screenshots, and debug failures using detailed logs.
This saves time and ensures that your locators and commands are not only syntactically correct but also practical in real-user scenarios.
Use findElement when you need to interact with a single element, such as a login button or search field. Use findElements when multiple matches are expected, like dropdown options, table rows, or page links. Always combine them with the most stable locator available, usually an ID or Name. For complex or dynamic layouts, fall back on CSS or XPath.
1. What happens if Selenium cannot find an element?
If findElement cannot locate the element, it throws a NoSuchElementException. If findElements cannot find any matches, it returns an empty list without failing the test.
2. What is the return type of findElement and findElements?
findElement returns a single WebElement. findElements returns a List<WebElement> that can contain multiple elements or be empty.
3. How do you deal with dynamic or changing elements in Selenium?
Use explicit waits like WebDriverWait with conditions to allow elements to load. For changing attributes, rely on relative XPath or stable CSS selectors instead of dynamic IDs.
4. Can Selenium interact with hidden elements on a webpage?
No. Selenium only interacts with elements that are visible and enabled. To handle hidden elements, trigger the action that makes them visible, such as clicking a menu or scrolling.
5. Why does findElements return an empty list sometimes?
It happens when the locator does not match any element at that point in time. This could be due to incorrect locators, timing issues, or elements being hidden. Adding waits or validating locator correctness usually resolves it.
Run Selenium Tests on Cloud
Get visual proof, steps to reproduce and technical logs with one click
Continue reading
Try Bird on your next bug - you’ll love it
“Game changer”
Julie, Head of QA
Try Bird later, from your desktop