How to Fix a Proxy Timeout Error
Find which timer gave up, then apply three ranked fixes, two with cURL, Python and Node.js code.
Updated
TL;DR
A proxy timeout means one side stopped waiting: your own client when no status code comes back, a gateway when you get 504, or the website when you get 408. The fastest fix is separate connect and read timeouts set from timings through the proxy.
What a timeout looks like in each client
Times in these messages come from your settings or client defaults, so yours will differ.
| Where | What you see |
|---|---|
| curl, --max-time reached | curl: (28) Operation timed out after 30002 milliseconds with 0 bytes received |
| curl, proxy slow to open the HTTPS tunnel | curl: (28) Connection timed out after 10002 milliseconds |
| Python requests | requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='example.com', port=443): Read timed out. (read timeout=30) |
| Puppeteer page.goto() | TimeoutError: Navigation timeout of 30000 ms exceeded |
| nginx gateway (default 504 page) | 504 Gateway Time-out nginx |
| http-proxy-middleware, target slow or down (504) | Error occurred while trying to proxy: localhost:3000/api/items |
| Chrome, proxy too slow | This site can't be reached. example.com took too long to respond. ERR_TIMED_OUT |
Why this happens
A proxy adds a stop to every trip, so answers come back later.
Your request now needs two connections, one to the proxy and one from the proxy to the site, and a residential exit adds a home connection's delay. A limit set without the proxy in mind can expire first.
Diagnose your timeout first
Each check clears one part of the route, so you change only the part that is slow.
Turn the proxy off in your browser and reload; if the page is still slow, the site is the cause, not the proxy.
Print curl -w '%{time_appconnect}' for an https:// URL, direct and with -x; if only the proxied time is high, the proxy's side is slow.
Run curl -v to an https:// URL through the proxy; if CONNECT gets 504, the proxy could not reach the site in time.
In Python, read the full exception; if ProxyError wraps ConnectTimeoutError, the proxy never accepted your connection.
If you run the gateway, read its error log; nginx's "upstream timed out" means the app behind it did not answer in time.
Solutions ranked by effectiveness
Try them in order and stop once requests finish inside your limits.
- Most common fix
Set separate connect and read timeouts
Applies when your code waits forever or gives up too soon through the proxy. Python requests has no default timeout, so pass both values and give the connect value enough time for both hops.
curl -x http://USERNAME:PASSWORD@proxy.geonode.io:9000 \ --connect-timeout 20 \ --max-time 120 \ https://example.com/ - Check next
Shorten the proxy route and lighten its load
Applies only when the proxy route is slow and the site is not. Geonode's docs name distance to the proxy and too many simultaneous requests as causes of high latency.
In the dashboard's Proxy Configuration, set Gateway (Host) to the location nearest you.
Use its host: proxy.geonode.io (France), us.premium-residential.geonode.com (United States) or sg.premium-residential.geonode.com (Singapore).
Add -country-<country_code> to the username for an exit near the site's servers.
Send fewer requests at once per proxy, and keep free-list proxies out of timed jobs.
- For developers
Retry idempotent requests with backoff
Applies when timeouts come and go. Resend only requests that are safe to repeat, such as GET, with growing waits and a cap on tries; constant timeouts mean a dead proxy or slow site.
curl -x http://USERNAME:PASSWORD@proxy.geonode.io:9000 \ --connect-timeout 20 --max-time 120 \ --retry 3 --retry-max-time 300 \ https://example.com/
Stop the timeout from coming back
Habits for scripts and long jobs that keep one slow hop from failing a whole run.
Log time to first byte for each request and alert when it nears your read timeout.
When you run both client and gateway, set the client's limit higher, so failures arrive as a readable 504.
Remove a proxy from your list after repeated connect timeouts instead of retrying it.
For downloads of unknown size, use curl's --speed-limit and --speed-time in place of --max-time.
Related errors
Learn more
FAQ
Keep one IP for long jobs
Sticky sessions hold one IP from 3 minutes up to 24 hours, set per job.


