{"id":"9107c984b11c444b","repo":"encode/httpx","slug":"proxy-protocol-must-be-either-http-https-so","errorCode":null,"errorMessage":"Proxy protocol must be either 'http', 'https', 'socks5', or 'socks5h', but got {proxy.url.scheme!r}.","messagePattern":"Proxy protocol must be either 'http', 'https', 'socks5', or 'socks5h', but got (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"httpx/_transports/default.py","lineNumber":212,"sourceCode":"                ) from None\n\n            self._pool = httpcore.SOCKSProxy(\n                proxy_url=httpcore.URL(\n                    scheme=proxy.url.raw_scheme,\n                    host=proxy.url.raw_host,\n                    port=proxy.url.port,\n                    target=proxy.url.raw_path,\n                ),\n                proxy_auth=proxy.raw_auth,\n                ssl_context=ssl_context,\n                max_connections=limits.max_connections,\n                max_keepalive_connections=limits.max_keepalive_connections,\n                keepalive_expiry=limits.keepalive_expiry,\n                http1=http1,\n                http2=http2,\n            )\n        else:  # pragma: no cover\n            raise ValueError(\n                \"Proxy protocol must be either 'http', 'https', 'socks5', or 'socks5h',\"\n                f\" but got {proxy.url.scheme!r}.\"\n            )\n\n    def __enter__(self: T) -> T:  # Use generics for subclass support.\n        self._pool.__enter__()\n        return self\n\n    def __exit__(\n        self,\n        exc_type: type[BaseException] | None = None,\n        exc_value: BaseException | None = None,\n        traceback: TracebackType | None = None,\n    ) -> None:\n        with map_httpcore_exceptions():\n            self._pool.__exit__(exc_type, exc_value, traceback)\n\n    def handle_request(","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/encode/httpx/blob/b5addb64f0161ff6bfe94c124ef76f6a1fba5254/httpx/_transports/default.py#L194-L230","documentation":"Raised by the synchronous HTTPTransport constructor when the supplied Proxy has a scheme that is none of 'http', 'https', 'socks5', 'socks5h'. The constructor branches on proxy.url.scheme and falls through to a ValueError for any other value. It is a programmer/config error surfaced at Client/transport construction time.","triggerScenarios":"Passing httpx.Client(proxy='ftp://...'), proxy='socks4://...', proxy='socks5://...' misspelled as 'socKS5://', or a Proxy object whose URL was built with an unsupported scheme. Also triggered by a typo in the ALL_PROXY env var (e.g. 'socsk5://').","commonSituations":"Confusing SOCKS4 (unsupported by httpx/httpcore) with SOCKS5; pasting a proxy URL from a tool that uses a non-standard scheme prefix; trailing slash or colon turning 'http' into 'http:'; case where env-derived proxy string has a stray scheme.","solutions":["Use one of the supported schemes: 'http', 'https', 'socks5', or 'socks5h' in the proxy URL.","If you have a SOCKS4 proxy, run/upgrade to a SOCKS5 server, or front it with an HTTP proxy.","Strip whitespace and validate the proxy string before passing it: assert proxy.split('://')[0] in {'http','https','socks5','socks5h'}.","If the value comes from an env var, log it (without credentials) to catch typos like 'socsk5'."],"exampleFix":"// before\nclient = httpx.Client(proxy=\"socks4://127.0.0.1:1080\")  # ValueError\n\n// after\nclient = httpx.Client(proxy=\"socks5://127.0.0.1:1080\")","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\n\nALLOWED_PROXY_SCHEMES = {\"http\", \"https\", \"socks5\", \"socks5h\"}\n\ndef validate_proxy(proxy: str) -> str:\n    scheme = urlparse(proxy).scheme.lower()\n    if scheme not in ALLOWED_PROXY_SCHEMES:\n        raise ValueError(\n            f\"Unsupported proxy scheme {scheme!r}; \"\n            f\"must be one of {sorted(ALLOWED_PROXY_SCHEMES)}\"\n        )\n    return proxy\n\nclient = httpx.Client(proxy=validate_proxy(my_proxy))","typeGuard":"def is_supported_proxy(value: object) -> bool:\n    if not isinstance(value, str):\n        return False\n    scheme = value.split(\"://\", 1)[0].lower()\n    return scheme in {\"http\", \"https\", \"socks5\", \"socks5h\"}","tryCatchPattern":"try:\n    client = httpx.Client(proxy=proxy_str)\nexcept ValueError as e:\n    if \"Proxy protocol must be\" in str(e):\n        log.error(\"Bad proxy config: %s\", proxy_str.split(\"@\")[-1])  # strip creds\n    raise","preventionTips":["Centralize proxy config in one helper that validates the scheme.","Log the proxy scheme (never credentials) when reading env-derived proxies.","Treat SOCKS4 endpoints as unsupported and convert them at the config layer."],"tags":["proxy","config","sync","network","validation"],"analyzedSha":"b5addb64f0161ff6bfe94c124ef76f6a1fba5254","analyzedAt":"2026-08-04T19:32:56.768Z","schemaVersion":2}