Without limits, a script can hang forever on a dead server; with retries, it survives brief outages.
By default curl waits a long time: the connect phase times out after 300 seconds and the whole transfer has no time limit. In scripts and health checks, always set limits:
--connect-timeout 5limits the TCP and TLS connect phase.-m 30/--max-time 30limits the entire operation. Exceeding either gives exit code 28.
Retrying transient failures:
--retry 3retries up to three times when the error is considered transient: a timeout or an HTTP 408, 429, 500, 502, 503 or 504. Waits double from 1 second each time unless you set--retry-delay.- curl honours the server's
Retry-Afterheader for 429 and 503 responses. --retry-all-errorsretries on any error (including other HTTP errors when used with--fail); use carefully.--retry-max-time 60caps the total time spent retrying, and--retry-connrefusedalso retries when the connection is refused (useful while a service is starting).
Be careful with retries on non-idempotent requests: retrying a POST that timed out may create the resource twice if the first attempt actually succeeded. APIs often support an Idempotency-Key header for exactly this.
A good default for scripts: curl -sS --fail-with-body --connect-timeout 5 --max-time 30 --retry 3.
Example
curl -sS --connect-timeout 5 --max-time 20 https://api.example.com/report -o report.json
echo $? # 28 if it took longer than 20 s
# robust download in CI
curl -fsSL --retry 5 --retry-delay 2 --retry-max-time 60 \
-o tool.tgz https://releases.example.com/tool.tgz
# wait for a service that is still starting
curl -fsS --retry 10 --retry-connrefused --retry-delay 1 http://localhost:8080/health
# POST with an idempotency key so a retry cannot double-charge
curl -sS --retry 3 -H "Idempotency-Key: $(uuidgen)" --json @order.json https://api.example.com/ordersRemember
- --connect-timeout for connecting, --max-time for the whole request
- --retry N handles timeouts and HTTP 408, 429, 500, 502, 503, 504
- Retrying non-idempotent requests can duplicate work
Watch out for
- Running curl in cron or CI without --max-time, so a stalled connection blocks the job indefinitely.