By · Updated

CSS Selector Tester

Matched Element Paths, Attributes and Text From Pasted HTML

No ratings yet

OneTask is free, with no sign-up, and built by one person.
If this tool saved you time, a coffee helps keep new ones coming.

How the CSS Selector Tester works

This CSS selector tester highlights every element a selector matches. Paste a fragment of HTML or a whole page, write a CSS selector and see exactly which elements it picks out. Every match is listed with a unique path, its tag and classes, and either its markup, its text or its attributes, so you can check a scraper, a test locator or a stylesheet rule before you rely on it.

CSS selector tester: specificity and matching

CSS selectors are how stylesheets, JavaScript, scrapers and end-to-end tests all point at elements. The same string works in a .css file, in document.querySelectorAll, in BeautifulSoup's select(), in Playwright and Cypress locators and in Scrapy. Because the syntax is compact, it is easy to write a selector that is subtly too broad — matching a hidden duplicate of the element — or too narrow, matching nothing on the page you actually get from the server. This tester evaluates the selector with the browser's own engine, so the result is authoritative.

Simple selectors. div by tag, .price by class, #main by id, [data-id] by attribute presence and [href^="https"] by attribute value with the ^= starts-with, $= ends-with, *= contains and ~= word-in-list operators. Combine them without spaces to require all of them on one element: a.button[target=_blank].

Combinators. A space means descendant at any depth, > means direct child, + the immediately following sibling and ~ any later sibling. nav > ul > li walks a fixed structure; h2 + p finds the paragraph directly after each heading. Comma separates alternatives: h1, h2, h3 matches all three.

Pseudo-classes. :first-child, :last-child, :nth-child(2n+1), :nth-of-type(3), :not(.hidden), :has(img), :is(article, section) > h2, :empty and :checked are all supported by modern browsers and therefore by this tool. :has() in particular lets a selector choose a parent based on its children, which was impossible in CSS for years and is now the standard answer to "the card that contains a sold-out badge".

What is not supported. Pseudo-elements like ::before do not select elements and cannot be queried. Interaction states — :hover, :focus, :visited — never match in a static document. Library extensions such as jQuery's :contains() and :eq() are not real CSS and will report a syntax error; use :has() or an XPath expression instead.

Reading the results. Each match gets a path of the form body > div:nth-child(2) > a that identifies it uniquely and can be pasted straight back in. The Show setting switches the right column between the element's outer HTML, its trimmed text and a list of its attributes. The headline count is the fastest sanity check: a scraper selector should usually match exactly the number of items you can see on the page.

Parsing. The text is parsed with the browser's HTML parser, so fragments without html or body wrappers are fine, unclosed tags are repaired the way a browser would repair them, and element names are case-insensitive. Scripts in the pasted HTML are never executed.

FAQ

Why does a selector that works in DevTools match nothing here?

DevTools runs against the live DOM after JavaScript has run. If the elements you see are rendered by a framework, they are not in the server's HTML. Paste the DOM from the Elements panel — right-click html, Copy outerHTML — rather than the page source.

Does it support :has() and :is()?

Yes, along with :where(), :not() with complex arguments, and the :nth-child(An+B of S) form, because it uses the browser's selector engine and every current browser supports them. If your target is an older scraping library, check that library's documentation before relying on them.

How do I select by text content?

CSS cannot. Selecting by the text an element contains is a job for XPath — //a[contains(., 'Next')] — or for a test framework's text locator. Use the XPath tester for that, or select a structural parent here and filter in code.

Why do I get duplicate matches?

querySelectorAll returns each element once, so real duplicates mean the page really has two copies — typically a mobile and a desktop version of the same component, one hidden by CSS. Add :not([hidden]) or narrow by an ancestor to pick the one you want.

See also: all Dev Utilities tools, Formatters & Validators, Data & Encoding, Security & Identifiers, SEO, Accessibility, AI.

Related tools