CSS Selector Tester
Test CSS selectors against HTML snippets
Your selector finds nothing, or finds forty things instead of twelve, and the page looks exactly like it should in DevTools. Paste the HTML your parser actually receives, try selectors against it, and see every match and its count before you run anything across a thousand pages.
No input provided
How to use
- 1Paste the HTML your code receives, not what DevTools shows — Those are two different documents. Take the response body from Request Tester, or view-source, or Copy outerHTML if you know the fragment is already in the source. Testing against the wrong one is the single most common reason a selector passes here and fails in production.
- 2Write the selector — Anything the browser understands works: .product-card h2 a, div[data-id], ul.results > li:nth-child(2), nav a[href]:not([href='#']).
- 3Read the count first, the matches second — The number of matches tells you more than the matches do. Expected twelve products and got forty? The selector reaches outside the list. Got zero? Either the class is not in the raw HTML at all, or it is spelled differently by one character.
- 4Tighten it until the count is right — Add a parent, an attribute, or a structural pseudo-class and watch the number move. Matches update as you type; switch auto mode off and use Run if the HTML is large.
Examples
.product-title -> 0 matchesdiv.price#root > div:nth-child(2) > div > div.sc-hKgILt > ul > li:nth-child(1) > a[class^="ProductCard_"]ul.results > li.itemsection.reviews .authornav a[href]:not([href='#'])tbody tr:nth-child(2n) td:nth-child(3)When to use for web scraping
CSS selectors are what most Python and Node parsers run on — BeautifulSoup, Scrapy, Cheerio and Playwright all take them directly. The trouble is that a selector verified in DevTools is verified against the wrong document. DevTools shows the DOM after scripts have executed; your parser sees the bytes that arrived. Anything a script inserted is not there, and a selector that matched forty items in the console can match zero in code. The second recurring problem is class names you cannot rely on. Styled-components, CSS modules and utility frameworks generate names like sc-hKgILt or ProductCard_title__x7Kd2, and they change whenever the site is rebuilt. A parser anchored to them works for a week. Anchor to something that is not styling instead: a data-attribute, an id, itemprop, the tag structure, or at least a stable prefix through [class^="ProductCard_"]. This tool works on an HTML string, exactly the way your parser does. It returns every matched element and, more usefully, how many there were. The count is the real test: forty where you expected twelve means the selector reached past the container, and zero means the thing you are after is not in this HTML at all. Both answers arrive in seconds instead of after a crawl. What it cannot do: it does not execute JavaScript, and dynamic pseudo-classes like :hover, :focus and :checked mean nothing in a static document — structural ones such as :nth-child, :first-of-type and :not() work fully. CSS also cannot select an element by its text or walk upwards to a parent; when you need that, use XPath Tester. To get the raw HTML in the first place, send the request through Request Tester and paste the response body here.