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.
$ 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.
$ 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.
$ 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.009589
Discarding the body with --output /dev/null keeps the transcript focused on the status fields that automation usually needs.
$ 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.184672
A healthy response should finish with exit code 0 and enough margin below the configured --max-time ceiling for ordinary variation.