XPath Playground
Practice XPath against a real page. Type an expression and every matching element lights up instantly, along with the Selenium and Playwright code to use it. Work through the challenges, then keep the cheat sheet below as a reference.
XPath cheat sheet
Every example below works in the playground above. Prefer relative paths that
start with // over absolute ones like /html/body/main/ul/li[2]:
an absolute path breaks the moment the page layout changes.
| Expression | What it selects |
|---|---|
//h1 | Every h1 element, anywhere on the page. |
//input[@id='nl-email'] | An element by an exact attribute value. |
//button[text()='Subscribe'] | An element whose own text is exactly "Subscribe". |
//h2[contains(text(),'Key')] | Partial text match. |
//li[contains(@class,'sale')] | One class among several (@class='sale' fails when there are more classes). |
//label[normalize-space()='Email address'] | Text match that ignores extra spaces and line breaks. |
//input[@type='checkbox' and @name='terms'] | Combine conditions with and / or. |
//h2/following-sibling::span | Siblings that come after an element. |
//td[text()='#1002']/parent::tr | Step up to the parent. |
//span[text()='Shipped']/ancestor::tr | Step up any number of levels to an ancestor. |
//tr[td[text()='#1002']] | A row that contains a matching cell, without stepping back up. |
(//li)[2] | The second match on the whole page. |
//ul/li[2] | The second li inside each ul. Not the same as (//li)[2]. |
//*[starts-with(@data-testid,'add-')] | Attribute starts with a prefix, on any element type. |
XPath or CSS?
Reach for XPath when you need to match on text or walk up the tree
(parent::, ancestor::), which CSS can't do. For everything
else, CSS is shorter and usually faster. Try the same tasks in the
CSS Selector Playground, or see how Playwright's
user-facing locators compare in the Playwright Locator Playground.