unclecode/crawl4ai · error · InvalidCSSSelectorError

Invalid CSS selector, No elements found for CSS selector: {c

Error message

Invalid CSS selector, No elements found for CSS selector: {css_selector}

What it means

Raised as InvalidCSSSelectorError by get_content_of_website_optimized (crawl4ai/utils.py:1184) when the css_selector argument matches no elements after excluded_tags decomposition. Distinct from 140/141 in that it fires in the 'optimized' extraction path, and importantly the exclusion step runs first — so a selector can legitimately match in the raw HTML but still fail because excluded_tags decomposed the matched nodes beforehand.

Source

Thrown at crawl4ai/utils.py:1184

    """
    if not html:
        return None

    soup = BeautifulSoup(html, "html.parser")
    body = soup.body

    image_description_min_word_threshold = kwargs.get(
        "image_description_min_word_threshold", IMAGE_DESCRIPTION_MIN_WORD_THRESHOLD
    )

    for tag in kwargs.get("excluded_tags", []) or []:
        for el in body.select(tag):
            el.decompose()

    if css_selector:
        selected_elements = body.select(css_selector)
        if not selected_elements:
            raise InvalidCSSSelectorError(
                f"Invalid CSS selector, No elements found for CSS selector: {css_selector}"
            )
        body = soup.new_tag("div")
        for el in selected_elements:
            body.append(el)

    links = {"internal": [], "external": []}
    media = {"images": [], "videos": [], "audios": []}

    # Extract meaningful text for media files from closest parent
    def find_closest_parent_with_useful_text(tag):
        current_tag = tag
        while current_tag:
            current_tag = current_tag.parent
            # Get the text content from the parent tag
            if current_tag:
                text_content = current_tag.get_text(separator=" ", strip=True)
                # Check if the text content has at least word_count_threshold

View on GitHub (pinned to 7e80152142)

Solutions

  1. Check for overlap between css_selector and excluded_tags and remove the conflict.
  2. Confirm the selector matches in the exact HTML passed (static markup, pre-JS).
  3. Pre-validate with BeautifulSoup: BeautifulSoup(html,'html.parser').body.select(sel) before calling the API.
  4. Catch InvalidCSSSelectorError and retry without css_selector to get full-page content as a fallback.

Example fix

# before
res = get_content_of_website_optimized(url, html, css_selector="div.ads + div.content", excluded_tags=["div"])

# after
res = get_content_of_website_optimized(url, html, css_selector="div.content", excluded_tags=["script", "style"])
Defensive patterns

Strategy: validation

Validate before calling

def safe_extract_optimized(html, css_selector, excluded_tags):
    if css_selector:
        sel_soup = BeautifulSoup(html, "html.parser")
        for tag in excluded_tags or []:
            for el in sel_soup.select(tag):
                el.decompose()
        if not (sel_soup.body or sel_soup).select(css_selector):
            return None  # would raise; caller falls back
    return get_content_of_website_optimized(
        "local", html, css_selector=css_selector, excluded_tags=excluded_tags
    )

Try / catch

try:
    res = get_content_of_website_optimized(url, html, css_selector=sel, excluded_tags=ex)
except InvalidCSSSelectorError:
    res = get_content_of_website_optimized(url, html, excluded_tags=ex)

Prevention

When it happens

Trigger: Calling get_content_of_website_optimized(url, html, css_selector="nav.menu") with excluded_tags=["nav"] (the selector's own match is decomposed); a selector matching only <script>/<form> nodes when those tags are excluded; same no-match cases as 140 on optimized path.

Common situations: Passing excluded_tags that overlap the css_selector target; configuration drift between the exclusion list and the extraction selector; SPA static-HTML mismatch as in 140.

Related errors


AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14). Data as JSON: /api/errors/f015ed8da875edc8. Report an issue: GitHub.