ERR_CONNECTION_REFUSED is Chrome's way of reporting that the TCP connection itself was rejected. Your machine resolved the domain to an IP address, sent a connection request to that IP, and got an active "no" back before any HTTP happened. That makes it different from a timeout, which is silence, and from NXDOMAIN, which means the name never resolved at all. Something at that address is alive and answering, it just refused to talk to you on that port.
What "refused" means at the TCP level ¶
Every HTTP request starts with a TCP handshake. Your client sends a SYN packet to the server's IP and port, and one of three things comes back:
- SYN-ACK. The port is open, the handshake completes, and HTTP proceeds.
- RST (reset). The connection is actively rejected. The operating system surfaces this as
ECONNREFUSED, and the browser shows ERR_CONNECTION_REFUSED. - Nothing. The packets vanish. After the retry budget runs out you get ERR_CONNECTION_TIMED_OUT instead.
Two things commonly produce that reset. First, nothing is listening: the machine is up but no process has the port bound, so the kernel itself replies with an RST. Second, a firewall configured to REJECT rather than DROP: a REJECT rule sends the reset (or an ICMP unreachable) back explicitly, while a DROP rule discards the packet silently and produces a timeout.
| Error | Stage that failed | What actually happened |
|---|---|---|
| DNS_PROBE_FINISHED_NXDOMAIN | Name resolution | The domain never resolved to an IP address |
| ERR_CONNECTION_REFUSED | TCP connect | The IP replied with a reset, an active rejection |
| ERR_CONNECTION_TIMED_OUT | TCP connect | Packets went unanswered, silence |
Refusal is the noisiest of the three failures and the most informative. It arrives in milliseconds rather than after a 20-30 second wait, and it proves a machine at that IP is powered on and routable. The only question is why it said no. If your failure is at the name-resolution stage instead, see DNS_PROBE_FINISHED_NXDOMAIN.
Server-side causes ¶
- Crashed or stopped process. The web server or application process died and nothing rebound the port, so every SYN to port 443 gets a kernel reset. Classic after an out-of-memory kill or a failed restart.
- Wrong port or wrong interface. The service listens on 8080 while traffic arrives on 80, or it bound to 127.0.0.1 instead of 0.0.0.0 so only local connections work. Common after a config change or a fresh deployment.
- Firewall or security-group REJECT. A host firewall (iptables, nftables, Windows Firewall) or a cloud security rule rejecting traffic on that port. Sometimes intentional, sometimes a rule pushed to the wrong host.
- Resource exhaustion. A process that runs out of file descriptors stops accepting new sockets, and under enough pressure it often crashes outright, at which point the port is unbound and refusals begin. Exhaustion usually shows up as slow responses, then timeouts, then hard refusals.
- Deploy window. During a restart there is a gap between the old process releasing the port and the new one binding it. Refusals that last a few seconds and heal on their own are usually this.
Client-side causes ¶
If the site is fine for everyone else, the refusal is being generated on or near your machine. The giveaway is usually that many sites fail at once, because it is unlikely every server you visit crashed simultaneously.
- Proxy or VPN. A system proxy setting pointing at a proxy that isn't running turns every page load into a refused connection to that dead proxy. VPN kill switches do the same when the tunnel drops. Check your OS proxy settings first.
- Antivirus or security suite. Many products inspect HTTPS by inserting a local proxy between the browser and the network. When that component crashes or updates badly, connections are refused locally. Temporarily disabling web protection is a fast test.
- Hosts file. A leftover entry mapping the domain to 127.0.0.1 or an old IP, from past development work or an ad-block list, sends the browser to an address with nothing listening. Check
/etc/hostson macOS and Linux, or the hosts file under System32 on Windows. - Browser extension. Proxy and privacy extensions can reroute requests. An incognito window with extensions disabled, or a different browser, isolates this in seconds.
The localhost case, for developers ¶
The most common place to meet this error is http://localhost:3000 during development. There is no mystery here: refused on localhost means nothing on your machine is accepting connections on that port. The usual suspects, in order:
- The dev server isn't running. It never started, or it crashed on boot and the error scrolled past. Check the terminal it was started in.
- It's on a different port. Many dev servers bump to 3001 or another port when the default is taken, and print the new port at startup.
- IPv4 vs IPv6 mismatch. On some systems localhost resolves to the IPv6 address
::1first. If the server bound only to the IPv4127.0.0.1, the browser connects to::1, finds nothing, and reports refusal. Browsing to127.0.0.1:3000directly is the test. - Docker port mapping. The container port isn't published, or the app inside the container bound to
127.0.0.1, which is the container's own loopback, so the published port connects to nothing. Bind to0.0.0.0inside containers.
To see what is actually listening, run ss -ltn or lsof -i :3000 on Linux and macOS, or netstat -ano on Windows, then compare the bound address and port against what the browser is dialing.
Down for everyone, or refused just for you ¶
Because refusal happens at the TCP layer, before TLS and before any HTTP request is sent, it produces an unusually clean signal on a multi-method check. isitdown.io probes a target with 4 independent probe methods in parallel, HTTP/1.1 with strict TLS, HTTP/2 with relaxed TLS, a GET with a real browser User-Agent, and a HEAD with a curl User-Agent. All four have to complete the same TCP handshake first, so a genuine connection refusal at the origin fails all four identically.
- All 4 methods fail. The refusal is real and server-side. The process is down, the port is wrong, or a firewall is rejecting everyone.
- All 4 methods pass while your browser gets refused. The block is on your side, a proxy, the hosts file, antivirus, or an extension. Work through the client-side list above.
- A mixed result. Some methods pass and some fail. That is not a connection refusal at all: the site is up but blocking or mishandling a specific request type, a TLS problem, a User-Agent block, or a HEAD refusal. Different failure, different fix.
After the check, confirm from a second network, a mobile hotspot is the quickest. If you operate the site yourself, a free isitdown.io account monitors up to 5 sites with the same four methods every 5 minutes and emails you on failure. An incident only opens after 2 consecutive failed probes, so a few seconds of refusals during a deploy won't page you, and it resolves after 2 consecutive passes.
FAQ ¶
Does ERR_CONNECTION_REFUSED mean the server is offline?
No, usually the opposite. A powered-off or unreachable host produces a timeout, because nothing is there to answer. A refusal means something at that IP, the kernel or a firewall, is alive and actively sending resets. The machine is up; the service on that port is not, or is being shielded.
Why am I getting it on every website at once?
Every site failing simultaneously points to a broken local intermediary: a system proxy that isn't running, a VPN that dropped with a kill switch active, or an antivirus web-protection module that crashed. It is not plausible that every origin server refused you at the same moment.
My server says it's running, so why is localhost refused?
A live process is not the same as a process listening where you are connecting. Check the bound address and port with ss -ltn or lsof. The two classic mismatches are the server on 127.0.0.1 while the browser connects to the IPv6 ::1, and a Docker app bound to the container's loopback so the published port maps to nothing.
Can a firewall cause refused instead of timed out?
Yes. A firewall rule set to REJECT sends an explicit reset or ICMP unreachable, which surfaces as refused. A rule set to DROP discards packets silently, which surfaces as a timeout. Which error you see tells you how the blocking device was configured.