psf/requests · error · InvalidProxyURL
Please check proxy URL. It is malformed and could be…
Error message
Please check proxy URL. It is malformed and could be missing the host.
What it means
Raised when a proxy is selected for the request but parse_url(proxy) yields no host component. The code prepends an http:// scheme if missing, parses the result, and rejects it as an InvalidProxyURL if proxy_url.host is falsy. This guards against proxy strings like "://", "http://", or bare credentials with no host before any connection is attempted.
Solutions
- Validate the proxy string has a host before assigning it: parse with urllib3.util.parse_url and check .host.
- Clear empty proxy env vars (unset HTTP_PROXY when not needed) rather than leaving them blank.
- Normalize proxy config through a single helper that rejects malformed entries at startup.
- For per-request bypass, set proxies={'http': None, 'https': None} rather than an empty string.
- Log the resolved proxy at DEBUG in your session wrapper so malformed values are visible.
Example fix
# before
proxies = {"https": "http://"} # -> InvalidProxyURL
requests.get("https://example.com", proxies=proxies)
# after
from urllib3.util import parse_url
p = "http://proxy.local:8080"
assert parse_url(p).host, f"bad proxy: {p}"
requests.get("https://example.com", proxies={"https": p}) Defensive patterns
Strategy: validation
Validate before calling
from urllib3.util import parse_url
def normalize_proxies(proxies: dict | None) -> dict | None:
"""Drop/fix proxy entries whose parsed host is empty."""
if not proxies:
return proxies
out = {}
for scheme, proxy in proxies.items():
if proxy is None:
out[scheme] = None # explicit bypass
continue
if not parse_url(proxy).host:
raise ValueError(f"proxy for {scheme} has no host: {proxy!r}")
out[scheme] = proxy
return out
requests.get(url, proxies=normalize_proxies(proxies)) Type guard
from urllib3.util import parse_url
def is_well_formed_proxy(proxy) -> bool:
if proxy is None:
return True
if not isinstance(proxy, str) or not proxy:
return False
return bool(parse_url(proxy).host) Try / catch
import requests.exceptions as exc
try:
resp = session.get(url, proxies=proxies)
except exc.InvalidProxyURL as e:
raise ValueError(
f"misconfigured proxy {proxies!r}: missing host"
) from e Prevention
- Validate proxy strings at config load time, not at request time. Unset empty HTTP_PROXY/HTTPS_PROXY env vars rather than leaving them blank. Use None to bypass a proxy per-scheme, not an empty string. Centralize proxy configuration so malformed values are caught once.
When it happens
Trigger: Triggered inside send (the modern path) when proxies maps a scheme to a proxy string that parses to an empty host, e.g. proxies={'http': ''}, {'http': 'http://'}, {'https': ':8080'}, or a malformed value from HTTP_PROXY env var. The check runs only when select_proxy returns a non-empty proxy.
Common situations: Seen when HTTP_PROXY/HTTPS_PROXY env vars are set to empty or malformed values in CI, when a config file writes a proxy with a typo, when an empty proxy string is intentionally used to bypass but is malformed, or when proxy parsing of a socks URL occurs without the socks extra (though that path raises InvalidSchema separately).
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Invalid timeout . Pass a (connect, read) timeout tuple, or…
- Unsupported event specified, with event name
- Could not find a suitable TLS CA certificate bundle…
- Could not find the TLS certificate file, invalid path
- Could not find the TLS key file, invalid path
AI-assisted analysis of psf/requests@8068356288 (2026-08-11).
Data as JSON: /api/errors/825b20b7267f0bd1.
Report an issue: GitHub.
Appendix: source
Thrown at src/requests/adapters.py:496
:rtype:
urllib3.HTTPConnectionPool
"""
assert _is_prepared(request)
proxy = select_proxy(request.url, proxies)
try:
host_params, pool_kwargs = self.build_connection_pool_key_attributes(
request,
verify,
cert,
)
except ValueError as e:
raise InvalidURL(e, request=request)
if proxy:
proxy = prepend_scheme_if_needed(proxy, "http")
proxy_url = parse_url(proxy)
if not proxy_url.host:
raise InvalidProxyURL(
"Please check proxy URL. It is malformed "
"and could be missing the host."
)
proxy_manager = self.proxy_manager_for(proxy)
conn = proxy_manager.connection_from_host(
**host_params, pool_kwargs=pool_kwargs
)
else:
# Only scheme should be lower case
conn = self.poolmanager.connection_from_host(
**host_params, pool_kwargs=pool_kwargs
)
return conn
def get_connection(
self, url: str, proxies: dict[str, str] | None = None
) -> HTTPConnectionPool:View on GitHub (pinned to 8068356288)