Proxy Errors in httpx and aiohttp
The async Python libraries configure proxies differently from requests and report refusals in their own way. Below are the error texts they produce and what each one means.
Updated · Prokso editorial team
- Since httpx 0.28.0 there is no proxies argument: set the proxy with proxy= or mounts=
- httpx reports a proxy refusal as ProxyError, aiohttp as ClientHttpProxyError, and the word after 407 names the reason
- SOCKS in httpx needs httpx[socks], and in aiohttp it works only through the aiohttp-socks package
What the error means
In httpx, the proxy is set with the proxy= argument. The old proxies= argument was deprecated in version 0.26.0 and removed in 0.28.0, so now it gives TypeError: Client.__init__() got an unexpected keyword argument 'proxies'. If the proxy did not accept the CONNECT request, httpx raises httpx.ProxyError with the response code and text, for example 407 NO_USER. If it could not connect to the proxy at all, you get httpx.ConnectError instead.
In aiohttp, a failure to connect to the proxy is ClientProxyConnectionError with the text Cannot connect to host gw.prokso.com:823. A refusal of CONNECT is ClientHttpProxyError, for example 407, message='NO_USER'. Note that the text of this exception contains the proxy address together with the username and password, so do not publish such logs.
Both libraries support SOCKS only through extra packages. Without them, httpx says Using SOCKS proxy, but the 'socksio' package is not installed and suggests pip install httpx[socks]. aiohttp has no built-in SOCKS support at all: you need the aiohttp-socks package.
Causes
- The old proxies argument in httpx. Code written for versions before 0.28 fails with TypeError as soon as the client is created.
- Username, password or a limit. 407 NO_USER means wrong sign-in data, while TRAFFIC_EXHAUSTED and THREADS_EXHAUSTED point to plan limits. For https:// sites it is an exception, for http:// an ordinary response with status 407.
- SOCKS without the extra package. httpx lacks socksio, or aiohttp got a socks5:// line in the proxy= argument. aiohttp does not reject such a line; it sends a plain HTTP CONNECT request to the SOCKS port, and the resulting error is confusing.
- The wrong host or port. ConnectError in httpx and ClientProxyConnectionError in aiohttp: the line does not say gw.prokso.com, or the port is outside 823, 824 and 10000-20000.
- The https:// scheme in the proxy line. Port 823 expects plain HTTP. The httpx documentation recommends http:// even for https sites, and aiohttp has only limited support for https:// proxies.
How to fix it
- In httpx, replace
proxies=withhttpx.Client(proxy='http://USERNAME:PASSWORD@gw.prokso.com:823'). For different proxies for different addresses, usemounts=. - For SOCKS in httpx, install
pip install 'httpx[socks]'and writeproxy='socks5h://USERNAME:PASSWORD@gw.prokso.com:824'. httpx accepts the socks5h scheme since version 0.28.0. - In aiohttp, pass the username and password in the line itself:
session.get(url, proxy='http://USERNAME:PASSWORD@gw.prokso.com:823'). The proxy_auth parameter has been deprecated since version 3.14. - For SOCKS in aiohttp, install aiohttp-socks and create the session with
ProxyConnector.from_url('socks5://USERNAME:PASSWORD@gw.prokso.com:824'). This method accepts the socks5, socks4 and http schemes, and for SOCKS5 it lets the proxy turn the site name into an IP by default (the rdns parameter). A full example is in the aiohttp guide. - Handle 407 by the response text: NO_USER means check the username and the IP list, TRAFFIC_EXHAUSTED means top up traffic, THREADS_EXHAUSTED means cut simultaneous tasks to 1000 per plan. All ports and line formats are collected in the gateway reference.
How to check that it works
Send a request to https://prokso.com/ip with the same client and the same proxy line. If the response is JSON with the IP, country and ASN of the proxy, the setup is correct. You can also test the line without code in the proxy checker to separate a code error from a data error.
Two-minute diagnosis
First paste the line into the proxy checker. If the proxy works there, the cause is in your app or its settings. If not, test the line from a terminal:
curl -v -x "http://USERNAME:PASSWORD@gw.prokso.com:823" https://api.ipify.org
- A
< HTTP/1.1 407line right afterCONNECTmeans the proxy answered. The name after the code, for exampleNO_USER, points to the cause. - The proxy answered
CONNECTwith 200 and then another code arrived - the proxy works, and that answer came from the website. - No answer at all, only a timeout - the connection never reached the proxy: check the host, port and network.
Setup guides where this error comes up
FAQ
Why does httpx raise ProxyError: 407 but return a response for an http site?
For https://, the client opens a CONNECT tunnel, and a refusal there becomes an exception. For http://, the request goes to the proxy directly, and 407 comes back as an ordinary response. What the code means is explained on the <a href="/en/errors/407-proxy-authentication-required">407 Proxy Authentication Required</a> page.
Does aiohttp take the proxy from environment variables?
Not by default. The HTTP_PROXY and HTTPS_PROXY variables are read only when the session is created with trust_env=True.
Can I write socks5h in aiohttp-socks?
In the python-socks package that aiohttp-socks is built on, the from_url method accepts socks5, not socks5h. Resolving the site name on the proxy side is on by default there for SOCKS5. About the protocol itself, see the glossary: <a href="/en/glossary/socks5">SOCKS5</a>.
Other proxy errors
Residential $1.59, mobile $2.50, datacenter $0.65 per GB
Sign up in a minute, get access right after payment.