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.
| Flag | What it covers | Default | When it triggers error 28 |
|---|---|---|---|
--max-time | Whole request (DNS + connect + TLS + body) | Unlimited | Server is slow to respond |
--connect-timeout | TCP + TLS handshake only | 300 seconds | Server is unreachable / network blocked |
--speed-time + --speed-limit | Low transfer rate | Off | Bytes/sec stays below threshold |
curl --max-time 30 --connect-timeout 10 https://api.example.com
curl -I --max-time 5 --connect-timeout 3 https://example.com -o /dev/null -w '%{http_code}
'
curl --max-time 600 --connect-timeout 15 https://example.com/large.iso -O
# Abort if transfer drops below 1 KB/s for 30 seconds
curl --speed-time 30 --speed-limit 1024 https://example.com/large.zip -O
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.
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.
cURL prints two distinct error 28 messages:
--connect-timeout exceeded. Server is unreachable, port blocked, or DNS slow.--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.
Adding a proxy typically increases:
Recommended timeouts for proxied requests:
| Proxy type | --connect-timeout | --max-time |
|---|---|---|
| Direct (no proxy) | 5-10 s | 15-30 s |
| Static datacenter | 10-15 s | 30-60 s |
| Rotating residential | 15-25 s | 45-90 s |
| LTE mobile | 20-30 s | 60-120 s |
Verify proxy latency before launching scrapers with our proxy checker tool — it tests handshake and request latency in 5 seconds.
curl -s -o /dev/null -w '%{http_code}' --max-time 5 --connect-timeout 3 https://example.com/health
curl --retry 3 --retry-delay 2 --max-time 30 --connect-timeout 10 -H 'Authorization: Bearer xyz' https://api.example.com/items
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).