Web interfaces often identify controls through nearby labels, ancestor sections, or visible text instead of one unique attribute. XPath gives Selenium a way to express those relationships and distinguish one control from visually similar controls elsewhere on the page.

Python passes an XPath expression through By.XPATH to find_element() or an explicit-wait locator tuple. A lookup from the driver searches the current document, while a lookup from an existing WebElement can stay within that element when the expression starts with .//.

Prefer a stable unique ID or CSS selector when either describes the target directly. Reserve XPath for relationships that belong to the interface contract, and avoid copied absolute paths or positional indexes that break when a wrapper or neighboring component changes.

Steps to find Selenium elements with XPath:

  1. Define the page-level and descendant XPath locators for the target form.
    FORM = (By.XPATH, "//form[.//input[@name='my-text']]")
    FIELD_XPATH = ".//input[@name='my-text']"
    BUTTON_XPATH = ".//button[normalize-space()='Submit']"

    The form locator requires a descendant input named my-text. normalize-space() ignores extra whitespace around the visible button label.

  2. Wait for the form that satisfies the page-level XPath.
    form = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located(FORM)
    )

    The explicit wait retries the locator until the form exists or the timeout raises an exception.
    Related: How to use explicit waits in Selenium

  3. Find the text field inside the matched form.
    field = form.find_element(By.XPATH, FIELD_XPATH)

    The leading dot in .// keeps the search inside form. A bare // expression starts from the document root and can select a matching control from another form.

  4. Find the submit button inside the matched form.
    button = form.find_element(By.XPATH, BUTTON_XPATH)
  5. Confirm the XPath results against their expected element values.
    assert (
        form.tag_name,
        field.get_dom_attribute("name"),
        button.text,
    ) == ("form", "my-text", "Submit")
  6. Save the completed locator program as selenium-find-xpath.py.
    selenium-find-xpath.py
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.ui import WebDriverWait
     
     
    URL = "https://www.selenium.dev/selenium/web/web-form.html"
    FORM = (By.XPATH, "//form[.//input[@name='my-text']]")
    FIELD_XPATH = ".//input[@name='my-text']"
    BUTTON_XPATH = ".//button[normalize-space()='Submit']"
     
     
    driver = webdriver.Chrome()
    try:
        driver.get(URL)
     
        form = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located(FORM)
        )
        field = form.find_element(By.XPATH, FIELD_XPATH)
        button = form.find_element(By.XPATH, BUTTON_XPATH)
     
        assert (
            form.tag_name,
            field.get_dom_attribute("name"),
            button.text,
        ) == ("form", "my-text", "Submit")
     
        print(f"page_title: {driver.title}")
        print(f"form_tag: {form.tag_name}")
        print(f"field_name: {field.get_dom_attribute('name')}")
        print(f"button_text: {button.text}")
    finally:
        driver.quit()
  7. Run the program to prove that each XPath resolves to the intended element.
    $ python3 selenium-find-xpath.py
    page_title: Web form
    form_tag: form
    field_name: my-text
    button_text: Submit