CSS Locators in Python 2026: Powerful Web Scraping Techniques
CSS locators (also called CSS selectors) are one of the fastest and most readable ways to locate elements during web scraping. In 2026, with modern async scraping tools and dynamic websites, CSS locators remain the go-to choice for most Python developers due to their simplicity, speed, and maintainability compared to XPath.
This March 24, 2026 guide covers everything you need to know about using CSS locators effectively in Python web scraping with BeautifulSoup, parsel, httpx, and Playwright.
TL;DR — Key Takeaways 2026
- CSS locators are faster and cleaner than XPath in most cases
- Use
.select()or.select_one()in BeautifulSoup - Master combinators, pseudo-classes, and attribute selectors
- Combine with
httpx + asynciofor high-performance crawlers - Prefer data attributes and specific selectors for stability
1. Basic CSS Locators
from bs4 import BeautifulSoup
html = """
MacBook Pro 2026
$2499
"""
soup = BeautifulSoup(html, "html.parser")
# By tag
titles = soup.select("h2")
# By class
prices = soup.select(".price")
# By ID
# soup.select("#main-product")
# By tag + class
products = soup.select("div.product")
print(titles[0].text) # "MacBook Pro 2026"
2. Advanced CSS Locators in 2026
# Child combinator
soup.select("div.product > p.price")
# Descendant combinator
soup.select("div.product .rating")
# Adjacent sibling
soup.select("h2.title + p.price")
# Nth child
soup.select("li:nth-child(odd)")
# Attribute selectors
soup.select('a[href^="https"]')
soup.select('[data-testid="product-card"]')
# Pseudo-classes
soup.select("button:hover")
soup.select("tr:nth-of-type(2n)")
3. Real-World Async Scraping Example
import httpx
from bs4 import BeautifulSoup
async def scrape_page(url: str):
async with httpx.AsyncClient(timeout=15.0) as client:
response = await client.get(url)
soup = BeautifulSoup(response.text, "html.parser")
items = []
for card in soup.select('div[data-product-card]'):
item = {
"title": card.select_one(".title").get_text(strip=True),
"price": card.select_one(".price").get_text(strip=True),
"rating": card.select_one(".rating").get_text(strip=True) if card.select_one(".rating") else None,
"link": card.select_one("a")["href"] if card.select_one("a") else None
}
items.append(item)
return items
# Usage: asyncio.run(scrape_page("https://example.com/products"))
4. Best Practices for CSS Locators in 2026
- Be specific — avoid generic selectors like
divor.item - Prefer data attributes —
[data-testid="..."]is very stable - Use
select_one()when expecting only one element - Handle missing elements gracefully with checks
- Use Playwright when content is rendered by JavaScript
- Document your locators — they will break less often
Conclusion — CSS Locators in 2026
CSS locators continue to be the most elegant and performant way to scrape data from websites in Python. In 2026, combining them with asynchronous requests and modern parsing libraries allows you to build fast, reliable, and maintainable scrapers. Focus on writing clean, specific selectors and always follow ethical scraping practices.
Next steps:
- Practice writing specific CSS locators on real websites
- Related articles: Attributes in CSS Selectors 2026 • Crawl in Python 2026