Skip to content

Proxy timeout? Find which operation is waiting

Diagnose proxy connection and read timeouts with bounded curl checks. Compare HTTPX and Requests limits, then separate client waits from gateway errors.

Mobileproxies.orgUpdated 4 min read

A proxy timeout means an operation exceeded a configured time limit. Identify whether the client was connecting, waiting for response data or waiting for a free connection. Increasing every timeout can hide the failure and leave more requests waiting.

Identify the operation that timed out

Keep the exact exception name and the timeout settings. HTTPX distinguishes connect, read, write and pool timeouts. A pool timeout means the client waited for an available connection; it is not direct evidence that a remote proxy stopped responding.

Requests supports separate connect and read timeout values. Its timeout is not a deadline for downloading the entire response. A server that keeps sending data can keep the request alive beyond that value. Use your job runner's deadline when you need a wall-clock limit for the whole task.

ObservationNext check
Connect timeoutEndpoint, protocol, network route and current rental state.
Read timeoutResponse progress from the proxy or destination.
Pool timeoutClient connection limits and responses left open.
HTTP 504 responseWhich gateway returned it and what it was waiting for.

References: Requests timeout semantics; HTTPX timeout types

Use a small, bounded request

Use the private curl configuration from the authentication guide with a 10-second connect timeout and a 30-second overall limit. These are example diagnostic limits, not promised service timings. Adjust them to a measured workload once you know where time is spent.

Compare the same small URL directly and through the proxy from the same machine, where direct testing is permitted. Do not run a large parallel speed test while diagnosing one failed connection.

Shell
curl -q --config "$HOME/.config/proxy-check.curl" \
  --connect-timeout 10 --max-time 30 \
  --output /dev/null \
  --write-out 'connect_elapsed=%{time_connect}s first_byte=%{time_starttransfer}s total=%{time_total}s http=%{http_code}\n' \
  https://example.com
printf 'curl_exit=%s\n' "$?"

References: curl proxy and configuration options

Read curl's timing fields

curl exit code 28 reports that a time limit was reached. The elapsed-time fields narrow the investigation, but they cannot independently locate delay inside a carrier network or destination server. Time to first byte includes the work performed before the first response byte arrives.

time_connect is elapsed time from the transfer start until the connection completes, including earlier name resolution. It is not the duration of the TCP handshake alone. For a proxy request, that connection is to the proxy; later tunnel and destination work still has to finish.

If curl reaches its deadline before receiving a response byte, the first-byte field may stay at zero. Include that run as a failed sample. Reporting only completed requests makes an unreliable connection look faster than it is.

References: curl proxy and configuration options

HTTP 200 can arrive before a timeout

Our local fixture sent HTTP 200 headers, then delayed the response body. curl 8.7.1 reached its 0.25-second total limit and exited with code 28 while still reporting HTTP 200. Checking only the status would have counted that incomplete response as a success.

Requests 2.32.5 completed a six-byte response in about 0.92 seconds with a 0.4-second read timeout because each byte arrived about 0.15 seconds apart. A separate fixture that paused the body beyond a 0.25-second read timeout raised ConnectionError with a read-timeout cause. This was the observed exception wrapper in this version.

Controlled responseObserved result
Headers, then delayed body; curl max-time 0.25HTTP 200; exit 28 after about 0.25 seconds.
One byte every 0.15 seconds; Requests read timeout 0.4Completed after about 0.92 seconds.
Headers, then delayed body; Requests read timeout 0.25ConnectionError after about 0.25 seconds.
Shell
python3 proxy-diagnostics-lab.py --output proxy-lab-results.json

Recorded on macOS with Python 3.9.6 on 13 November 2026. These local timings demonstrate timeout semantics, not proxy speed. A heavily stalled machine can change the timing results.

Download the local diagnostic lab

Change one condition at a time

  1. Keep the endpoint, URL and client constant and repeat a small number of checks. Record failures as well as successes.
  2. Compare a second small destination you are authorized to request. A failure on one destination needs a different investigation from a failure on every destination.
  3. Reduce concurrency to one request. If that helps, inspect client pooling and workload capacity before buying more ports.
  4. Check whether a rotation or carrier reconnect coincided with the failure. Keep long-running work separate from deliberate rotation where possible.

Retry only when the operation permits it

A timed-out request may still have reached the destination. Do not automatically repeat purchases, messages or other state-changing actions without an application-specific idempotency mechanism. For safe read checks, use a limited retry count, a delay and an overall deadline.

If the proxy works on neutral requests but the application still times out, send the application error and a redacted timing comparison to support. Include whether the same timeout occurs with one request and a second destination.

Sources and further reading