D4Vinci/Scrapling · error · ValueError

Invalid hostname for the CDP URL

Error message

Invalid hostname for the CDP URL

What it means

Returned by _is_invalid_cdp_url (and raised as ValueError from __post_init__) when the URL has a valid scheme but urlparse finds an empty network location — i.e. no host. Example: 'ws:///path' has no hostname. Marked pragma: no cover because it is an edge case rarely hit in practice.

Source

Thrown at scrapling/engines/_browsers/_validators.py:112

    dns_over_https: bool = False

    def __post_init__(self):  # pragma: no cover
        """Custom validation after msgspec validation"""
        if self.page_action and not callable(self.page_action):
            raise TypeError(f"page_action must be callable, got {type(self.page_action).__name__}")
        if self.page_setup and not callable(self.page_setup):
            raise TypeError(f"page_setup must be callable, got {type(self.page_setup).__name__}")
        if self.proxy and self.proxy_rotator:
            raise ValueError(
                "Cannot use 'proxy_rotator' together with 'proxy'. "
                "Use either a static proxy or proxy rotation, not both."
            )
        if self.proxy:
            self.proxy = construct_proxy_dict(self.proxy)
        if self.cdp_url:
            cdp_msg = _is_invalid_cdp_url(self.cdp_url)
            if cdp_msg:
                raise ValueError(cdp_msg)

        if not self.cookies:
            self.cookies = []
        if not self.extra_flags:
            self.extra_flags = []
        if not self.selector_config:
            self.selector_config = {}
        if not self.additional_args:
            self.additional_args = {}
        if not self.capture_xhr:
            self.capture_xhr = None

        if self.init_script is not None:
            validation_msg = _is_invalid_file_path(self.init_script)
            if validation_msg:
                raise ValueError(validation_msg)

        if self.executable_path is not None:

View on GitHub (pinned to 5d213a2d47)

Solutions

  1. Include the host (and usually port): ws://127.0.0.1:9222/devtools/browser/<id>
  2. Double-check URL construction code for empty host placeholders

Example fix

// before
session = StealthySession(cdp_url='ws:///devtools/browser/abc')

// after
session = StealthySession(cdp_url='ws://127.0.0.1:9222/devtools/browser/abc')
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse
p = urlparse(cdp_url)
assert p.netloc, 'cdp_url must include a host'

Type guard

def cdp_url_has_host(u: str) -> bool:
    from urllib.parse import urlparse
    return bool(urlparse(u).netloc)

Prevention

When it happens

Trigger: Passing a CDP URL like 'wss://' or 'ws:///devtools/browser/id' where the authority component (host[:port]) is missing.

Common situations: Programmatically building the CDP URL and dropping the host segment, or string-formatting bugs that leave the netloc empty.

Related errors


AI-assisted analysis of D4Vinci/Scrapling@5d213a2d47 (2026-08-14). Data as JSON: /api/errors/75bee054cfddc89f. Report an issue: GitHub.