Guide
CSS selectors are fast and native to the browser; XPath can walk up to parents, sideways to siblings, and filter by text content. This guide compares the two languages for web scraping and testing, with runnable XPath examples you can open in the Sandbox.
CSS selectors are built for styling, so every modern browser optimises them for speed. They are the native language of Playwright, Puppeteer, Selenium, and Cypress, which makes them the right default for most UI tests.
XPath was designed to navigate XML trees. It can move up to parents and ancestors, sideways to siblings, and filter by the text content inside a node — relationships CSS selectors cannot express.
The table below shows common locator patterns side by side. Where only XPath appears, you are looking at a tree relationship CSS cannot express.
| Task | CSS selector | XPath |
|---|---|---|
| By id | #work | //*[@id='work'] |
| By class | .project | //*[contains(@class, 'project')] |
| By attribute | [data-testid='hero'] | //*[@data-testid='hero'] |
| Child | section > h2 | //section/h2 |
| Descendant | section h2 | //section//h2 |
| First child | li:first-child | //li[1] |
| Parent | not possible | //h2/parent::* |
| Ancestor | not possible | //span/ancestor::form |
| Preceding sibling | not possible | //input/preceding-sibling::label |
| Text content | not possible (native CSS) | //a[contains(., 'Home')] |
Open any example in the Sandbox to run it against the built-in XHTML sample. Tweak the expression, then copy it into your scraper or test suite.