How to Use ID Locators in Selenium WebDriver
Find elements by their HTML id in Selenium WebDriver. Learn the Java, Python, JavaScript, and C# syntax, handle duplicate IDs, and troubleshoot common lookup failures.
Use Selenium’s ID locator with the raw value of an element’s id attribute. For example, if the markup is <input id="lname">, Java uses driver.findElement(By.id("lname")) and Python uses driver.find_element(By.ID, "lname"). Do not add # to the value passed to an ID locator; the hash is used with a CSS selector such as #lname.
1. What an ID locator does
An HTML element can have an id attribute, for example <input id="lname">. Selenium’s ID strategy matches the element’s ID attribute to the locator value. Selenium says an ID should generally be unique on a page, but your test should not assume every application has valid, unique markup.
Inspect the rendered DOM to find the actual ID. The value may differ from a label, placeholder, name attribute, or text visible on the page. Pass that exact value to the ID strategy.
2. Complete examples by language
These examples locate an element whose ID is lname. They assume Selenium and a compatible browser setup are already available in your project. The navigation URL is a placeholder: use the page your test is meant to exercise.
Java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class FindById {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("https://example.com/form");
WebElement lastName = driver.findElement(By.id("lname"));
System.out.println(lastName.getAttribute("id"));
} finally {
driver.quit();
}
}
}
findElement returns the first matching element in the current search context. It throws a NoSuchElementException when there is no match.
Python
from selenium import webdriver
from selenium.webdriver.common.by import By
with webdriver.Chrome() as driver:
driver.get("https://example.com/form")
last_name = driver.find_element(By.ID, "lname")
print(last_name.get_attribute("id"))
Python’s locator constant is By.ID. The argument following it is the raw ID value.
JavaScript
const { Builder, By } = require('selenium-webdriver');
(async function findById() {
const driver = await new Builder().forBrowser('chrome').build();
try {
await driver.get('https://example.com/form');
const lastName = await driver.findElement(By.id('lname'));
console.log(await lastName.getAttribute('id'));
} finally {
await driver.quit();
}
})();
The JavaScript binding also exposes By.id. Its API reference describes the ID locator implementation in terms of a CSS selector; treat that as an implementation detail of that binding, not a universal implementation guarantee for every language.
C#
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://example.com/form");
IWebElement lastName = driver.FindElement(By.Id("lname"));
Console.WriteLine(lastName.GetAttribute("id"));
Ruby
require "selenium-webdriver"
driver = Selenium::WebDriver.for :chrome
begin
driver.navigate.to "https://example.com/form"
last_name = driver.find_element(id: "lname")
puts last_name.attribute("id")
ensure
driver.quit
end
cURL, Python requests, and Node fetch for a page screenshot
Selenium locates elements in an interactive browser session. If your goal is to save a page image rather than interact with an element, a screenshot API can capture the page directly. The following runnable request examples use ScreenshotNeo; replace the target URL and supply your API key. See the ScreenshotNeo API documentation for request options.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com/form \
-o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com/form"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com/form'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
3. Find one element or inspect all matches
Choose the singular or plural finder based on what the test needs. Selenium searches within the current search context, which can be the whole driver or a parent element.
| Intent | Java | Python | Result when there are no matches |
|---|---|---|---|
| Find the expected element | findElement(By.id("lname")) |
find_element(By.ID, "lname") |
Throws a no-such-element exception. |
| Get all matches or check whether any exist | findElements(By.id("lname")) |
find_elements(By.ID, "lname") |
Returns an empty collection. |
Use the plural form when the page might contain duplicate IDs and the test needs to detect that condition. For example, a test that requires uniqueness can assert the result count is exactly one before interacting with the element. A singular lookup returns the first match, so it does not prove the ID is unique.
List<WebElement> matches = driver.findElements(By.id("lname"));
if (matches.size() != 1) {
throw new AssertionError("Expected exactly one element with id=lname; found " + matches.size());
}
WebElement lastName = matches.get(0);
4. ID locator versus CSS and other strategies
Use the dedicated ID strategy when the target has a suitable ID and the test is meant to identify it by that attribute. The dedicated locator receives the raw ID:
By.id("fname")
CSS uses a hash-prefixed selector instead:
By.cssSelector("#fname")
Do not write By.id("#fname"). That asks Selenium to find an element whose ID literally includes the hash, which is a different value.
Selenium also documents locators based on name, CSS selector, XPath, class name, link text, partial link text, and tag name. Choose based on the actual markup and test intent. If there is no useful ID, another documented strategy may fit better. Selenium’s locator practices recommend choosing locators deliberately and managing them separately from lookup methods.
5. Practical workflow and edge cases
- Navigate to the page under test.
- Inspect the rendered DOM and identify the target’s exact
idattribute value. - Pass the raw value to the ID locator, without a CSS hash.
- Use the singular finder if one element is expected; use the plural finder if you need all matches or want an empty result when none exist.
- Assert the relevant result, such as the element count, value, or state, before continuing the test.
- Duplicate IDs: Though IDs are generally expected to be unique, malformed or dynamically generated pages can contain duplicates. A singular lookup returns the first match in the search context; use plural lookup and assert the count when uniqueness matters.
- Element not yet present: Dynamic pages may add the element after navigation. A lookup performed too early can fail; synchronize with the page condition your test needs before looking it up.
- Wrong search context: A lookup scoped to a parent element cannot find an ID outside that parent. Search from the driver or the correct parent.
- Rendered DOM differs from source: Client-side code may create or change IDs after initial HTML is delivered. Inspect the live DOM at the point the test runs.
- Frames: Elements inside a frame require the driver to switch to that frame before searching within it.
- Shadow DOM: An element inside a shadow root may require searching from that root rather than from the top-level driver.
6. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| No-such-element exception | The ID is misspelled, not present yet, or outside the active search context. | Check the exact rendered ID, wait for the relevant page state, and confirm the correct frame or parent context. |
Lookup with #value fails |
The hash was included in the argument to the dedicated ID strategy. | Pass value to By.id or By.ID; keep #value only in a CSS selector. |
| The test interacts with the wrong element | Duplicate IDs exist, and the singular finder returned the first match. | Use plural lookup, inspect all matches, and assert the expected count or scope the search to the intended component. |
| The locator works in one state but not another | The application renders a different DOM after navigation, a state change, or a responsive layout change. | Inspect the DOM in the failing state and identify a locator appropriate to that state. |
| Element is inside a frame or shadow root | The search starts from the document context instead of the nested context. | Switch to the frame or locate the shadow root, then search from the appropriate context. |
7. Performance, reliability, and cost
An ID locator is a direct way to express that a test targets an element by its ID. The supplied Selenium references do not establish a speed ranking among locator strategies, so choose based on correct identification and maintainability rather than assuming IDs are always faster.
Reliability depends on the page exposing a suitable, stable ID and on the test searching at the right time and in the right context. A singular match alone does not establish uniqueness. When uniqueness is part of the test contract, check the plural result count.
Selenium itself is browser automation software; the research sources do not specify its licensing or infrastructure costs. Account for the browsers and execution environment your project uses. A direct screenshot API can be a different fit when you need an image or PDF rather than browser interaction.
8. Or skip the browser setup
If you need a page screenshot instead of an element interaction, ScreenshotNeo captures a URL with one GET request. Its API also accepts the parameter names other screenshot APIs use, which can make switching easier. See the API docs.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot; each step can be turned off. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.
Sign up for 1,000 free screenshots a month, with no card required.
9. FAQ
Does an ID locator require the ID to be unique?
Selenium describes IDs as generally unique, but duplicate IDs can occur. Use plural lookup and check the result count if your test depends on uniqueness.
Can I use an ID locator with a dynamically generated ID?
Yes, if you can determine the rendered value when the test runs. If the value changes unpredictably, choose a locator that reflects a more stable part of the page structure.
Does findElement return every matching ID?
No. It returns the first match in the current search context. Use findElements to get all matches.
Is By.id("name") the same syntax as CSS #name?
They target an ID using different locator strategies: the ID locator takes the raw value; CSS takes a selector with a hash.


