D4Vinci/Scrapling · error · TypeError

Invalid proxy dictionary: {e}

Error message

Invalid proxy dictionary: {e}

What it means

Raised when the `proxy` argument is a dict but it fails schema validation: scrapling converts it to a `ProxyDict` structure (via msgspec-style `convert`) and re-raises the `ValidationError` as a TypeError. The dict is expected to have exactly the keys 'server', 'username', and 'password'. Any missing required key, wrong value type, or unexpected/unknown key makes validation fail.

Source

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

            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. Provide all three keys with string values: {'server': 'http://host:port', 'username': 'user', 'password': 'pass'}.
  2. If auth is not needed, still include 'username': '' and 'password': '' — check the ProxyDict definition for which fields are optional.
  3. Remove requests-style keys like 'http'/'https' and any extra keys not in the schema.
  4. Include the original ValidationError text (it is embedded in the message) to see exactly which field failed.

Example fix

# before
proxy = {"http": "http://proxy:8080"}

# after
proxy = {"server": "http://proxy:8080", "username": "user", "password": "pass"}
Defensive patterns

Strategy: validation

Validate before calling

def is_valid_proxy_dict(d: dict) -> bool:
    return (
        isinstance(d, dict)
        and isinstance(d.get("server"), str)
        and all(isinstance(d.get(k, ""), str) for k in ("username", "password"))
    )

assert is_valid_proxy_dict(proxy_dict), proxy_dict

Type guard

from typing import Any

def is_proxy_dict(value: Any) -> bool:
    return isinstance(value, dict) and isinstance(value.get("server"), str)

Try / catch

try:
    fetcher.fetch(url, proxy=proxy_dict)
except TypeError as e:
    if "Invalid proxy dictionary" in str(e):
        raise ConfigError("proxy dict needs server/username/password as strings") from e
    raise

Prevention

When it happens

Trigger: Passing proxy={'server': 'http://p:8080'} (missing username/password), proxy={'server': 8080} (server not a str), proxy={'proxy': '...'} (wrong key name), or including extra keys not in ProxyDict such as {'server': ..., 'bypass': ...}.

Common situations: Copying a requests-style dict ({'http': url, 'https': url}) instead of Playwright style; renaming keys; partial dicts from environment variables or config files where optional keys were dropped.

Related errors


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