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:
- 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.
- 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 - 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.
- Find the submit button inside the matched form.
button = form.find_element(By.XPATH, BUTTON_XPATH)
- Confirm the XPath results against their expected element values.
assert ( form.tag_name, field.get_dom_attribute("name"), button.text, ) == ("form", "my-text", "Submit")
- 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()
- 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
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.