XPath for In-Browser Testing

Both Chrome and Firefox support XPath searches when in the DOM view of their dev tools. Because the browser cleans whatever HTML it encounters (closing tags, correcting nesting), XPath can operate on the code as XML.

Simple checks like finding a unique ID value can result in multiple hits in the page (attribute references, script, partial matches, etc.). As a result, one of my most frequent XPath searches will bring me directly to the node with a given ID value (or tell me there is more than one).


Essentially that statement is saying bring me to any node (*) anywhere in the tree (//) that has an id attribute ([@id…]) with a specific value ([…="VALUE"]).

This works for other elements and attributes. To adjust it, this will get me all nodes that are <input type="text">:


This will get me all nodes that are <input type="text"> that do not have an autocomplete attribute:


This will get me all nodes that are <input type="text"> that do not have an autocomplete attribute that are descendants of a <main> (to avoid contact forms in a footer, for example):


Breaking away from the form field example, this will cycle through all instances of a node with a tabindex value of 1 or more:


This returns instances of aria-labelledby that probably point to more than one thing (or just have an errant space character):

//*[contains(@aria-labelledby," ")]

Swap out aria-labelledby for aria-describedby, headers, or other attributes that accept space-separated values.

Annoying aria-label values that include interaction instructions with either “click” or “press”:

//*[contains(@aria-label,"click") or contains(@aria-label,"press")]

You can find all instances of a particular inline style (you will need to tweak spaces and syntax to match what you want to find):

//*[contains(@style,"color: rgb(112, 129, 133)")]

If you follow me on the Twitters you may recall when I asked folks to check for hits on this one:


It was the quickest way I could think of to find cases of nodes with aria-hidden="false" living somewhere within a node with aria-hidden="true" (primarily to see if Angular is the only offender preventing this ARIA issue from ever going anywhere).

Let’s take a quick look in the browser.

Here I demonstrate the feature in Firefox to identify duplicated id values on a page:

In Firefox dev tools on the Material Design page, searching for ‟theming” and getting 40 results. Searching for ‟//*[@id="theming"]” and getting 2 results.
I know this page has a duplicated id value because my accessibility tools told me so, but when searching for all instances of ‟theming” I get 40 results. Using //*[@id="theming"] gets me 2 results, a more manageable number.

And here it is in Chrome:

In Chrome dev tools on the Material Design page, searching for ‟filled-text-field” and getting 23 results. Searching for ‟//*[@id="filled-text-field"]” and getting 2 results.
As above, but when searching for all instances of ‟filled-text-field” I get 23 results. Using //*[@id="filled-text-field"] gets me 3 results

If you are far more comfortable with CSS selectors, Lloydi showed me this handy CSS selector to XPath converter.

That’s it. That’s the post.

Update: 27 April 2021

Tossing out some other variations that may help. Like this one which made it easier to find the live regions (turned out there were more than one) that were getting updated with the exact same text that appeared in a few other places on the screen in some deeply nested nodes:


This syntax helped me quickly demonstrate a page had 26 script blocks:


On the same page, this helped me quickly prove there were 157 calls to external scripts:


And confirm they were all loading from external domains:

It also had way too many linked CSS files:



These DevTool interfaces also let you search by CSS selector, like main input[type="text"]:not([autocomplete]), and has auto-complete capabilities that can be helpful. I used a little XPath, basically by rote, well over ten years ago and haven’t seen much reason to learn it.

One thing the XPath version seems to do is clearly differentiate the DOM code from mere strings. In trying to find duplicate ids using just the CSS selector #theming, the search also finds hers that end with that string; preceding it with an asterisk (* #theming) does seem to force it to match only the CSS selectors.

Curtis Wilcox; . Permalink
In response to Curtis Wilcox. Reply

I also have dusty XPath skills from the previous decade (my company built a CMS that output XML, which we processed with XSLT to web and other formats), so yeah, it is a niche skill for me too.

But as I have seen more tools (things like Selenium or accessibility testing tool reporting features) lean on XPath, I have found myself dusting off those skills in response.

Leave a Comment or Response

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>