spyderproxy

cURL Timeout: Settings, Errors, and Fixes

D

Daniel K.

|
Published date

Wed May 06 2026

Quick verdict: cURL has two separate timeouts. --max-time is the maximum time for the whole request (DNS + connect + TLS + body transfer). --connect-timeout is just the TCP+TLS handshake. Defaults: --max-time is UNLIMITED (which is why your scripts hang); --connect-timeout defaults to 300 seconds. For production scripts, always set --max-time 30 --connect-timeout 10 as a sensible baseline.

This guide covers what each timeout does, the meaning of error 28 (operation timed out), how proxies affect timeouts, retry patterns, and 6 working examples.

The Two Timeouts

Flag What it covers Default When it triggers error 28
--max-timeWhole request (DNS + connect + TLS + body)UnlimitedServer is slow to respond
--connect-timeoutTCP + TLS handshake only300 secondsServer is unreachable / network blocked
--speed-time + --speed-limitLow transfer rateOffBytes/sec stays below threshold

6 Working Examples

1. Sensible production defaults

curl --max-time 30 --connect-timeout 10 https://api.example.com

2. Short timeout for liveness checks

curl -I --max-time 5 --connect-timeout 3 https://example.com -o /dev/null -w '%{http_code}
'

3. Long timeout for large downloads

curl --max-time 600 --connect-timeout 15 https://example.com/large.iso -O

4. Low-speed timeout (abort if transfer below threshold)

# Abort if transfer drops below 1 KB/s for 30 seconds
curl --speed-time 30 --speed-limit 1024 https://example.com/large.zip -O

5. Through a proxy with timeouts

curl --max-time 60 --connect-timeout 20   -x http://USER:[email protected]:8080   https://api.example.com

Notice connect-timeout is 20s, longer than direct calls — through a residential proxy, the handshake adds 100-300ms RTT, so allow more headroom.

6. Retry on timeout

curl --retry 3 --retry-delay 5   --max-time 30 --connect-timeout 10   https://api.example.com

By default, cURL retries on transient errors (timeout, connection-refused, 5xx). For 4xx errors, add --retry-all-errors if you want to retry those too.

Decoding Error 28

cURL prints two distinct error 28 messages:

  • "Connection timed out after N milliseconds"--connect-timeout exceeded. Server is unreachable, port blocked, or DNS slow.
  • "Operation timed out after N milliseconds with X bytes received"--max-time exceeded. Server connected fine but didn't finish the response in time.

Diagnose by separating the budgets: set --connect-timeout 5 --max-time 30. If you get connect-timeout error, it's a network/DNS issue; if max-time, it's a slow server.

Proxy Effects on Timeouts

Adding a proxy typically increases:

  • Connect time by 50-300 ms (extra TCP+TLS handshake to the proxy)
  • Per-request RTT by 50-200 ms (proxy adds latency)
  • Throughput variability (proxy capacity varies)

Recommended timeouts for proxied requests:

Proxy type --connect-timeout --max-time
Direct (no proxy)5-10 s15-30 s
Static datacenter10-15 s30-60 s
Rotating residential15-25 s45-90 s
LTE mobile20-30 s60-120 s

Verify proxy latency before launching scrapers with our proxy checker tool — it tests handshake and request latency in 5 seconds.

Production Patterns

Liveness check (fast fail)

curl -s -o /dev/null -w '%{http_code}'   --max-time 5 --connect-timeout 3   https://example.com/health

API call with retry

curl --retry 3 --retry-delay 2   --max-time 30 --connect-timeout 10   -H 'Authorization: Bearer xyz'   https://api.example.com/items

Long download with low-speed timeout

curl --max-time 1800   --speed-time 60 --speed-limit 102400   https://example.com/big-file.iso -O

Allows up to 30 minutes total, but aborts if transfer drops below 100 KB/s for 60 seconds (probably hung).