D4Vinci/Scrapling · error · ValueError
Invalid proxy string!
Error message
Invalid proxy string!
What it means
Raised by `construct_proxy_dict` in scrapling/engines/toolbelt/navigation.py when a proxy passed as a string cannot be parsed into a usable proxy URL. The string is run through `urlparse`, and if the scheme is not one of http/https/socks4/socks5, or the URL has no hostname, the library rejects it before Playwright ever sees it. This is a config-validation error: the proxy string is structurally invalid, not merely unreachable.
Source
Thrown at scrapling/engines/toolbelt/navigation.py:107
else:
await route.continue_()
else:
await route.continue_()
return handler
def construct_proxy_dict(proxy_string: str | Dict[str, str] | Tuple) -> Dict:
"""Validate a proxy and return it in the acceptable format for Playwright
Reference: https://playwright.dev/python/docs/network#http-proxy
:param proxy_string: A string or a dictionary representation of the proxy.
: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)View on GitHub (pinned to 5d213a2d47)
Solutions
- Prefix the proxy string with an explicit supported scheme, e.g. 'http://proxy1:8080' or 'socks5://proxy1:1080'.
- Ensure the string contains a hostname after the scheme (not just credentials or a port).
- If the proxy has auth, embed it as 'scheme://user:pass@host:port'.
- Alternatively pass a Playwright-style dict {'server': ..., 'username': ..., 'password': ...} which skips string parsing.
Example fix
// before proxy = "proxy1:8080" Fetcher.get(url, proxy=proxy) // after proxy = "http://proxy1:8080" Fetcher.get(url, proxy=proxy)
Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
def is_valid_proxy_string(p: str) -> bool:
if not isinstance(p, str):
return False
u = urlparse(p)
return u.scheme in ("http", "https", "socks4", "socks5") and bool(u.hostname)
proxy = "proxy1:8080"
assert is_valid_proxy_string(proxy), f"bad proxy: {proxy!r}" Type guard
def is_proxy_string(value: object) -> bool:
return isinstance(value, str) and is_valid_proxy_string(value) Try / catch
try:
fetcher.fetch(url, proxy=proxy)
except ValueError as e:
if "Invalid proxy string" in str(e):
raise ConfigError(f"proxy {proxy!r} needs scheme+host, e.g. http://host:port") from e
raise Prevention
- Always write proxies as scheme://host[:port]; never host:port alone.
- Centralize proxy normalization in one helper so every entry point validates.
- Validate the pool once at startup instead of per-request.
When it happens
Trigger: Calling a fetcher (e.g. `Fetcher.get(..., proxy=...)`) or `construct_proxy_dict` directly with strings like `"proxy1:8080"` (no scheme), `"http://"` (no hostname), `"ftp://proxy:8080"` (unsupported scheme), or `"user:pass@proxy:8080"` (scheme missing, credentials alone).
Common situations: Proxy vendor sends host:port only; users copy proxy strings from dashboards that omit the scheme; using an ftp or other unsupported scheme; typos like `http//proxy:8080`.
Related errors
- Cannot use 'proxy_rotator' together with 'proxy' or 'proxies
- Invalid proxy dictionary: {e}
- 'quality' is only valid when 'image_type' is 'jpeg'.
- Browser not initialized for proxy rotation mode
- Cannot use 'proxy_rotator' together with 'proxy'. Use either
AI-assisted analysis of D4Vinci/Scrapling@5d213a2d47 (2026-08-14).
Data as JSON: /api/errors/30ff0411e3d1d2c5.
Report an issue: GitHub.