Back to blog

cURL Timeout Explained: Settings, Fixes & Examples

-
Table of contents
-

By default, the cURL command can hang indefinitely if a server doesn’t respond. This is because there’s no timeout for the entire operation unless you set one. In practice, cURL requests can stall your whole script if they hang.

For reliability, always set appropriate timeout parameters so cURL won’t wait forever: if an operation exceeds your limit, it stops and returns an error instead of freezing.

What is a cURL timeout?

A cURL timeout is a limit on how long a request is allowed to run when using cURL. Without timeouts, cURL might wait forever for a response that isn’t coming. This can lead to hanging scripts, wasted resources, and frustrating delays.

Timeouts matter because they protect your applications from unreliable servers, poor internet connections, and unexpected delays. If a request takes too long, cURL will stop and report an error, thus allowing your script or program to handle the issue cleanly, such as by retrying or logging the failure.

There are several kinds of timeouts you can set: a connect timeout for the time it takes to connect to the server, a maximum time for the entire operation, and a low-speed timeout if the transfer becomes too slow. Each plays a role in ensuring your cURL requests don’t hang or fail silently.

Types of cURL timeouts

cURL provides a few options to control how long it waits:

  • Total timeout (--max-time): The maximum time in seconds for the entire request. If this time is exceeded, cURL aborts with a timeout error.
  • Connect timeout (--connect-timeout): The maximum time to establish the connection (DNS lookup + handshake). If the server isn’t connected within that limit, cURL stops the attempt (timeout error 28).
  • Slow transfer timeout: Aborts the transfer if data speed stays below a specified rate for too long.
  • Millisecond precision options (libcurl): If you're using libcurl (cURL’s underlying library in code), you can set timeouts with millisecond accuracy using options like CURLOPT_TIMEOUT_MS and CURLOPT_CONNECTTIMEOUT_MS. These are useful for applications needing precise control over timeout values.

Default cURL timeout behavior

If you don’t set any timeouts, here’s what happens:

  • No overall limit

By default, there is no max time set, and cURL could wait indefinitely for the operation to complete. No cURL max time limit is enforced unless you specify one.

  • Default cURL connect timeout

cURL has a built-in timeout for the connection phase of about 300 seconds (5 minutes). This default is quite high, so it’s often lowered with a custom --connect-timeout.

  • No slow-transfer cutoff

The low-speed abort is off by default, so even a very slow or stalled transfer will keep going.

  • Bottom line

Relying on defaults is risky since cURL requests could hang forever and block your program. It’s better to explicitly set a cURL connect timeout and a total timeout so you control how long cURL will wait.

How to set timeouts in cURL

You can configure timeouts when running the cURL command using these options:

Total operation timeout: --max-time

Sets an upper limit (maximum time in seconds) for the total request duration. If the transfer exceeds this time, cURL will terminate it. The following example caps the request at 30 seconds.

curl --max-time 30 https://example.com

Connect timeout: --connect-timeout

Limits how long cURL waits to connect to the host (including DNS resolution). The following example makes cURL give up if it cannot connect within 5 seconds.

curl --connect-timeout 5 https://example.com 

Slow transfer timeout: --speed-limit & --speed-time

Tells cURL to abort a transfer that’s too slow. The following example will stop the download if the speed drops below 1,000 bytes per second for 15 seconds.

curl --speed-limit 1000 --speed-time 15 https://example.com/file.zip

libcurl timeout options

In libcurl, corresponding options match the above. For example:

  • CURLOPT_TIMEOUT sets the total timeout (default 0, meaning no limit)
  • CURLOPT_CONNECTTIMEOUT sets the connection timeout (default 300 seconds)

There are also millisecond-resolution versions (CURLOPT_TIMEOUT_MS, etc.), and low-speed threshold options (CURLOPT_LOW_SPEED_LIMIT and CURLOPT_LOW_SPEED_TIME) to abort slow transfers.

Common cURL timeout errors & how to fix them

Error 28: operation timed out

Error 28 is cURL’s code for a timeout. It indicates the transfer did not finish within the specified timeout. You might see “...0 bytes received” in the error message. This means no data at all was received from the server before the timeout. To fix it, increase your timeout-related values if they were too low, or check for network/server slowness.

“Operation timed out after X ms with 0 bytes received”

This is a common message that means cURL hit its maximum time limit (like --max-time), or the connection timeout expired before receiving any data. If this happens frequently, it might indicate DNS resolution issues, an unresponsive server, or network connectivity problems.

Debugging timeouts with -v and --trace-time

To investigate where your cURL request is hanging, use the -v flag for verbose output. This shows each stage of the connection, including DNS resolution and SSL handshakes. Add --trace-time to timestamp every line of the log. Together, these options help you see if the delay is during the cURL connect timeout, data transfer, or somewhere else in the whole operation.

How to choose the right timeout values

Choosing the right values depends on the type of request you're making and the conditions of your network. There's no one-size-fits-all, but here are some general guidelines to help you set timeouts more effectively.

  • APIs: Use a short timeout (2–5 seconds) and a max time of 10–30 seconds. APIs (especially paired with proxies) are typically fast, and long delays usually mean something’s wrong.
  • Browser-like web requests: Use a timeout of 5–10 seconds and a maximum time of 30–60 seconds to allow for larger HTML responses or redirects.
  • Large downloads: You can set a higher maximum time allowed, such as 300–900 seconds, but still keep the timeout short (5–10 seconds). Also consider enabling low-speed aborts with --speed-limit and --speed-time to stop stalled transfers.
  • CLI tools & scripts: Always set a timeout explicitly to prevent scripts from hanging. A good default: --connect-timeout 5 and --max-time 30.

When picking values, balance these three factors:

  • Timeout length: Too short may cause premature failures; too long may block your app.
  • Retry logic: If you’re retrying failed requests, shorter timeouts work better.
  • Network conditions: For unstable networks, increase timeouts slightly to reduce false timeouts.
What is the default curl timeout?

By default, cURL has no set timeout for the full operation. It will wait indefinitely unless you set a timeout. The only built-in limit is a 300-second cURL connect timeout for the connection phase (around 5 minutes).

What is the difference between --max-time and --connect-timeout?

--connect-timeout only limits the time spent establishing the connection (DNS lookup and handshake). --max-time (the cURL max time) caps the duration of the whole operation from start to finish. Connect-timeout is just for the initial connection, whereas --max-time limits the entire request.

How do I set a curl timeout under 1 second?

Use fractional seconds. For example, --connect-timeout 0.5 sets a 0.5s timeout, and --max-time 0.5 sets a 0.5s total timeout. (If you’re using libcurl in code, you can use the millisecond options like CURLOPT_TIMEOUT_MS for the same effect.)

Why does curl timeout even when the server is online?

“Online” doesn’t guarantee the server will respond quickly. cURL will timeout if the server or network is too slow to deliver data within your set time limit. In other words, the server may be up, but if it doesn’t send a response before your timeout (due to slowness or network lag), cURL treats it as a timeout.

How do I debug curl timeout errors?

Run the cURL command with -v to see which step is stalling (DNS, connect, etc.), and add --trace-time to a trace log to timestamp each operation. This helps pinpoint where the delay is so you can set a timeout or fix the network issue.

Learn more
-

Related articles