Exit code 7 is CURLE_COULDNT_CONNECT. curl found an IP address for the name, tried to open a TCP connection, and the attempt failed. DNS worked; the connection did not. Newer curl versions print the elapsed time and a reason:
curl: (7) Failed to connect to example.com port 443 after 12 ms: Couldn't connect to server
curl: (7) Failed to connect to example.com port 443: Connection refused
curl: (7) Failed to connect to localhost port 8080 after 0 ms: Connection refused
curl: (7) couldn't connect to host
The elapsed time is a strong clue. A failure after a few milliseconds means something answered with a reset (refused). A failure after many seconds usually means a timeout, which curl reports as error 28 in most cases but can show as 7 when the OS gives up first (for example "Network is unreachable" or "No route to host").
Step 1: read the reason after the colon
- Connection refused: the host is reachable, but nothing listens on that port, or a firewall actively rejects.
- Network is unreachable / No route to host: your machine has no route to that address, often an IPv6 address on a host without IPv6.
- Couldn't connect to server: generic; use
curl -vfor detail.
Run it verbosely and see which address curl tried:
curl -v https://example.com/ 2>&1 | head -20
Lines like Trying 2001:db8::10:443... followed by Trying 203.0.113.10:443... show curl falling back from IPv6 to IPv4.
Step 2: confirm whether the service is listening
If you control the server, log in and list listeners:
sudo ss -ltnp | grep -E ':(80|443|8080)\b'
You should see a line with LISTEN and your web server's process (nginx, apache2, node). No line means the service is stopped, crashed or bound to another port. Check systemctl status nginx and the error log, then start it. Common traps:
- The app binds to
127.0.0.1:8080only, so it works locally and is refused from outside. Bind to0.0.0.0or put a reverse proxy in front. - A container publishes no port. Check
docker psfor a0.0.0.0:443->443/tcpmapping. - The service restarted into a crash loop. See nginx connect() failed 111 for the same condition seen from a proxy.
Step 3: check the firewall and security group
A listener that works locally but is refused or unreachable from outside is blocked in transit. Check, in order:
- The host firewall:
sudo ufw status,sudo firewall-cmd --list-allorsudo iptables -S. - The cloud security group or network ACL for the instance.
- A provider-level or hosting-panel firewall.
- Port forwarding on a router, if the server sits behind NAT.
Test from outside your network with the Port Checker. If it reports closed from the internet and open locally, the block is between the two. Your own public address, shown by What Is My IP, is useful when an allowlist is in place.
Step 4: the IP may be wrong
DNS can point to an old server. Compare the address curl used with the one you expect, and look it up with the IP Lookup. If the name resolves to an address you no longer own, fix the DNS record. A recent move that has not fully propagated causes mixed results; see how long DNS propagation takes.
Step 5: IPv6, proxies and local quirks
- IPv6 broken: compare
curl -4 -I https://example.com/andcurl -6 -I https://example.com/. If only IPv4 works, your server'sAAAArecord points to a host that is not serving IPv6. Fix the server or remove the record. - Proxy variables:
env | grep -i proxy. A dead proxy, orNO_PROXYmistakes, makes every request fail with a connect error to the proxy address, which curl prints as the proxy host and port. - Localhost confusion:
localhostcan resolve to::1first. A service listening only on IPv4 refuses::1; curl normally retries IPv4, but not every client does. Use127.0.0.1explicitly to test. - Wrong port: HTTP on 443 or HTTPS on 80 produces other errors, but a typo like
:4433just refuses. - Rate limiting or fail2ban: your IP may be banned. Check
sudo fail2ban-client statusand firewall drop rules.
When the site works for everyone but you
Run the Website Health Check or the HTTP Status Checker. If they connect fine, the block is local: your network, VPN, security software or an IP ban. The guide to connection refused, timed out and reset walks through the browser versions of the same failures.
Next steps
- Test the open port with the Port Checker.
- Run the Website Health Check from outside your network.
- Compare with curl (28) operation timed out and curl (6) could not resolve host.
- Alert when a port stops answering with an Uptime Monitor.
FAQ
Is curl 7 an SSL problem?
No. It happens before any TLS handshake, at the TCP connection stage. TLS failures show up as errors such as 35, 51, 58 or 60.
Why does it say "after 0 ms"?
The operating system refused the connection instantly, typically a reset from a host with no listener on the port, or a local routing failure. Check the listener and firewall.
Can DNS cause curl error 7?
Yes, indirectly. If DNS returns an old or wrong IP, curl connects to a machine that refuses or does not exist. Verify the record with the DNS Checker.
How do I fix it for a Docker container?
Make sure the app listens on 0.0.0.0 inside the container and that the port is published with -p. From another container, use the service name rather than localhost.
Get notified when this fix updates
Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.
This page is general information written by our editorial team and updated when documentation changes. Servers and providers differ, so test changes safely first. See our editorial policy and disclaimer.