How to find Elements in Selenium with Python

Learn how to locate web elements with ID, XPath, CSS selectors, link text, and other Selenium strategies.

Written by Nithya Mani Nithya Mani
Reviewed by Ashwani Pathak Ashwani Pathak
Last updated: 27 August 2026 12 min read

Key Takeaways

  • Selenium offers several locator strategies in Python, including ID, name, class name, CSS selectors, and XPath, and choosing the right one makes tests more stable and easier to maintain.
  • Use find_element() when you expect a single match and find_elements() when you need to work with multiple matching elements on the page.
  • Reliable element handling depends on more than the locator itself; combining clear selectors with explicit waits and avoiding brittle XPath expressions helps reduce flaky test failures.

When a Selenium test cannot find the element it needs, the rest of the flow usually stops there. I have seen simple changes to an ID, class name, or page structure turn a working test into a failure even though the feature itself was still fine.

That is why element location is one of the first things I pay attention to when writing Selenium tests in Python. Choosing the right locator makes the test easier to read, less fragile, and much easier to maintain when the UI changes.

In this guide, I look at how to find elements in Selenium with Python using ID, name, XPath, CSS selectors, class names, and other locator strategies, along with when to use find_element() and find_elements() in real test scenarios.

What are Elements in Selenium?

In Selenium, I work with web elements every time I interact with a page. These are the HTML components users see or use, such as buttons, text fields, checkboxes, dropdowns, links, and other page content.

Selenium represents these elements through the WebElement interface. Once I locate an element, I can perform actions such as clicking it, entering text, reading its value, or checking its state.

To find the right element, I use locator strategies such as ID, name, class name, XPath, or CSS selectors. The better the locator, the easier it is to keep the test stable when the page changes.

Why Web Elements Matter in Automation

Web elements are at the center of most automation and testing scripts because they are how I tell Selenium what to interact with on a page. If I cannot identify the right element reliably, even a simple test can break before it gets to the actual validation.

  • Interact with the page: Web elements let me click buttons, type into input fields, select options, open menus, and perform the same actions a user would.
  • Verify application behavior: I can read text, inspect attributes, check whether an element is displayed or enabled, and confirm that the page responds correctly after an action.
  • Build complete user flows: Locating individual elements makes it possible to automate end-to-end journeys such as login, search, checkout, form submission, and account creation.
  • Handle dynamic content: Modern pages often load or update elements after the initial page load. By locating those elements correctly and pairing them with waits, I can make tests more reliable even when content appears asynchronously.
  • Reduce flaky failures: Stable locators help prevent tests from breaking because of small UI changes. I usually prefer selectors that are specific enough to identify the element without depending too heavily on fragile page structure.
  • Reuse test logic: Once elements are identified consistently, I can organize them into reusable page objects or helper methods, which makes larger test suites easier to maintain.
  • Improve debugging: When a test fails, a clear element locator makes it easier to understand whether the problem came from the page, the locator, or the test logic itself.

How Locators Identify Web Elements

Element locators are the selectors I use to tell Selenium which part of the page I want to work with. A locator can point to a single element, such as a login button, or a group of elements, such as every product card on a page.

Selenium supports several locator strategies, and I choose between them based on how the page is structured and which attributes are likely to remain stable.

Locator TypeWhat I use it for
IDFinds an element by its id attribute. I usually prefer this when the ID is unique and stable.
NameFinds elements using the name attribute, which is common in forms and input fields.
XPathLocates elements using XPath expressions. It is useful when I need to navigate relationships between elements or target something without a simple unique attribute.
Link TextFinds a link using its exact visible text.
Partial Link TextFinds a link using part of its visible text when the full label may vary.
Tag NameFinds elements by HTML tag, such as input, button, or a. This is useful when I expect multiple matches.
Class NameFinds elements using a CSS class. I use this carefully because classes are often shared by many elements.
CSS SelectorUses CSS selector syntax to target elements by attributes, classes, IDs, or combinations of these. It is one of the most flexible options for web automation.

For example:

driver.find_element(By.ID, "login-button")

This returns the first element with the ID login-button.

driver.find_elements(By.NAME, "username")

This returns a list of all elements whose name attribute is username.

driver.find_elements(By.XPATH, "//input")

This finds all <input> elements on the page.

driver.find_elements(By.CSS_SELECTOR, "p.content")

This finds all paragraph elements with the content class.

The important part is not simply knowing every locator type. I try to choose a locator that is specific, readable, and unlikely to change when the UI is updated. That usually makes the test easier to maintain and less likely to fail for reasons unrelated to the feature itself.

Getting Python Ready for Web Automation

Before I can locate elements, I first need Selenium available in the Python environment. The setup is small and only takes a couple of steps.

1. Install Selenium

Use pip to install the Selenium package:

pip install selenium

With modern Selenium versions, Selenium Manager can handle driver management automatically in many common setups, so I usually do not need to download and configure a browser driver manually.

2. Import the modules

Next, import WebDriver and the By class, which I will use for locator strategies:

from selenium import webdriver

from selenium.webdriver.common.by import By

At this point, I am ready to launch a browser and start finding elements with locators such as ID, CSS selector, XPath, or name.

Ways To Locate Elements in Python

Once the browser is running, I choose a locator based on what is most stable on the page. I usually start with a unique ID or a clear CSS selector, then move to XPath when I need more control over relationships or text.

Before the examples, there is one distinction I keep in mind:

  • find_element() returns the first matching element and raises an exception if nothing matches.
  • find_elements() returns all matching elements as a list. If nothing matches, it returns an empty list.

1. Locate an Element by ID

If an element has a unique and stable id, this is usually the first locator I try because it is simple and easy to read.

element = driver.find_element(By.ID, "element_id")

For example:

login_button = driver.find_element(By.ID, "login-button")

Locate an Element by ID

Because an HTML id is expected to be unique on the page, I would normally use find_element() rather than find_elements() with this locator.

2. Locate an Element with XPath

I use XPath when the element does not have a useful ID or when I need to locate it by text, attributes, or its relationship to another element.

# Find by exact text

element = driver.find_element(

    By.XPATH,

    "//*[text()='Get started free']"

)



# Find by partial text

element = driver.find_element(

    By.XPATH,

    "//*[contains(text(), 'Get started')]"

)



# Find by attribute

element = driver.find_element(

    By.XPATH,

    "//input[@name='username']"

)

Locate an Element with XPath

XPath is flexible, but I try to keep expressions short and avoid selectors that depend heavily on the page hierarchy.

3. Locate an Element with a CSS Selector

CSS selectors are another option I use often because they can target IDs, classes, attributes, and combinations of these without much syntax.

# By class

element = driver.find_element(

    By.CSS_SELECTOR,

    ".classname"

)



# By ID

element = driver.find_element(

    By.CSS_SELECTOR,

    "#elementid"

)



# By attribute

element = driver.find_element(

    By.CSS_SELECTOR,

    "input[name='username']"

)

Locate an Element with a CSS Selector

When the page already has clear CSS-friendly attributes, this is often one of the easiest locators to maintain.

4. Locate Links by Their Text

For anchor elements, Selenium lets me use the visible link text directly.

# Exact link text

link = driver.find_element(

    By.LINK_TEXT,

    "Help Center"

)



# Partial link text

partial_link = driver.find_element(

    By.PARTIAL_LINK_TEXT,

    "Help"

)

Locate Links by Their Text

I use LINK_TEXT when the label is stable. PARTIAL_LINK_TEXT is useful when only part of the text is predictable.

5. Use Name, Tag Name, or Class Name

These locators are useful when the page structure makes them a better fit:

Locator MethodWhen I use itExample
NameWhen a form field has a stable name attributedriver.find_element(By.NAME, “username”)
Tag NameWhen I want to target elements by HTML tagdriver.find_elements(By.TAG_NAME, “input”)
Class NameWhen an element has a useful single CSS classdriver.find_element(By.CLASS_NAME, “login-button”)

In practice, I do not choose a locator just because Selenium supports it. I look for the option that is specific enough to find the right element and stable enough to survive normal UI changes.

How to Keep Element Locators Reliable

A locator only works well if it keeps finding the right element as the page changes. I usually focus more on stability and readability than on making a selector as short or clever as possible.

  • Prefer unique and stable attributes: I start with a unique id, name, or dedicated test attribute when one is available. These are usually less likely to break than selectors tied to the page layout.
  • Keep selectors specific: CSS selectors and IDs are often clearer than broad locators such as tag names. For example, targeting input[name=”email”] is safer than locating every input element and relying on its position.
  • Avoid brittle XPath expressions: I try not to use long absolute XPath expressions such as /html/body/div[2]/… because small DOM changes can break them. Shorter XPath expressions based on stable attributes or relationships are easier to maintain.
  • Use explicit waits for dynamic elements: I do not assume an element is ready just because the page has loaded. Explicit waits let me wait for the exact condition I need before interacting with it.
from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC



element = WebDriverWait(driver, 10).until(

    EC.presence_of_element_located((By.ID, "element_id"))

)
  • Use relative locators when relationships are clearer: Selenium 4 supports relative locators such as above(), below(), and near(). I use these when an element is easier to describe in relation to another stable element than through its own attributes.
  • Do not depend on generated values: Dynamic IDs, changing class names, and index-based selectors can make tests fragile. If those values change between builds, I look for a more predictable attribute.
  • Choose maintainability over tiny speed differences: Locator performance rarely matters as much as whether the selector remains reliable over time. I would rather use a clear, stable locator than optimize for a negligible lookup-time difference.

The best locator is usually the one another tester can understand quickly and that still works after a normal UI update.

Conclusion

Finding elements is one of the most basic parts of Selenium automation, but it has a big effect on how reliable my tests become.

I try to choose locators that are clear, stable, and easy to maintain instead of relying on selectors that break whenever the page structure changes.

I also avoid treating locators in isolation. Combining the right selector with explicit waits and sensible element handling makes my tests much less flaky. Once those basics are in place, the rest of the Selenium workflow becomes easier to build, debug, and maintain.

Version History

  1. Aug 27, 2026 Current Version

    Updated locator guidance, examples, and structure for clearer Selenium element handling in Python.

    Ashwani Pathak
    Reviewed by Ashwani Pathak Automation Expert
Tags
Automation Testing Selenium
Nithya Mani
Nithya Mani

Lead Engineer

Nithya Mani is a Lead Engineer with 8+ years of experience in customer solutions. She specializes in creating tailored testing solutions that address real customer needs and optimize workflows.

Automation Tests on Real Devices & Browsers
Seamlessly Run Automation Tests on 3500+ real Devices & Browsers