Install & Compatibility
Where this runs
tested against v0.9.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.022s · 18.2MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 1.7s · import 0.018s · 19MB
16MB installed
● package 16MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
Matcher
✓ from cssselect2 import Matcher
ElementWrapper
✓ from cssselect2 import ElementWrapper
✗ cssselect2.ElementWrapper(etree_element, parent, index, previous, in_html_document)
ElementWrapper should not be instantiated directly. Use `ElementWrapper.from_xml_root()` or `ElementWrapper.from_html_root()` for document roots, and access other elements via wrapper methods like `iter_children()` or `iter_subtree()`.
compile_selector_list
✓ from cssselect2 import compile_selector_list
This quickstart demonstrates the core workflow of `cssselect2`. It involves parsing a CSS stylesheet using `tinycss2`, compiling its selectors into a `cssselect2.Matcher` object, parsing an HTML document with an ElementTree-like parser, wrapping the root element in `cssselect2.ElementWrapper`, and then iterating through the wrapped elements to find matching CSS rules.
from xml.etree import ElementTree
import cssselect2
import tinycss2
# 1. Parse CSS and add rules to the matcher
matcher = cssselect2.Matcher()
css_rules = tinycss2.parse_stylesheet('p { color: blue; } body p { background: red; }', skip_whitespace=True)
for rule in css_rules:
if rule.type == 'qualified-rule': # Handle only actual CSS rules
selectors = cssselect2.compile_selector_list(rule.prelude)
payload = (tinycss2.serialize(rule.prelude), tinycss2.serialize(rule.content))
for selector in selectors:
matcher.add_selector(selector, payload)
# 2. Parse HTML and wrap the tree
html_content = '''
<html>
<body>
<div>
<p class="intro">Hello <span>World</span>!</p>
<p>Another paragraph.</p>
</div>
</body>
</html>
'''
html_tree = ElementTree.fromstring(html_content)
wrapper = cssselect2.ElementWrapper.from_html_root(html_tree)
# 3. Find CSS rules applying to each tag
print('Matching CSS rules:')
for element in wrapper.iter_subtree():
tag = element.etree_element.tag.split('}')[-1] # Handle namespaces if present
matches = matcher.match(element)
if matches:
print(f' Tag "{tag}" matches:')
for match in matches:
specificity, order, pseudo_type, payload = match
selector_string, content_string = payload
print(f' - Selector: "{selector_string}" (Declarations: "{content_string}")')
Debug
Known issues
breakingSupport for older Python versions is regularly dropped. Version 0.9.0 dropped Python 3.9 support, and previous versions (0.8.0, 0.5.0, 0.4.0) have also removed support for Python 3.8, 3.6, and 3.5 respectively. Ensure your environment uses a supported Python version (currently >=3.10 for 0.9.0).fixUpgrade your Python environment to a version officially supported by `cssselect2` (e.g., Python 3.10+ for `cssselect2` 0.9.0) before upgrading the library.
affects: 0.4.0, 0.5.0, 0.8.0, 0.9.0
deprecatedThe `iter_ancestors` and `iter_previous_siblings` methods on `ElementWrapper` were deprecated in version 0.6.0 and removed in 0.7.0. Attempting to call these methods will result in an AttributeError.fixReplace calls to `element.iter_ancestors()` with `element.ancestors` and `element.iter_previous_siblings()` with `element.previous_siblings`. These are now properties returning tuples.
affects: 0.6.0, 0.7.0+
gotchaWhen working with `ElementWrapper` objects, it's crucial not to instantiate them directly. Doing so can lead to unexpected behavior and may not correctly establish the necessary parent/sibling relationships for selector matching.fixAlways use factory methods like `cssselect2.ElementWrapper.from_xml_root(element)` or `cssselect2.ElementWrapper.from_html_root(element)` to create the initial `ElementWrapper` for the document's root element. Other elements should be accessed through the methods provided by the `ElementWrapper` itself (e.g., `iter_children()`, `iter_subtree()`).
affects: All
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'cssselect2'
The `cssselect2` library has not been installed in the active Python environment.
fixInstall the library using pip: `pip install cssselect2`
cssselect2.parser.SelectorError: (<FunctionBlock url( … )>, 'expected a compound selector, got function')
This error occurs when the provided CSS selector string is syntactically incorrect or attempts to use features (like `@import url(...)`) that are not valid for element selection in `cssselect2`.
fixReview the CSS selector for syntax errors. Ensure the selector adheres to valid CSS selector syntax for selecting elements within a document. For example, `cssselect2` is for selecting elements, not parsing entire CSS stylesheets with directives like `@import`.
AttributeError: 'ElementTree' object has no attribute 'getiterator'
This error typically arises when `cssselect2` (or the code interacting with it) is used with `xml.etree.ElementTree` in Python 3.9 or later, where the `getiterator()` method was removed.
fixEnsure `cssselect2` is updated to its latest version (`pip install --upgrade cssselect2`). If directly manipulating `ElementTree` objects, replace deprecated methods like `getiterator()` with the modern `iter()` method.
Upgrade
Version history
0.9.0latest on PyPI · released Feb 12, 2026
Audit
Dependencies
tinycss2requiredRequired for parsing CSS stylesheets and component values.
webencodingsrequiredRequired for character encoding detection in HTML parsing contexts.