D4Vinci/Scrapling · error · ValueError

The proxy argument's string is in invalid format!

Error message

The proxy argument's string is in invalid format!

What it means

Raised inside the `try` block of `construct_proxy_dict` where the parsed proxy pieces are assembled into the Playwright dict. It is the ValueError handler for cases where urllib cannot coerce URL components (classically the port when accessed). In practice this branch is nearly dead code because the f-string assembly rarely raises ValueError, but it exists to convert low-level urllib failures into a clear message about the proxy string format.

Source

Thrown at scrapling/engines/toolbelt/navigation.py:120

    :return:
    """
    if isinstance(proxy_string, str):
        proxy = urlparse(proxy_string)
        if proxy.scheme not in ("http", "https", "socks4", "socks5") or not proxy.hostname:
            raise ValueError("Invalid proxy string!")

        try:
            result = {
                "server": f"{proxy.scheme}://{proxy.hostname}",
                "username": proxy.username or "",
                "password": proxy.password or "",
            }
            if proxy.port:
                result["server"] += f":{proxy.port}"
            return result
        except ValueError:
            # Urllib will say that one of the parameters above can't be casted to the correct type like `int` for port etc...
            raise ValueError("The proxy argument's string is in invalid format!")

    elif isinstance(proxy_string, dict):
        try:
            validated = convert(proxy_string, ProxyDict)
            result_dict = structs.asdict(validated)
            return result_dict
        except ValidationError as e:
            raise TypeError(f"Invalid proxy dictionary: {e}")

    raise TypeError(f"Invalid proxy string: {proxy_string}")

View on GitHub (pinned to 5d213a2d47)

Solutions

  1. Verify the port is numeric: 'http://proxy:8080', not 'http://proxy:80tl'.
  2. URL-encode credentials containing special characters (@, :, /) before embedding them.
  3. Test the URL with `urllib.parse.urlsplit(...).port` in a REPL to confirm every component resolves.
  4. Switch to the dict form {'server': 'http://proxy:8080', 'username': ..., 'password': ...} to bypass string parsing entirely.

Example fix

# before
proxy = "http://user:p@ss@proxy:8080"  # raw '@' breaks parsing

# after
from urllib.parse import quote
proxy = f"http://{quote('user', safe='')}:{quote('p@ss', safe='')}@proxy:8080"
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlsplit

def proxy_components_resolve(p: str) -> bool:
    try:
        u = urlsplit(p)
        _ = u.port, u.hostname, u.username, u.password
        return u.scheme in ("http", "https", "socks4", "socks5") and u.hostname is not None
    except ValueError:
        return False

Type guard

def is_resolvable_proxy_url(value: object) -> bool:
    return isinstance(value, str) and proxy_components_resolve(value)

Try / catch

try:
    fetcher.fetch(url, proxy=proxy)
except ValueError as e:
    if "invalid format" in str(e):
        log.warning("proxy %r has unresolvable components; url-encode credentials", proxy)
    raise

Prevention

When it happens

Trigger: Passing a proxy string that parses (valid scheme + hostname) but whose components blow up when formatted, e.g. a malformed port segment such as 'http://proxy:notaport' on Python versions where `proxy.port` access raises, or other degenerate URL component encodings.

Common situations: Hand-built proxy URLs with non-numeric ports, unencoded special characters in userinfo, or exotic IPv6/hostname forms that urlparse accepts but cannot fully resolve.

Related errors


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