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

CSS selectors are patterns that match elements in a document tree. In scraping, you use them after a browser or parser has built that tree to locate tags, classes, IDs, attributes, relationships, and structural positions. A selector does not download a page, execute JavaScript, or guarantee that text visible in a browser exists in the original HTML.

This guide covers selector syntax, browser APIs, Python libraries, dynamic pages, escaping, troubleshooting, and a practical workflow for reliable extraction.

What are CSS selectors?

A selector describes which nodes in an HTML or XML tree should match. Selectors Level 4 defines the syntax used for type, class, ID, attribute, combinator, pseudo-class, and logical selectors. A parser or browser evaluates the selector against the tree it has constructed.

For example, article.product matches an <article> element whose class list includes product. The selector does not care whether the element came from a network response, a template, or script-generated markup; it only sees the tree available to the selecting tool.

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.

CSS selector cheatsheet

Goal Selector What it matches
All paragraphs p Every p element
ID #main The element with ID main
Class .product Elements whose class list includes product
Compound article.product article elements with class product
Descendant article p Paragraphs at any depth inside an article
Direct child ul > li li elements directly inside a ul
Adjacent sibling h2 + p A paragraph immediately following an h2
Subsequent sibling h2 ~ p Paragraph siblings appearing after an h2
Attribute present a[href] Links that have an href attribute
Exact attribute input[type="email"] Inputs whose type is exactly email
Attribute prefix a[href^="https"] Links whose href starts with https
Attribute suffix a[href$=".pdf"] Links whose href ends with .pdf
Attribute substring [data-id*="item"] Elements whose data-id contains item
Multiple alternatives h1, h2, h3 Elements matching any listed branch
First child li:first-child An li that is first among its siblings
Logical alternatives button:is(.primary, .submit) Buttons matching either argument
Relational condition article:has(img) Articles containing a matching image descendant

How combinators change the match

Descendants and children

A space means “at any depth below.” Thus article p also matches paragraphs nested in sections, while article > p matches only paragraphs that are direct children of the article.

Siblings

+ selects the next sibling only. ~ selects later siblings at the same parent level. Whitespace and comments between elements do not make a non-adjacent element adjacent.

Selector lists

Separate alternatives with commas: .price, [data-price], meta[itemprop="price"]. Each branch is evaluated independently; a node matching at least one branch is returned.

Classes, IDs, and attributes

Classes and IDs

Use .name for a class and #name for an ID. A class selector tests the class list, so .card matches an element with classes card featured. Combine conditions without spaces when they apply to one element: div.card.featured. A space would instead mean a descendant.

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

Attribute operators

  • [attr] tests presence.
  • [attr="value"] tests an exact value.
  • [attr~="token"] tests a whitespace-separated token.
  • [attr|="en"] tests an exact value or a hyphen-prefixed value such as en-US.
  • [attr^="start"], [attr$="end"], and [attr*="part"] test prefixes, suffixes, and substrings.

Quote attribute values when they contain punctuation or could be confused with selector syntax. Attribute matching can be case-sensitive or case-insensitive depending on the attribute and document language; verify behavior in your parser.

Pseudo-classes and newer selectors

Pseudo-classes add conditions without changing the selected element type. Structural examples include :first-child, :last-child, and :nth-child(2n). Logical selectors include :is() and :where(). Relational :has() matches an element based on a relative selector, as in article:has(img).

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.

Browser support and non-browser parser support are not identical. A parser may implement only part of the Selectors Level 4 syntax. Test advanced selectors against the exact library and version used in production, and keep a simpler fallback when portability matters.

Pseudo-elements such as ::before and ::after represent rendered abstractions, not ordinary nodes in the document tree. A static HTML parser generally cannot extract their generated content as if it were an element.

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

Using selectors in browser JavaScript

Select the first match

const card = document.querySelector('article.product');
if (card) {
  console.log(card.textContent.trim());
}

querySelector() returns the first matching element or null when there is no match.

Select every match

const links = document.querySelectorAll('a[href^="https"]');
for (const link of links) {
  console.log(link.href);
}

querySelectorAll() returns a static NodeList. Later DOM changes do not automatically add or remove entries from that returned list.

Invalid selectors

Both methods throw a SyntaxError DOMException for malformed selector strings. Validate selectors in the same browser context in which you will run them; a selector accepted by one parser may not be accepted by another.

Escape dynamic identifiers

Never concatenate untrusted or arbitrary data directly after # or .. IDs and class values may contain characters that are not valid CSS identifiers.

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.
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.
const idFromData = 'item:2026/09';
const node = document.querySelector(`#${CSS.escape(idFromData)}`);

CSS.escape() converts a value to a safe identifier. If you are building a selector from user input, also constrain the allowed selector structure rather than allowing arbitrary queries.

CSS selectors in Python scraping libraries

Beautiful Soup

from bs4 import BeautifulSoup

html = open('page.html', encoding='utf-8').read()
soup = BeautifulSoup(html, 'html.parser')

headline = soup.select_one('article h1')
prices = [node.get_text(strip=True) for node in soup.select('[data-price]')]
print(headline.get_text(strip=True) if headline else 'not found')
print(prices)

Beautiful Soup provides select() for all matches and select_one() for the first. Its parser choice affects the tree you query. The Beautiful Soup documentation notes that lxml is faster and supports more selectors when CSS-only querying is the goal; treat that as project guidance, not a universal benchmark.

Scrapy

import scrapy

class ProductSpider(scrapy.Spider):
    name = 'products'
    start_urls = ['https://example.com/catalog']

    def parse(self, response):
        for card in response.css('article.product'):
            yield {
                'name': card.css('h2::text').get(),
                'url': card.css('a[href]::attr(href)').get(),
            }

Scrapy exposes CSS and XPath selectors through its response and selector APIs. Use its current documentation for exact extraction extensions such as text and attribute pseudo-elements.

lxml

from lxml import html

root = html.fromstring(open('page.html', encoding='utf-8').read())
for title in root.cssselect('article.product h2'):
    print(title.text_content().strip())

lxml.cssselect translates CSS selectors to XPath. Check the installed lxml version and dependencies before relying on newer selector constructs.

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

Why does my CSS selector return no results?

  1. Inspect the actual tree. Save the response body and search it for the expected text or attribute. If it is absent, changing the selector cannot create it.
  2. Check JavaScript rendering. A browser may insert content after scripts run. A static HTTP client or parser sees only the original response unless you render the page first.
  3. Check scope and combinators. Replace a deep selector with a simple probe such as document.querySelectorAll('article').length, then add one condition at a time.
  4. Check spelling and class tokens. Class names are space-separated tokens; .product-card is different from .product_card.
  5. Check iframe and shadow DOM boundaries. Content inside an iframe belongs to another document. Shadow roots may require access through the component’s shadow tree.
  6. Check parser support. Replace :has() or another newer feature with a two-step query when your parser does not implement it.
  7. Check malformed syntax. An unmatched bracket, quote, or parenthesis raises a syntax error in browser APIs.
  8. Check hidden versus absent content. CSS can hide an element without removing it from the tree; conversely, generated text in a pseudo-element may never exist as a node.

Designing selectors that survive page changes

  • Prefer stable attributes such as data-testid, data-product-id, or semantic elements over auto-generated class names.
  • Keep selectors as short as possible while remaining specific: [data-product-id] is usually more durable than a chain of layout classes.
  • Use a selector list for known variants, for example h1.product-title, [data-testid="product-title"].
  • Assert cardinality. If one product should be present, fail loudly when the selector returns zero or several unexpected matches.
  • Store representative HTML fixtures and run selector tests against them after template changes.
  • Normalize extracted text and resolve relative URLs after selection; do not encode cleanup assumptions into an overly fragile selector.

When a rendered screenshot is the fastest diagnostic

For pages whose markup changes after JavaScript runs, compare the original response with the rendered browser DOM. A screenshot can reveal consent dialogs, newsletter overlays, lazy-loaded sections, or bot checks that explain why an otherwise correct selector appears empty.

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and each response reports the result through X-Page-Verdict and X-Billed headers. An MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf.

One request returns PNG, JPEG, WebP, or PDF. The API supports full-page and element captures, device presets, retina scale, dark mode, waits, custom CSS and JavaScript, clicks, hidden selectors, 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, usage reporting, and an OpenAPI specification. Common parameter names used by other screenshot APIs also work.

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
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 response headers and options. Equivalent Python and Node.js calls are useful in automated selector-debugging pipelines:

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)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());

The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 shots; yearly billing gives two months free. Create a free ScreenshotNeo account to try it.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability, and cost considerations

Selector matching is normally cheaper than downloading or rendering a page, so the dominant costs in scraping are network requests, browser startup, JavaScript execution, and storage. Narrow selectors reduce the amount of post-processing, but a complex selector is not automatically faster than several simple queries; measure your workload.

For dynamic sites, wait for a specific selector, a fixed delay, or network idle before extracting. Add timeouts and retries around navigation, not around every individual query. Cache fetched pages when permitted, record the URL and retrieval time, and preserve failed HTML or screenshots for diagnosis. Respect site terms, robots policies, authentication requirements, and privacy obligations.

FAQ

Can CSS selectors select text nodes directly?

No. Select an element, then read its text through the browser or library API. Some scraping frameworks provide convenience syntax such as text selectors, but that is an API feature rather than a CSS node type.

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

Are CSS selectors case-sensitive?

It depends on the document language, attribute, and matching mode. Do not assume that casing rules from HTML apply unchanged to XML.

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.

Should I use CSS or XPath?

Use the form your tool supports best. CSS is concise for classes, attributes, and common relationships; XPath can express some axes and text conditions more directly. Scrapy and lxml support both workflows.

Can a selector bypass a login or CAPTCHA?

No. Selectors only query a tree you can access. Authentication, bot challenges, and permissions must be handled separately and lawfully.

Frequently Asked Questions

Can CSS selectors select text nodes directly?

No. Select an element, then read its text through the browser or library API.

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.

Are CSS selectors case-sensitive?

Matching depends on the document language, attribute, and mode; HTML and XML can differ.

Should I use CSS or XPath?

Choose the syntax your library supports and your extraction logic needs; both are available in common scraping frameworks.

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.