{"record":{"id":"825b20b7267f0bd1","repo":"psf/requests","slug":"please-check-proxy-url-it-is-malformed-and-could","errorCode":null,"errorMessage":"Please check proxy URL. It is malformed and could be missing the host.","messagePattern":"Please check proxy URL\\. It is malformed and could be missing the host\\.","errorType":"exception","errorClass":"InvalidProxyURL","httpStatus":null,"severity":"error","filePath":"src/requests/adapters.py","lineNumber":496,"sourceCode":"        :rtype:\n            urllib3.HTTPConnectionPool\n        \"\"\"\n        assert _is_prepared(request)\n\n        proxy = select_proxy(request.url, proxies)\n        try:\n            host_params, pool_kwargs = self.build_connection_pool_key_attributes(\n                request,\n                verify,\n                cert,\n            )\n        except ValueError as e:\n            raise InvalidURL(e, request=request)\n        if proxy:\n            proxy = prepend_scheme_if_needed(proxy, \"http\")\n            proxy_url = parse_url(proxy)\n            if not proxy_url.host:\n                raise InvalidProxyURL(\n                    \"Please check proxy URL. It is malformed \"\n                    \"and could be missing the host.\"\n                )\n            proxy_manager = self.proxy_manager_for(proxy)\n            conn = proxy_manager.connection_from_host(\n                **host_params, pool_kwargs=pool_kwargs\n            )\n        else:\n            # Only scheme should be lower case\n            conn = self.poolmanager.connection_from_host(\n                **host_params, pool_kwargs=pool_kwargs\n            )\n\n        return conn\n\n    def get_connection(\n        self, url: str, proxies: dict[str, str] | None = None\n    ) -> HTTPConnectionPool:","sourceCodeStart":478,"sourceCodeEnd":514,"githubUrl":"https://github.com/psf/requests/blob/8068356288978c4f54661ae6f95afe0e0831885e/src/requests/adapters.py#L478-L514","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"# before\nproxies = {\"https\": \"http://\"}  # -> InvalidProxyURL\nrequests.get(\"https://example.com\", proxies=proxies)\n\n# after\nfrom urllib3.util import parse_url\np = \"http://proxy.local:8080\"\nassert parse_url(p).host, f\"bad proxy: {p}\"\nrequests.get(\"https://example.com\", proxies={\"https\": p})","handlingStrategy":"validation","validationCode":"from urllib3.util import parse_url\n\ndef normalize_proxies(proxies: dict | None) -> dict | None:\n    \"\"\"Drop/fix proxy entries whose parsed host is empty.\"\"\"\n    if not proxies:\n        return proxies\n    out = {}\n    for scheme, proxy in proxies.items():\n        if proxy is None:\n            out[scheme] = None  # explicit bypass\n            continue\n        if not parse_url(proxy).host:\n            raise ValueError(f\"proxy for {scheme} has no host: {proxy!r}\")\n        out[scheme] = proxy\n    return out\n\nrequests.get(url, proxies=normalize_proxies(proxies))","typeGuard":"from urllib3.util import parse_url\n\ndef is_well_formed_proxy(proxy) -> bool:\n    if proxy is None:\n        return True\n    if not isinstance(proxy, str) or not proxy:\n        return False\n    return bool(parse_url(proxy).host)","tryCatchPattern":"import requests.exceptions as exc\n\ntry:\n    resp = session.get(url, proxies=proxies)\nexcept exc.InvalidProxyURL as e:\n    raise ValueError(\n        f\"misconfigured proxy {proxies!r}: missing host\"\n    ) from e","preventionTips":["Validate proxy strings at config load time, not at request time.\nUnset empty HTTP_PROXY/HTTPS_PROXY env vars rather than leaving them blank.\nUse None to bypass a proxy per-scheme, not an empty string.\nCentralize proxy configuration so malformed values are caught once."],"tags":["proxy","invalid-proxy-url","config","validation"],"backgroundTag":null,"analyzedSha":"8068356288978c4f54661ae6f95afe0e0831885e","analyzedAt":"2026-08-11T20:11:09.238Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}