Geonode logo
Proxy and connection errors

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.

WhereWhat you see
curl, --max-time reachedcurl: (28) Operation timed out after 30002 milliseconds with 0 bytes received
curl, proxy slow to open the HTTPS tunnelcurl: (28) Connection timed out after 10002 milliseconds
Python requestsrequests.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 slowThis 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.

  1. 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/
  2. 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.

    1. In the dashboard's Proxy Configuration, set Gateway (Host) to the location nearest you.

    2. Use its host: proxy.geonode.io (France), us.premium-residential.geonode.com (United States) or sg.premium-residential.geonode.com (Singapore).

    3. Add -country-<country_code> to the username for an exit near the site's servers.

    4. Send fewer requests at once per proxy, and keep free-list proxies out of timed jobs.

  3. 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.

  1. Log time to first byte for each request and alert when it nears your read timeout.

  2. When you run both client and gateway, set the client's limit higher, so failures arrive as a readable 504.

  3. Remove a proxy from your list after repeated connect timeouts instead of retrying it.

  4. For downloads of unknown size, use curl's --speed-limit and --speed-time in place of --max-time.

A new exit on every retryRotating ports give each request a new IP, so a retry uses another exit.
Try residential proxies

Related errors

Learn more

FAQ

A server working as a gateway or proxy gave up waiting for the server behind it. The hyphen comes from RFC 2616's old reason phrase, which nginx and HAProxy still print; RFC 9110 calls the status Gateway Timeout.

It means the server, or a proxy acting for it, stopped waiting for your full request, such as a large upload on a slow route. Chrome quietly resends the request when a 408 arrives on a reused HTTP/1.1 connection.

It is CURLE_OPERATION_TIMEDOUT: one of curl's limits ran out, either --connect-timeout (300 seconds when unset), --max-time or the --speed-limit check. Through an HTTP proxy the connect limit also covers CONNECT, and older builds print Proxy CONNECT aborted due to timeout.

A connection timeout limits the wait to open the connection; a read timeout limits each wait for data after that. In Python requests the read value caps the gap between bytes, so a slow but steady download never trips it.

proxyTimeout caps the wait for the target and answers 504; timeout caps the incoming socket and closes it unanswered. Both options reach the underlying proxy on every request in v3 and in v4.

Raise the second number in timeout=(connect, read) past the longest pause the site needs before sending data. Behind a proxy, a slow CONNECT reply also raises ReadTimeout; if the message shows your connect value, raise that number instead.

Keep one IP for long jobs

Sticky sessions hold one IP from 3 minutes up to 24 hours, set per job.