For Test Automation Engineers

Master XPath
Once and For All

Stop writing fragile locators. Learn to craft bulletproof XPath expressions with interactive tutorials, a live playground, and real-world challenges.

29
Lessons
96
Exercises
Free
Forever

Why XPathDecoded?

Everything you need to go from XPath confusion to XPath confidence.

Write Robust Locators

Learn patterns that survive DOM changes. Every example rated for stability so you know what's production-ready.

Interactive Playground

Test XPath expressions against real HTML in real-time. See matches highlighted, get instant feedback.

Practice & Master

Reinforce learning with MCQs, timed quizzes, and hands-on challenges. Track your progress as you improve.

Quick Recipes

Common XPath patterns ready to use. Click any recipe to try it in the playground.

By data-testid

stable

Target an element by its test id attribute

//*[@data-testid='login-button']
Try it

Button by Text

medium

Find a button containing specific text

//button[contains(text(), 'Sign')]
Try it

Exact visible label

medium

Match the trimmed visible text of a button, tolerant of whitespace and nesting

//button[normalize-space()='Sign In']
Try it

Input by Label

stable

Find the input that follows a label

//label[normalize-space()='Email Address']/following-sibling::input
Try it

Table Cell by Header

medium

Find a cell by computing the column index from its header

//table//tr/td[count(//th[normalize-space()='Price']/preceding-sibling::th)+1]
Try it

Button in a specific row

stable

Filter the row by content, then descend to the action

//tr[td[normalize-space()='USB-C Hub']]//button[@data-action='edit']
Try it

Button in the card with a title

medium

Container-by-content, then the control inside it

//article[.//h2[normalize-space()='Smart Watch Series 5']]//button[normalize-space()='Add to Cart']
Try it

Button inside an open dialog

stable

Anchor to the dialog landmark to avoid the page-level duplicate

//*[@role='dialog']//button[normalize-space()='Save']
Try it

Contains Class

medium

Match partial class names

//*[contains(@class, 'btn-primary')]
Try it

Button containing an icon

medium

Match the icon by its data attribute, then the button around it

//button[.//*[local-name()='svg'][@data-icon='trash']]
Try it

Common Questions