Skip to main content
DevOps Insightsguides & answers

curl · troubleshooting

curl: (28) Operation timed out

curl gave up waiting, and the wording of the message says where it was stuck. Failed to connect … Timeout was reached means the connection never opened; Operation timed out … bytes received means it opened but the response was too slow.

Reproduced on curl 8.5.0, . Where the text says “reproduced”, the behaviour was run on that version, not taken from documentation.

First published

New to this? Read what is actually happening first, then come back to the steps.

On this page · 8 sections

Before you start

  • The full message (it says which timeout), and the curl options used.

Run this first

step 1 of 1
curl -v --connect-timeout 5 -m 30 URL

Look for Connected to … before the error, or not

Shows whether the connection opened before the timeout.

Work out which cause you have

A few questions to narrow the list. Every answer ends in a command that confirms or rules the cause out — this cannot see your cluster, so nothing here is a certainty until you have checked.

Narrow it down

0 answered · nothing is sent anywhere

Which wording does the error use?

Cause space

2 of 2 still possible

  • Packets are dropped before a connection opensCommon
  • The server accepted the connection and is too slowCommon

Nothing ruled out yet. Answer the question above and the branches your answer eliminates will strike through here.

Or diagnose it manually

In this order. The first command usually contains the whole answer.

  1. Step 1

    curl -v --connect-timeout 5 -m 30 URL

    Shows whether the connection opened before the timeout.

    Look for Connected to … before the error, or not

Every cause, and how to fix it

Ordered by how often each one turns out to be the answer.

Packets are dropped before a connection opens

Common

A security group, network ACL or firewall drops the traffic silently, or the address is on a network this machine cannot route to.

Confirm

curl -v --connect-timeout 5 URL 2>&1 | grep -E 'Trying|Connected|Timeout'

Trying ADDRESS:PORT and then a timeout, never Connected

Fix

  • Open the port for this source in the security group or firewall, or call an address reachable from here.
  • For AWS, check both the security group of the target and the route from the caller's subnet.

The server accepted the connection and is too slow

Common

An overloaded or stuck backend, a long-running request, or a proxy waiting on an upstream.

Confirm

curl -sS -o /dev/null -w 'connect %{time_connect}s, first byte %{time_starttransfer}s\n' URL

A quick connect and a long or missing time to first byte

Fix

  • Find why the server is slow: its logs, CPU and the upstreams it calls.
  • If the request is legitimately long, raise --max-time for that call only.

Understanding it properly

Skip this if you are mid-incident — the working part of the page is above. Worth reading afterwards, because understanding the mechanism is what stops the next one.

In plain terms

Exit code 28 is a timeout, but there are two kinds. If curl never got a connection, packets are being dropped on the way: a firewall, security group or wrong network. If it connected and then waited, the server accepted the request and is slow or stuck.

Words used on this page

--connect-timeout
How long curl waits for the connection to open.
-m, --max-time
How long the whole transfer may take, connection included.
What is actually happening

Reproduced on 23 October 2026 with curl 8.5.0 on Ubuntu 24.04 and curl 8.7.1 on macOS. To an address that never answers, curl --connect-timeout 2 printed curl: (28) Failed to connect to 10.255.255.1 port 80 after 2002 ms: Timeout was reached.

To a server that accepted the connection and never replied, curl -m 2 printed curl: (28) Operation timed out after 2002 milliseconds with 0 bytes received. Both exited 28; the wording, not the number, tells you which side to look at.

Compare curl (7): a refusal is immediate, while a dropped packet makes curl wait for the full timeout.

How to tell this is your problem
WhereWhat you see
Connection never openedcurl: (28) Failed to connect to 10.0.1.5 port 443 after 10002 ms: Timeout was reached
Connected, no response in timecurl: (28) Operation timed out after 30001 milliseconds with 0 bytes received

How to know it is actually fixed

  • curl completes well inside its timeout, and the time to first byte is stable.

Stopping it happening again

  • Set both --connect-timeout and --max-time in scripts, so a dropped network fails fast and a stuck server cannot hang a job.
  • Retry timeouts with --retry, which curl already treats as transient.

Sources

Behaviour described here is drawn from official documentation. Where a figure could not be confirmed on an official page it is attributed in the text rather than stated as canonical.

Did this get you to an answer?

No text box on purpose — please do not paste production logs anywhere

Something wrong or out of date? Report it