GameCSS · XPath

Selector Golf

Write the shortest selector that matches exactly the highlighted elements: nothing more, nothing less. Fewer characters means a better score.

Hole 1 of 15 · par 2

Select the page heading

page.html target matched wrong match
<div class="page">
<header class="site-header">
<a href="/" class="logo">Bookstore</a>
</header>
<h1 class="title">All books</h1> (target)
<p class="count">20 results</p>
</div>
Your score is the character count of the selector.
Type a selector to start.

Learn the skill behind the game

CSS vs XPath selectors for web scraping

Every scraper comes down to the same step: point at the elements that hold the data and ignore everything else. You do that with a selector, and there are two languages for it.

CSS selectors are the ones you already know from stylesheets: h1, .price, ul.books > li a, a[href^="/product/"]. They are short and readable, and almost every tool supports them. Beautiful Soup's select(), Cheerio in Node.js, Scrapy and Playwright all take CSS selectors directly, so most scrapers never need anything else.

XPath describes a path through the document tree: //h3/a, //span[@class="price"]. It is longer to write but more powerful. XPath can match on an element's text, as in //a[contains(text(), "Next")], step up to a parent with .., and pick the nth match across the whole document. CSS can do none of these. Scrapy and lxml support XPath natively, and Playwright accepts it with an xpath= prefix.

A practical rule: write CSS first, and switch to XPath when the only reliable hook is the text on the page or a relationship CSS can't express.

What makes a selector good in a real scraper

Selector Golf rewards the shortest answer, but production scrapers reward the most stable one. Prefer hooks that carry meaning, such as ids, data-* attributes and semantic class names. Avoid long positional chains like div > div:nth-child(3) > span, which break the next time the layout changes. Auto-generated class names such as css-1x2y3z change on every deploy, so match a nearby stable attribute instead.

To put selectors to work, start with web scraping with Python or web scraping with Node.js, then handle pagination to walk through multi-page results. For pages built with JavaScript, the Playwright guide covers waiting for elements before you select them.

FAQ

Should I use CSS selectors or XPath for web scraping?

Start with CSS selectors. They are shorter, easier to read and supported by nearly every scraping library. Reach for XPath when you need something CSS can't express, such as matching an element by its text or stepping up to a parent element.

Is a shorter selector always better?

Not in production. Selector Golf rewards short selectors because it is a game. In a real scraper, prefer selectors tied to stable, meaningful hooks such as ids, data attributes or semantic classes, because they survive redesigns better than short positional selectors.

Is anything I type sent to a server?

No. The game parses each hole and runs your selector entirely in your browser. Your best scores are saved in your browser's local storage, and the game still works if storage is blocked.

Runs entirely in your browser. Nothing you type is sent anywhere.