Skip to content
RU
← All articles

ERR_CONNECTION_REFUSED: Causes and Fix

In short. A refusal is a positive signal: a machine at that address received your connection attempt and actively answered "nothing here". That distinguishes it from a timeout, where nothing answers at all, and it narrows the cause to a short list — the service is not running, it is listening on the wrong interface, or a firewall is rejecting rather than dropping.

Refused, dropped and reset are three different answers

Browsers show similar messages for all three, but at the network level they are distinct events with distinct causes. Telling them apart takes one command and eliminates most of the possibilities.

What happenedNetwork eventMeaningLikely cause
RefusedImmediate reset on connectHost is alive; nothing accepts on that portService stopped, wrong interface, firewall REJECT
Timed outNo answer at allPackets are being discarded silentlyFirewall DROP, wrong address, host gone
Reset mid-sessionReset after connectingConnection accepted, then terminatedApplication crash, proxy limit, inspection device
nc -vz -w 5 example.com 443
# "succeeded"            -> port is open; the problem is above TCP
# "Connection refused"   -> this article
# hangs, then times out  -> a different problem entirely

Refusal is the most informative of the three. Something is running at that address and it is reachable — the network path works, routing works, the host is up. Only the specific port is closed, which is a much smaller search space than a timeout gives you.

If you are not yet sure which layer is failing at all, the layer isolation guide covers the full sequence from DNS to application.

A browser showing a connection-refused error beside a terminal with the server not running

Is it you or the site?

Two checks, thirty seconds, and they split the problem cleanly.

  1. Does another site work? If everything is refused, look at your own machine or network — a local proxy setting, a security product, a captive portal.
  2. Does it fail from a second network? Mobile tethering is enough. Working elsewhere means the block is on your current network, not on the site.

The port checker answers this from outside your network entirely, and it reports closed and filtered as separate results — which is exactly the distinction the browser hides.

If it is your side

  • A proxy configured that no longer exists. Uninstalled VPNs and security tools leave the setting behind; every connection is then attempted against a dead address.
  • Local firewall or security suite rejecting outbound connections on that port.
  • A hosts file entry pointing the name at 127.0.0.1 — the connection reaches your own machine, which refuses because nothing is listening there.
# Is something redirecting this name locally?
grep -i example.com /etc/hosts            # macOS, Linux
# Windows: C:\Windows\System32\drivers\etc\hosts

# Is a proxy set that you did not intend?
env | grep -i proxy
scutil --proxy 2>/dev/null | head

Server side: the four causes, in order of frequency

1. The service is not running

Simple, common, and worth confirming rather than assuming. A process that exited on an unhandled error or was killed for memory leaves the port closed while the host stays perfectly reachable.

systemctl status nginx --no-pager
sudo ss -tlnp | grep -E ':(80|443)\s'          # what is actually listening
sudo journalctl -u nginx --since '1 hour ago' --no-pager | tail -20
sudo journalctl -k --since '1 hour ago' | grep -i 'killed process'   # OOM

2. It is listening, but not where you can reach it

This is the cause that wastes the most time, because systemctl status reports the service as active and healthy. A process bound to 127.0.0.1 accepts connections from the machine itself and refuses everything from outside — so it works when you test over SSH and refuses every real visitor.

sudo ss -tlnp | grep ':443'
# LISTEN 0 511 127.0.0.1:443  -> loopback only: refuses external connections
# LISTEN 0 511       *:443    -> all interfaces: reachable
# LISTEN 0 511    [::]:443    -> IPv6 (often covers IPv4 too, depending on config)

The fix is in the service's own configuration — nginx listen, an application's bind address, a container's published port. Testing from the server itself cannot detect this, which is precisely why it survives.

If the service works when you curl it on the server and refuses from anywhere else, stop reading logs. That exact combination is the signature of a loopback binding, and one ss line confirms it.

3. A firewall rejecting rather than dropping

Firewalls can discard a packet silently or answer it with a refusal. Which one you configured decides whether the visitor gets a timeout or an instant refusal — and an instant refusal from a firewall looks exactly like a stopped service.

# Linux
sudo iptables -L -n --line-numbers | grep -E 'REJECT|DROP'
sudo ufw status verbose
sudo firewall-cmd --list-all

# Is the port allowed at all?
sudo ss -tlnp | grep ':443'      # listening?
sudo iptables -L INPUT -n | grep 443

Cloud providers add another layer above the host: a security group or network ACL can reject before a packet ever reaches your firewall. Check both, because the host-level rules can be perfectly permissive while the cloud rule closes the port.

4. Containers and port mapping

A container listening correctly inside its own namespace is unreachable if the port is not published, or if it is published only on loopback. The application logs look healthy from inside and the outside world gets a refusal.

docker ps --format '{{.Names}}\t{{.Ports}}'
# 0.0.0.0:8080->80/tcp     reachable externally
# 127.0.0.1:8080->80/tcp   loopback only — external connections refused
# 80/tcp                   not published at all
A running service bound only to a loopback interface, accepting a local connection while refusing one arriving from outside
A healthy service on the wrong interface refuses every external connection while every local test succeeds.

Port 80 works and 443 does not (or the reverse)

When one port answers and the other refuses, the network is proven fine and the problem is a specific listener. That is a useful and frequently overlooked result.

for p in 80 443; do
  printf 'port %-4s ' "$p"
  nc -vz -w 5 example.com "$p" 2>&1 | tail -1
done

Refused on 443 with 80 open usually means TLS was never configured, the configuration failed to load, or the certificate file the server points at is missing — many servers refuse to start their TLS listener entirely rather than start without a valid certificate. Check the configuration test output rather than only the service status:

nginx -t          # names the failing directive and file
apachectl configtest

The "it works locally" trap

Nearly every cause above is invisible from the server. Loopback bindings, host firewalls, cloud security groups and unpublished container ports all permit local connections and refuse external ones, so the entire class survives any test run on the machine itself.

Test from outside, always. The port checker connects from an unrelated network and distinguishes open, closed and filtered — the three outcomes that map exactly onto the three causes in the table at the top.

Preventing the recurrence

A refusal means a total outage for that service, with no partial state and no gradual degradation. Two things reduce the time it lasts:

  • Watch the port from outside. An internal health check running on the same host cannot detect a loopback binding or a firewall rule — it is on the wrong side of both.
  • Alert on the transition, not on a threshold. There is no "slightly refused"; the state changes in one step, so the first failed external check is the signal.

Scheduled monitoring connects from outside on the ports you register and records every result, which turns "the site was down for a while last night" into a start time, an end time and a duration you can line up against a deploy or a restart.

An internal health check reporting success from inside the host boundary while an external check reports refusal
A check running on the host is inside every barrier that causes this error. Only an external check sits where visitors do.

A working order

  1. Confirm it is refusal, not timeout — nc -vz distinguishes them immediately.
  2. Check whether other sites fail, to split your side from the server's.
  3. Test both 80 and 443. One working proves the network path.
  4. On the server, check what is listening and on which interface — this is where the loopback case is caught.
  5. Check the firewall, host-level and cloud-level.
  6. Check container port publishing, if containers are involved.
  7. Verify from outside after every change, never from the server.

How to check right now

Use the port checker to see open, closed and filtered from outside your network — the fastest way to confirm a refusal is real and not local. Ping and TCP checks confirm the host is reachable at all, and traceroute shows whether the path completes. If the port is open and the failure is above TCP, the SSL checker and the header checker continue from there.

A recorded series of connection checks showing an abrupt transition from open to refused at a single point in time
Refusal has no gradual phase. The state changes in one step, which makes the first external failure the whole signal.

Frequently asked questions

How is this different from a timeout?

A refusal is an answer: the host received your packet and replied that nothing accepts on that port. A timeout is silence, which usually means a firewall discarding packets or an address that no longer hosts anything. Opposite causes, similar-looking messages.

Is it my problem or the site's?

If other sites load and a second network gives the same refusal, it is the site's. If everything is refused on one network only, it is that network — a proxy setting, a security product or a captive portal.

The service is running but connections are refused.

Check which interface it is bound to. A process on 127.0.0.1 reports as healthy, accepts local connections and refuses every external one. One ss -tlnp line settles it.

Will restarting the router help?

Rarely, and only if a captive portal or a stale local setting is involved. A refusal coming from the destination is unaffected by anything on your network.

Why does port 80 work while 443 is refused?

The network path is fine and the TLS listener is not running. Most often the configuration failed to load or the certificate file it references is missing — many servers decline to start the TLS listener at all rather than serve without a valid certificate.

How do I find out quickly next time?

Monitor the port from outside the host. Internal checks sit inside the firewall and inside the loopback boundary, so they pass through exactly the conditions that cause this error.

Checklist

  • Confirm refusal rather than timeout before investigating anything.
  • Check whether other sites fail, and whether a second network behaves differently.
  • Test 80 and 443 separately — one working proves the path.
  • Look at the listening interface, not just the service status.
  • Remember that a loopback binding passes every test run on the server.
  • Check host firewall and cloud security rules separately.
  • Verify container ports are published beyond loopback.
  • Read the configuration test output when a TLS listener will not start.
  • Test from outside after every change.
  • Monitor the port externally; internal checks cannot see this class of failure.

Check your website right now

Check if your site is reachable →
More articles: Networking
Networking
Cloudflare Blocked in Russia? Why Sites Fail and How to Fix It
20.07.2026 · 2 943 views
Networking
Your Site Is Blocked in Russia: Owner's Guide
13.07.2026 · 1 143 views
Networking
ERR_CONNECTION_TIMED_OUT: Fix It in Chrome, Windows and Android
23.06.2026 · 1 040 views
Networking
IP Geolocation Accuracy: How It Works and Where It Fails
11.03.2026 · 1 019 views