What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Elebase USB to USB C Adapter for iPhone 18 Pro Max,USBC Car Charger Adapter
  • 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:

  • #main matches an ID.
  • article.card matches an element with both a tag and class.
  • nav a matches descendant links.
  • ul.items > li requires a direct child.
  • a[href^="/docs/"] matches an attribute prefix.
  • .price + .currency matches 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • ::text selects 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
Anker USB-C Hub, 5-in-1 USB Hub for Laptops, 4K HDMI Multiport Adapter
  • 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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
Sale
Anker USB C Hub, 7in1 Multi-Port USB Adapter, 4K@60Hz USBC to HDMI Splitter
  • 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 ::text for direct text or ::attr(href) for an attribute, then call strip() where appropriate.
  • In XPath, string(.) gathers descendant text, while @href selects an attribute. Use normalize-space() when surrounding or repeated whitespace is irrelevant.
  • Resolve relative links against the response URL; do not assume every href is 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A repeatable decision process

  1. Inspect the returned HTML. Save the response or DOM snapshot and identify the smallest stable hook.
  2. Write the simplest direct selector. Try an ID, data attribute, class, child, or descendant CSS selector.
  3. Check the relationship. If the value depends on an ancestor, parent, or preceding sibling, try a relative XPath or a supported CSS relational selector.
  4. Check the host API. Confirm support for pseudo-classes, namespaces, XPath functions, frames, and shadow roots in the exact library version.
  5. Validate cardinality. Assert the expected number of matches, and decide whether zero, one, or many is valid.
  6. Test representative pages. Include missing fields, reordered cards, pagination, localization, and an error page.
  7. 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
Sale
UGREEN USB to USB C Adapter Combo 4-Pack, 10Gbps USB C Converter Space Gray
  • 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.Support on Ko-Fi

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:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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
Anker USB C Hub, 5-in-1 USBC to HDMI Splitter with 4K Display
  • 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should 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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.