CSS Selector Tester
Run a selector against your own markup, see what it matches and read its specificity.
The Browser's Own Selector Engine, On Your Markup
There are two ways to find out whether a selector works: guess, or ask the thing that will have to answer. This tool asks. Your markup is parsed into an inert document and the selector is handed to the same engine the browser uses on a real page, so a match here is a match there — including for the corners where people's mental models tend to drift, like nth-child counting all siblings while nth-of-type counts only matching ones.
The specificity is shown alongside, because a selector that matches and still loses to another rule is the other half of the problem, and the one that wastes the afternoon.
Key features
- The real engine — querySelectorAll on a parsed document, not a reimplementation that disagrees in edge cases.
- Parsed inertly — scripts in the markup never run and images are never fetched.
- Every match, with its path — each result shown as a readable element path plus its text.
- Specificity counted — ids, then classes and attributes and pseudo-classes, then elements.
- Invalid selectors named as such — the browser's own rejection, which is what would drop the rule from a stylesheet.
This tool runs entirely inside your browser using native Web APIs. Your files and text are never uploaded to a server, never logged and never shared with third parties.
How to use: CSS Selector Tester
- Paste your markup
A fragment is fine — it does not need to be a whole document. - Type a selector
Anything valid CSS, from a single class to a long descendant chain. - Read the matches
Each is shown with its path through the document and its text. - Check the specificity
Three numbers: ids, then classes and friends, then elements.
Technical specifications
| Processing location | Entirely in your browser — no server round trip |
|---|---|
| Data uploaded | None. Files and text never leave your device |
| Price | Free — no account, no trial, no usage cap |
| Category | Developer |
| Works offline | Yes, once the page has loaded |
| Browser support | Chrome 90+, Edge 90+, Firefox 90+, Safari 15+ |
| Interface languages | English, 中文, हिन्दी, Español, العربية |
Frequently asked questions
What is the difference between nth-child and nth-of-type?
nth-child counts every sibling; nth-of-type counts only siblings of the same tag. In a list of paragraphs with a heading first, p:nth-child(2) matches the first paragraph and p:nth-of-type(2) matches the second. Almost every surprise with these two comes from that difference, and it is visible immediately here.
How is specificity actually compared?
As three numbers read left to right, not as a total. 1-0-0 beats 0-9-9 because the first number is larger — ten classes never outweigh one id. When two selectors tie, the one written later in the stylesheet wins. Inline styles sit above all of it, and !important above that.
Is the specificity exact?
For ordinary selectors, yes. For :is(), :not() and :has() it is an estimate and labelled as one, because those take the specificity of their most specific argument, which needs a full selector parser to work out. :where() is the odd one: it always contributes zero, by design.
Can I use this for web scraping?
Yes, and it is one of the better uses for it. Paste the page source you are working against, try selectors until one matches only what you want, and take it to your scraper. Testing against the real markup catches the class names that turn out to be generated and change on every build.
Is it safe to paste markup with scripts in it?
Yes. DOMParser builds a document that is not connected to any window — its scripts never execute, its images are never requested, and it cannot see or touch the page around it. That is why the selector can be tested against untrusted markup at all.