What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use CSS selectors when a stable ID, class, attribute, child, or descendant relationship identifies the data directly. Use XPath when the query must navigate to a parent, ancestor, preceding sibling, or a predicate-heavy path. Neither language is universally faster: support and performance depend on the parser, browser engine, version, and workload.
This guide shows how the choice works in real Scrapy, Beautiful Soup, and browser-DOM code, how to avoid brittle selectors, and how to test the result before deploying a scraper.
CSS selectors and XPath solve overlapping problems
Both languages describe nodes in an HTML or XML tree. CSS uses selectors and combinators; XPath uses location paths, axes, and predicates. A direct match is usually shorter in CSS, while a relationship that requires moving from one node to another is often clearer in XPath.
| Task | CSS is a good fit when… | XPath is a good fit when… |
|---|---|---|
| ID, class, or attribute | A stable attribute identifies the target directly. | The target is part of a longer path or predicate. |
| Child or descendant | > or whitespace expresses the relationship clearly. |
A path expression is easier to read in your host tool. |
| Related node | A supported feature such as :has() expresses the condition clearly. |
You need parent, ancestor, preceding-sibling, or another explicit axis. |
| Text or attributes | The library supplies an extraction API (Scrapy adds ::text and ::attr(name)). |
The API supports node, text, and attribute expressions directly. |
| Speed | Only after measuring your actual parser and workload. | Only after measuring your actual parser and workload. |
Modern CSS overlaps some formerly XPath-only patterns. MDN’s comparison maps XPath’s ancestor, parent, and preceding-sibling axes to CSS features such as :has(), attribute selectors, combinators, and :scope/:host. Browser and parser support is version-specific, so treat that mapping as a guide, not a compatibility guarantee.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
Choose by the relationship your data requires
Start with stable, meaningful hooks
Prefer a documented ID, data attribute, semantic element, or stable class over generated class names and positional assumptions. A selector such as [data-product-id] communicates intent and survives layout changes better than div:nth-child(7). Confirm that the attribute is actually present in the HTML returned to your scraper; client-side rendering may add it later.
Use CSS for direct structure
CSS is concise for common patterns:
#mainmatches an ID.article.cardmatches an element with both a tag and class.nav amatches descendant links.ul.items > lirequires a direct child.a[href^="/docs/"]matches an attribute prefix..price + .currencymatches an adjacent sibling.
Switch to XPath for explicit navigation
XPath is useful when the value is defined by another node’s position or text. For example, to get the price from the product card whose heading is “Keyboard,” an XPath predicate can select the heading, move to its ancestor card, and then find the price descendant. Axes such as parent::, ancestor::, and preceding-sibling:: make that movement explicit.
XPath 3.1 is a W3C recommendation for addressing XML and JSON trees, but a scraping library or browser may implement only a subset or an older version. The label “XPath” does not promise identical functions across tools.
Scrapy: two selector APIs in one response
Scrapy 2.19.0 exposes both response.css() and response.xpath(). Its documentation says CSS queries are translated to XPath with cssselect. Scrapy/parsel also adds non-standard pseudo-elements for scraping:
Free tools Windows power users keep installed
One-click scans. No signup required.
::textselects text nodes.::attr(name)selects an attribute value..get()returns one result (the first when several match)..getall()returns every result.
Those pseudo-elements are Scrapy extensions, not standard CSS syntax. Keep them inside Scrapy code rather than copying them to a browser or another parser.
Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
import scrapy
class ProductsSpider(scrapy.Spider):
name = "products"
start_urls = ["https://example.com/catalog"]
def parse(self, response):
for card in response.css("article[data-product-id]"):
yield {
"id": card.css("::attr(data-product-id)").get(),
"name": card.css("h2::text").get(),
"url": response.urljoin(card.css("a.details::attr(href)").get()),
"price": card.xpath(".//span[contains(@class, 'price')]/text()").get(),
}
# A preceding-sibling relationship is often clearer in XPath.
note = response.xpath("//h2[normalize-space()='Shipping']/preceding-sibling::p[1]/text()").get()
if note:
yield {"shipping_note": note.strip()}
Use a relative XPath beginning with . when querying a selected card; without it, the expression can search the entire document and return the wrong node.
Beautiful Soup: CSS through Soup Sieve, plus tree searches
Beautiful Soup 4.14.3 implements CSS selection through Soup Sieve. Use select() for all matches and select_one() for the first. The library also provides its own tree-search methods, which can be clearer when matching a tag, attribute, or callable.
import requests
from bs4 import BeautifulSoup
html = requests.get("https://example.com/catalog", timeout=30).text
soup = BeautifulSoup(html, "html.parser")
for card in soup.select("article[data-product-id]"):
title = card.select_one("h2")
link = card.select_one("a.details[href]")
print({
"id": card.get("data-product-id"),
"name": title.get_text(" ", strip=True) if title else None,
"url": link.get("href") if link else None,
})
Beautiful Soup’s documentation recommends parsing with lxml when CSS selectors are all you need, describing that as its guidance for this use case rather than a universal benchmark. Parser choice, document size, and selector complexity can change the result. If you need XPath specifically, use a parser/API that exposes it instead of assuming Soup Sieve does.
Browser DOM XPath and CSS
In browser JavaScript, document.querySelectorAll() and document.querySelector() provide CSS selection. MDN documents Document.evaluate() for XPath:
const cards = document.querySelectorAll('article[data-product-id]');
const price = cards[0]?.querySelector('.price')?.textContent.trim();
const result = document.evaluate(
"//h2[normalize-space()='Shipping']/preceding-sibling::p[1]",
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
const shippingNote = result.singleNodeValue?.textContent.trim();
A browser API is not the same thing as a static parsing library. If your scraper runs in Playwright, Selenium, or another automation framework, verify the framework’s selector syntax, frame handling, shadow-DOM behavior, and version before deploying.
Rank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
Text, whitespace, and attributes need deliberate extraction
“Selecting the element” and “extracting the value” are separate steps. HTML often splits visible text across nested tags, inserts whitespace, or stores the real URL in an attribute. Normalize only after selecting the intended node.
- In Beautiful Soup, use
get_text(" ", strip=True)to join descendant text predictably. - In Scrapy, choose
::textfor direct text or::attr(href)for an attribute, then callstrip()where appropriate. - In XPath,
string(.)gathers descendant text, while@hrefselects an attribute. Usenormalize-space()when surrounding or repeated whitespace is irrelevant. - Resolve relative links against the response URL; do not assume every
hrefis absolute.
Scrapy’s selector documentation notes: “Per W3C standards, CSS selectors do not support selecting text nodes or attribute values.” Scrapy’s ::text and ::attr(name) are implementation extensions that address this scraping need.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchA repeatable decision process
- Inspect the returned HTML. Save the response or DOM snapshot and identify the smallest stable hook.
- Write the simplest direct selector. Try an ID, data attribute, class, child, or descendant CSS selector.
- Check the relationship. If the value depends on an ancestor, parent, or preceding sibling, try a relative XPath or a supported CSS relational selector.
- Check the host API. Confirm support for pseudo-classes, namespaces, XPath functions, frames, and shadow roots in the exact library version.
- Validate cardinality. Assert the expected number of matches, and decide whether zero, one, or many is valid.
- Test representative pages. Include missing fields, reordered cards, pagination, localization, and an error page.
- Measure only if it matters. Benchmark the parser, selector, document size, and concurrency used in production; do not transfer a result from another engine.
Common failures and fixes
The selector returns nothing
The content may be rendered by JavaScript, inside an iframe, or absent from the HTTP response. Save the response, inspect it, and either call the underlying data endpoint (where permitted) or use a browser automation context. For an iframe, switch to that frame before selecting. For shadow DOM, use the framework’s shadow-root API.
It works in DevTools but not in the scraper
DevTools inspects the live, mutated DOM; a static request sees the original response. Compare the two snapshots. Wait for the required selector or network activity in a browser workflow, or locate the server-rendered/API source.
Too many or wrong matches
Scope the query to a container, use a direct-child combinator or relative XPath, and assert cardinality. Avoid broad selectors such as div span when a semantic element or data attribute exists.
Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
Text is empty or duplicated
The visible text may be in descendants, generated by CSS, or split by nested markup. Gather descendant text deliberately, normalize whitespace once, and do not confuse an accessibility label or pseudo-element with source text.
A modern selector throws an error
Check the parser or browser version. Replace an unsupported feature with a simpler relationship or XPath, and add a compatibility test so an upgrade does not silently change extraction.
Speed differs between implementations
Scrapy’s CSS-to-XPath translation and Beautiful Soup’s lxml recommendation describe specific implementations, not a universal ranking. Profile parsing, network time, rendering, and extraction separately; selector time may be a small part of the total.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup: ScreenshotNeo
If your goal is a reliable visual capture rather than DOM extraction, ScreenshotNeo provides a single website-screenshot API call. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response reports the result in X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for all options. The same request in Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
And in Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
It also supports full-page and element capture, dark mode, device presets and arbitrary viewports, retina scale, PDF paper and page-range controls, HTML/CSS-to-image, custom CSS and JavaScript, clicks, selector waits, delays, network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, selectable cache TTLs, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work, easing migration.
Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
| Plan | Included shots | Price |
|---|---|---|
| Free | 1,000 per month | $0, no card |
| Starter | 3,000 | $5 |
| Growth | 15,000 | $15 |
| Pro | 60,000 | $39 |
| Scale | 250,000 | $99 |
| Business | 1,000,000 | $249 |
Every feature is on every plan, and yearly billing gives two months free. Start with 1,000 screenshots a month free, with no card required.
Further learning
Web Scraping with Python, 3rd Edition by Ryan Mitchell (O’Reilly Media, February 2024) is a 352-page intermediate-to-advanced book whose contents include CSS, XPath, and selectors. It is broader than a selector reference, but useful for building a complete Python scraping workflow.
Frequently Asked Questions
Can I mix CSS and XPath in one scraper?
Yes. Use whichever expression is clearest for each field, provided your framework exposes both APIs and you keep extraction and validation consistent.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesShould I rewrite every CSS selector as XPath for consistency?
No. Consistency matters less than a stable, understandable query that the installed engine supports. Document the reason for an unusual selector instead.
Does XPath work on JSON?
XPath 3.1 addresses XML and JSON trees, but scraping libraries and browser APIs may implement older or narrower subsets. Verify the actual host tool before relying on JSON features.
Is a selector enough to scrape a JavaScript application?
Only if the needed nodes exist in the HTML or rendered DOM you are querying. Otherwise obtain permitted structured data or render the page in an appropriate browser context.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

