CSS Selector & XPath Tester
Run a CSS selector or an XPath expression over HTML or XML you paste, with a live match count and every match highlighted and resolved to a unique path.
About CSS Selector & XPath Tester
This CSS selector tester and XPath tester runs against markup you paste, entirely in your browser. You have a saved page, an XML payload from an API, or a snippet a template will render. The question is narrow: whether one expression picks the node you want and only that node. DevTools answers that on a live page. This online selector tester answers it from a snapshot, on a locked-down laptop, or on markup no server has rendered yet. You can test XPath without browser devtools, against a file you already have. Both engines sit on one screen: CSS runs through querySelectorAll, XPath runs through document.evaluate, and switching between them keeps the same document. Matches are highlighted in the parsed document view, and each one resolves to a unique CSS path and a unique XPath you can paste into a scraper or a test. The match count carries a uniqueness verdict, so a locator that quietly matches two elements shows up before it turns into a flaky test. HTML and XML are separate parse modes because they are genuinely different parsers: HTML scaffolds and repairs your markup, XML is case-sensitive and reports a parse error with its line and column. Browsers implement XPath 1.0 and nothing later, so this XPath evaluator online runs that engine rather than a JavaScript reimplementation of a version your browser cannot execute. Nothing you paste is uploaded, and the tool makes no network calls.
How to use the CSS Selector & XPath Tester
- Paste HTML or XML into the document panel, or drop an .html, .xml, .svg, or .xhtml file onto it. This is how you test a CSS selector against HTML you already have instead of a page you have to load first.
- Pick the parse mode. HTML repairs and scaffolds your markup the way a browser does, which is what an XPath tester for HTML has to do. XML is case-sensitive and reports parse errors rather than repairing them.
- Choose the engine. CSS runs querySelectorAll, XPath runs document.evaluate, and both read the same parsed document.
- Type the expression. Matches highlight in the parsed document as you type, and the badge gives the CSS selector match count, with a Unique locator badge beside it when exactly one element matches.
- If the count is zero, or the expression is rejected, read the diagnosis. It names the cause (a pseudo-element, a dynamic pseudo-class, a silently dropped :is() branch, a default namespace, or the wrong engine) and offers a one-click rewrite where one exists. Use it to validate CSS selector syntax without guessing at which construct broke.
- With the CSS engine selected, read the Equivalent XPath panel, or the named refusal saying which construct cannot cross over. "Use this" swaps the CSS to XPath result into the expression field and switches the engine.
- In XML mode, add prefix and URI bindings in the Namespace bindings panel, then use the prefix in your expression. XPath 1.0 has no default namespace, so an unprefixed name will not match a namespaced element.
Common Use Cases
Validate a scraping rule against a saved page
A CSS selector tester for scraping is only worth much if it runs against the exact HTML your scraper will see. Save the response, paste it here, and test the CSS selector against the HTML before the extraction rule lands in code. The per-match panel shows the text and attributes you would actually pull out.
Check that a test locator is unique
One match means a stable Playwright, Selenium, or Cypress locator. Two means a test that passes until someone adds a second card to the page. The count and the resolved unique path both tell you which of the two you have.
Query an XML feed or SOAP envelope
Bind the prefix, run the XPath, and read the parse error with its line and column if the document is malformed. Atom, RSS, and SOAP all put their payload in a namespace, and that is the most common reason an XPath that looks right returns nothing.
Work out why a CSS rule is not applying
First confirm the selector matches the element you think it matches. Then read the specificity to see whether another rule outranks it. It is reported per selector in the list rather than aggregated, because that is how the cascade evaluates it.
Frequently Asked Questions
How do I test a CSS selector against HTML?
Paste the markup into the document panel, leave the parse mode on HTML, and type the selector. The tool parses the markup into a document in your browser and runs querySelectorAll against it, so the semantics are the ones the page itself would use. The page does not have to be live. The same goes if you need to test XPath without browser devtools: a saved response, a template fragment, or a snippet someone pasted into a ticket is enough to work from.
Why does my CSS selector match nothing?
Five causes cover almost every case. Pseudo-elements like ::before are rendering boxes rather than nodes, so no selector API can return them. Dynamic pseudo-classes like :hover and :focus need a rendered page with a user in front of it. An invalid branch inside :is() or :where() is dropped silently by the browser, so a typo there gives you a wrong match set and no error at all. The HTML parser inserts a tbody into any table that lacks one, so table > tr cannot match. And the engine toggle may simply be on XPath. The tool names whichever one applies rather than showing you an empty list, which is usually all it takes to validate CSS selector syntax against real markup.
How do I write an XPath that matches text?
Use contains(., "x") to search an element's whole string value, including text inside its descendants. contains(text(), "x") looks only at the first text node child, which is the usual trap: <p>Hello <b>world</b></p> has a text node of "Hello " and nothing else at that level. Paste your markup and run both forms through the XPath contains text tester above. The match count changes immediately and shows you which one you meant.
Can I convert a CSS selector to XPath?
Yes, for the subset that translates soundly: type, id, class, and attribute selectors with every operator, the four combinators, the child-position pseudo-classes, and :not() or :has() with a single simple argument. Outside that subset the tool refuses by name instead of guessing. State pseudo-classes are the clearest case. :checked reads live element state, which is not part of the XPath data model at all, so any translation would be wrong in a way you would not notice. Class matching uses the concat and normalize-space form, so it never matches a partial class name.
What XPath version do browsers support, and does this XPath tester match it?
XPath 1.0, through document.evaluate, and that is exactly what this tool runs. There is no matches(), no ends-with(), no sequences, and no XPath 2.0 or 3.1 anywhere in a browser engine. A tool advertising 2.0 or 3.0 is shipping a JavaScript reimplementation, so an expression you test there may not work in the browser, Selenium, or Playwright you actually use.
Why does my XPath work in DevTools but not here, or the other way round?
Parse mode, almost always. text/html scaffolds a document with html, head, and body, inserts a tbody into tables, and moves stray content out of tables. application/xml does none of that and is case-sensitive, so //Entry and //entry are different expressions. Switch the mode to match what the browser did, then read the repair notices, which name each change the HTML parser made to your markup.