Explicit timeout values keep cURL from hanging on unreachable hosts or slow responses. That matters in shell scripts, CI jobs, health checks, and ad-hoc troubleshooting, where waiting forever hides the real failure and blocks the next step in the workflow.
Option --connect-timeout limits how long cURL can spend reaching the server, including name resolution plus the TCP and TLS or QUIC handshake. Option --max-time limits the entire transfer, so a response that connects successfully but stalls later still stops at a predictable point.
A timeout returns exit status 28. Use that status to treat timeout failures differently from HTTP errors or certificate problems, and keep any retry budget separate with --retry-max-time so repeated attempts do not hide a slow dependency. The sample hosts and paths below stay masked while preserving the shape of a normal health check and a slower reporting endpoint.
Steps to handle timeouts in cURL:
- Limit the connection phase so an unreachable host fails quickly instead of waiting on the operating system's longer network timeout.
$ curl --connect-timeout 2 --silent --show-error http://192.0.2.200/ curl: (28) Failed to connect to 192.0.2.200 port 80 after 2001 ms: Timeout was reached
Option --connect-timeout stops the request if DNS lookup plus the TCP and TLS or QUIC handshake cannot finish inside the configured budget.
- Cap the whole request duration so a slow endpoint cannot block the terminal or script indefinitely after the connection succeeds.
$ curl --max-time 2 --silent --show-error https://api.example.net/reports/monthly?profile=slow-response curl: (28) Operation timed out after 2012 milliseconds with 0 bytes received
Set --max-time above the service's normal response time, or healthy requests will be cut off as timeout failures.
- Print machine-readable status fields when a script needs to tell a timeout apart from a successful transfer without parsing the response body.
$ curl --connect-timeout 2 --max-time 4 --silent --show-error --output /dev/null --write-out "http_code=%{http_code}\nexit_code=%{exitcode}\ntime_total=%{time_total}\n" https://api.example.net/reports/monthly?profile=slow-response curl: (28) Operation timed out after 4009 milliseconds with 0 bytes received http_code=000 exit_code=28 time_total=4.009589Discarding the body with --output /dev/null keeps the transcript focused on the status fields that automation usually needs.
- Verify the same timeout profile still leaves enough headroom for a healthy endpoint to complete normally.
$ curl --connect-timeout 2 --max-time 4 --silent --show-error --output /dev/null --write-out "http_code=%{http_code}\nexit_code=%{exitcode}\ntime_total=%{time_total}\n" https://api.example.net/health http_code=200 exit_code=0 time_total=0.184672A healthy response should finish with exit code 0 and enough margin below the configured --max-time ceiling for ordinary variation.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
