pypa/pip · error · InvalidProxyURL

Please check proxy URL. It is malformed and could be missing

Error message

Please check proxy URL. It is malformed and could be missing the host.

What it means

In the modern get_connection_with_tls_context path, after a proxy is selected and given an 'http' scheme prefix, Requests parses it with urllib3 parse_url and raises InvalidProxyURL if the resulting URL has no host component. This means the proxy string is structurally malformed (missing host), not merely unreachable.

Source

Thrown at src/pip/_vendor/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 d7d0d0a394)

Solutions

  1. Correct the proxy URL to include a host, e.g. 'http://proxy.example.com:8080'.
  2. Unset the malformed HTTP_PROXY/HTTPS_PROXY/ALL_PROXY env var if no proxy is intended.
  3. Validate the proxy string with urllib3.util.parse_url and confirm .host is set before passing it to requests.

Example fix

# before
proxies = {'http': 'http://:8080'}
requests.get(url, proxies=proxies)

# after
proxies = {'http': 'http://proxy.internal:8080'}
requests.get(url, proxies=proxies)
Defensive patterns

Strategy: validation

Validate before calling

from pip._vendor.urllib3.util import parse_url
pu = parse_url(prepend_scheme_if_needed(proxy, 'http'))
if not pu.host:
    raise ValueError(f'proxy URL is missing a host: {proxy!r}')

Try / catch

from pip._vendor.requests.exceptions import InvalidProxyURL
try:
    resp = session.get(url, proxies=proxies)
except InvalidProxyURL:
    proxies = clean_proxy_config(proxies)
    resp = session.get(url, proxies=proxies)

Prevention

When it happens

Trigger: Passing a proxies dict whose value parses to a hostless URL, e.g. 'http://', 'http://:8080', or '//' ; calling requests with proxies={'http':'http://'} ; or a SELECTED_PROXY env var that resolves to an empty host. Reached via send() on Requests >= 2.32.2.

Common situations: Empty or malformed HTTP_PROXY/HTTPS_PROXY env vars; proxy strings built by concatenation that dropped the host; config templating that produced 'http://:port'; uppercase proxy env vars with stray characters.

Related errors


AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04). Data as JSON: /data/errors/46886a8b6373dd64.json. Report an issue: GitHub.