Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Use Selenium’s By strategies to tell Python which page element to find. Prefer a unique, stable ID; if there is no suitable ID, use a short CSS selector. Choose XPath when you need to express a relationship or text condition that CSS does not handle as clearly. Use find_element for one match and find_elements when multiple matches are expected.

Find an element with Selenium Python

Import By from Selenium’s Python package, then pass a locator strategy and its value to the driver. This example opens a page, locates a login form’s email field, and enters a value:

from selenium import webdriver
from selenium.webdriver.common.by import By

# Ensure a compatible browser driver is available for your setup.
driver = webdriver.Chrome()
try:
    driver.get("https://example.com/login")

    email = driver.find_element(By.NAME, "email")
    email.send_keys("[email protected]")
finally:
    driver.quit()

Replace the example URL and locator with the page and element you are testing. find_element returns one matching element; find_elements returns a collection of matches (an empty collection if none match at the time of lookup). Selenium’s Python API defines the By constants used below.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

One element versus a collection

first_button = driver.find_element(By.TAG_NAME, "button")
all_buttons = driver.find_elements(By.TAG_NAME, "button")

Use the singular method when the test expects one target. Use the plural method when several matches are legitimate, then assert the expected count or select the intended item deliberately. A singular lookup does not make an ambiguous selector precise: it returns the first match, which may not be the element your test meant.

The eight traditional locator strategies

Strategy Python example Best fit Watch for
ID By.ID, "login" A unique, stable id attribute. IDs that are regenerated or otherwise unpredictable.
Name By.NAME, "email" A stable form-control name. The name may occur on more than one element.
CSS selector By.CSS_SELECTOR, "form#login input[name='email']" Readable combinations of element, ID, class, and attributes. Selectors tied to unstable styling or needlessly complicated.
XPath By.XPATH, "//button[@type='submit']" Relationships, text predicates, or cases with no suitable ID or name. Long, absolute, or complex expressions are harder to maintain and debug.
Class name By.CLASS_NAME, "information" Finding an element by one class token. Compound class strings are not accepted as one class name; use CSS for combinations.
Link text By.LINK_TEXT, "Selenium Official Page" A known anchor with stable visible text. Applies to links and is sensitive to copy changes.
Partial link text By.PARTIAL_LINK_TEXT, "Official Page" An anchor when a stable text substring is useful. Repeated substrings can match the wrong link.
Tag name By.TAG_NAME, "button" Collecting a group of elements, such as buttons. Common tags usually match many elements, so this is weak for unique targeting.

Here are the same patterns as executable Python statements:

from selenium.webdriver.common.by import By

by_id = driver.find_element(By.ID, "username")
by_name = driver.find_element(By.NAME, "email")
by_css = driver.find_element(By.CSS_SELECTOR, "form#login input[name='email']")
by_xpath = driver.find_element(By.XPATH, "//button[@type='submit']")
by_class = driver.find_element(By.CLASS_NAME, "information")
by_link = driver.find_element(By.LINK_TEXT, "Selenium Official Page")
by_partial_link = driver.find_element(By.PARTIAL_LINK_TEXT, "Official Page")
by_tag = driver.find_element(By.TAG_NAME, "button")
all_buttons = driver.find_elements(By.TAG_NAME, "button")

Choose a locator that will survive page changes

Selenium’s locator guidance prefers IDs when they are available, unique, and consistently predictable. When a good unique ID is absent, it recommends a well-written CSS selector. XPath is flexible, but Selenium’s guidance notes that it is typically harder to debug and can be slower; that is qualitative advice, not a universal benchmark or a promise that one strategy always wins in every browser.

Start with application-owned attributes

Inspect the rendered DOM and look for an attribute the application deliberately keeps stable: for example, an ID, a form name, an accessible label, or a test hook. Prefer such a contract over a generated class whose value may change when the page is rebuilt. Check that the selector matches exactly what you intend before adding it to a test.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Keep CSS selectors compact

For example, form#login input[name='email'] narrows an email field to a particular form. A short selector based on stable attributes is usually easier to understand than a chain of every container in the page. If the selector becomes long, consider whether a stable ancestor can make the scope clearer or whether the target has a better attribute.

Use XPath for relationships or text conditions

XPath is useful when the target makes sense in relation to another element or when a text predicate is the clearest way to express the match. Prefer a relative expression anchored to a stable attribute or ancestor, such as //button[@type='submit'], over an absolute path starting at /html. An absolute path encodes the page’s exact nesting; a small DOM rearrangement can invalidate it.

Scope repeated components

When a page contains repeated cards, rows, or forms, a selector that finds a field globally may match several copies. Locate a stable container first, then search within it, or express the relationship precisely in CSS or XPath. This makes the intended scope explicit and reduces accidental matches.

card = driver.find_element(By.CSS_SELECTOR, "section.account-card")
email = card.find_element(By.NAME, "email")

Use this pattern only when the container selector identifies the intended card; if several containers match, first make the container locator more specific or work with a collection deliberately.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Selenium 4 relative locators when position is meaningful

Sometimes the page offers no useful attribute on the target, but the target is naturally described as being above, below, beside, or near a reliably located element. Selenium 4 relative locators can express that relationship. They are an additional tool, not a substitute for a stable direct locator when one is available.

Use a nearby element only if it is itself identifiable and the spatial relationship is meaningful in the page layout. If responsive layout changes move the elements, positional relationships may become less reliable than an application-owned attribute.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Debug a locator that does not find the intended element

  1. Inspect the rendered DOM. Confirm the element is present in the page you actually opened and identify its current attributes and text.
  2. Check uniqueness. Try the selector in browser developer tools and see whether it matches one intended element or several. If several match, add stable scope rather than relying on whichever match comes first.
  3. Check strategy and value. Ensure the first argument is the right By constant and the second is a value for that strategy. For example, By.CLASS_NAME takes one class token, not a space-separated list of classes.
  4. Check link assumptions. Link-text strategies target anchors; if the target is a button or another element, choose a suitable attribute, CSS selector, or XPath instead.
  5. Replace brittle structure. If the locator starts with /html or follows many containers, anchor a shorter relative XPath or CSS selector to a stable attribute.
  6. Decide whether one or many matches are expected. Use find_elements for a legitimate collection and assert or filter it intentionally; make a singular locator unique when the test expects one item.
  7. Recheck after application changes. If a previously valid selector broke, compare the current rendered attributes and structure with the locator’s assumptions. Update the test to target a stable application contract, not a transient styling detail.

Common locator mistakes and fixes

  • No match: The attribute, text, or structure in the locator may not describe the rendered element. Inspect the current DOM and revise the locator based on what is present.
  • Wrong match: The selector is too broad or repeated. Add a stable container or attribute, then verify uniqueness.
  • Class-name error: The locator passes multiple class tokens to By.CLASS_NAME. Use one token or a CSS selector such as .primary.action.
  • Text locator misses the target: The target is not an anchor, or its visible link text has changed. Use an appropriate locator for the element type or a more stable attribute.
  • Test breaks after layout edits: An absolute XPath or long DOM path depends on nesting that changed. Replace it with a short relative locator anchored to a stable attribute.

Or skip the browser setup

If your goal is to capture a page image or PDF rather than interact with its elements in a Selenium test, ScreenshotNeo offers a website screenshot API. Its one-call GET endpoint returns an image or PDF; it is not a replacement for Selenium element interaction or locator assertions.

For example, save a WebP screenshot of a page with cURL:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for request options. Cookie banners are accepted and removed before the shot, along with known newsletter popups and chat widgets; those steps can be turned off. Bot checks, blank pages, and failed loads are not billed, and response headers report the page verdict and billing status. An MCP server provides screenshot tools for AI agents. The free plan includes 1,000 shots a month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month with no card.

FAQ

Can I use several locator strategies in one Selenium test?

Yes. Each lookup can use the strategy that best fits its target. Keep each locator explicit and maintainable instead of forcing every element into one strategy.

Is XPath always slower than CSS?

No universal speed ranking is established here. Selenium’s locator guidance describes XPath as potentially slower and harder to debug, while recommending a unique ID or well-written CSS where available. Choose first for stability and clarity, not an assumed timing advantage.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.