StatusDetector
Notebook

DNS vs SSL vs HTTP errors: what actually broke?

A broken page can fail at any of four layers — DNS, TCP, TLS, or HTTP. The error message you see almost never names the layer, but the layer is the entire answer. Here's how to tell them apart in under a minute.

StatusDetectorMay 13, 202614 min read

When a website fails to load, the browser shows a generic "this site can't be reached" message that hides the actual cause. The site might be fine and DNS is broken. DNS might be fine and the TLS certificate expired. The certificate might be valid and the application is returning 500s. Each of those is a different bug with a different fix, and the browser collapses all of them into the same red rectangle.

There are four layers where a page request can fail: DNS, TCP, TLS, and HTTP. The four layers happen in that order, and the request can't reach the next one until the current one succeeds. So if you know which layer broke, you've narrowed the bug-hunt to about a quarter of the possible causes.

This is the field guide for distinguishing the four. Each one has a distinct fingerprint in tools, browser dev-console, and command-line probes. Once you can read the fingerprint, "the site is broken" turns into "the TLS chain is missing the intermediate certificate" — and the fix follows.

The four-layer model

Every browser request to https://example.com/path is actually a stack of four protocol steps, each one depending on the one beneath it:

You move down the list in order, and you can't skip steps. If DNS fails, you never reach TCP. If TCP fails, you never reach TLS. The error you see is always the first layer that broke.

That last point is the entire diagnostic shortcut. The error fingerprint tells you the layer; the layer tells you the kind of fix.

DNS-layer failures

The browser doesn't know where to connect. The domain name doesn't translate to a usable IP address.

What it looks like

  • Browser shows "this site can't be reached" with DNS_PROBE_FINISHED_NXDOMAIN (Chrome), "server not found" (Firefox), or "Safari can't find the server" (Safari).
  • Command line: dig example.com returns NXDOMAIN, SERVFAIL, or an empty ANSWER section.
  • ping example.com says "cannot resolve" rather than failing on a packet level.

What's actually wrong

  1. The domain doesn't exist (NXDOMAIN). The name is mistyped, the domain was never registered, or it expired and was released. Check the spelling, then check WHOIS — see if the registration is still active.
  2. The authoritative DNS server is broken (SERVFAIL). The domain exists but the nameservers configured for it are timing out or returning errors. The domain owner's DNS hosting is the cause.
  3. The domain is in clientHold (the registrar removed it from the zone for non-payment, ICANN compliance, or trademark dispute). It resolves nowhere — even though the domain is technically still registered. Our Domain Status Analyzer flags this state directly.
  4. Your resolver is misbehaving. Less common but real: your ISP's DNS resolver cached a bad answer, or its upstream is down. Switching to 1.1.1.1 or 8.8.8.8 at the OS level rules this out in seconds.
  5. A recent DNS change hasn't propagated. Different resolvers worldwide cache for different times. See DNS propagation isn't a thing — here's what's actually happening for the real model.

How to confirm

Terminal
$ 

If different resolvers return different answers (or some return nothing), you have a propagation or resolver-level issue, not a "the site is down" issue. The DNS Lookup tool does this from our infrastructure across multiple resolvers in one click.

TCP-layer failures

DNS succeeded. The browser opened a connection to the resulting IP and the connection failed at the socket level. The site's server is either not listening, not reachable, or actively refusing.

What it looks like

  • Browser: "this site can't be reached" with ERR_CONNECTION_REFUSED, ERR_CONNECTION_RESET, or ERR_CONNECTION_TIMED_OUT.
  • Command line: curl reports Failed to connect or Connection timed out; nc -v example.com 443 either errors immediately or hangs.
  • Pings might succeed — ICMP can work even when TCP doesn't — which means the host is up but the application isn't listening or the firewall is dropping packets.

What's actually wrong

The three TCP failure modes mean three completely different things, and they're easy to confuse:

  1. Connection refused. The IP exists, the host is up, but nothing is listening on port 443 (or 80). Most commonly, the application server crashed or the wrong service is running on the box.
  2. Connection reset. A TCP connection was established and then closed unilaterally — usually by a firewall, a load balancer with a buggy health check, or middleware that decided the request looked malicious. Connection reset mid-handshake is also a fingerprint for TLS interception by a corporate proxy that doesn't have the destination's certificate.
  3. Connection timed out. The packets to the IP are going into a black hole. Either the host is fully unreachable (network outage between you and it), or a firewall is dropping packets without sending a reject. Timeouts are the most ambiguous failure mode — the network gave up rather than getting a definite answer.

See connection refused vs reset vs timeout for the deep dive on telling these three apart.

How to confirm

Terminal
$ 

If nc connects and openssl s_client also begins a handshake, you've passed TCP cleanly and any remaining error is TLS or HTTP. If nc fails, it's TCP.

TLS / SSL-layer failures

DNS and TCP succeeded. The browser opened an encrypted connection, but the certificate the server presented was rejected. Almost every "your connection is not private" warning in any browser belongs to this layer.

What it looks like

  • Browser: a full-page warning (NET::ERR_CERT_AUTHORITY_INVALID, NET::ERR_CERT_DATE_INVALID, NET::ERR_CERT_COMMON_NAME_INVALID, or SSL_ERROR_UNKNOWN_ISSUER on Firefox).
  • Command line: openssl s_client finishes the handshake but reports verify error:num=X with a code.
  • Some apps (especially mobile or old curl) just refuse to connect with "SSL handshake failed" and no further detail.

What's actually wrong

Almost every TLS failure is one of four causes:

  1. The certificate expired. The most common cause; certificates are time-bounded and someone forgot to renew. NET::ERR_CERT_DATE_INVALID.
  2. The certificate is for the wrong hostname. The server presented a cert for example.com and you asked for www.example.com (or vice versa). NET::ERR_CERT_COMMON_NAME_INVALID.
  3. The certificate chain is incomplete. The server only sent its own cert, not the intermediate CA cert. Browsers cache common intermediates, so the page might work in one browser and fail in another. NET::ERR_CERT_AUTHORITY_INVALID from some clients, success from others — a confusing fingerprint.
  4. The issuer isn't trusted. Self-signed cert, internal CA not installed on the client, an old CA that has since been distrusted by browser root stores. NET::ERR_CERT_AUTHORITY_INVALID.

See reading SSL certificate errors for the full field guide.

How to confirm

Terminal
$ 

If the certificate is valid and the chain is complete, you've passed the TLS layer. Anything remaining is HTTP.

HTTP-layer failures

DNS, TCP, and TLS all succeeded. The encrypted tunnel is up. The application above sent back a status code that isn't 200. This is the only layer where the server is willing to talk to you in detail — every HTTP error comes with a status code, a body, and headers that often name the cause.

What it looks like

  • Browser: a page (often the site's own styled error page) with a status code visible in DevTools → Network.
  • Command line: curl -i https://example.com/path returns headers including HTTP/1.1 502 Bad Gateway (or whatever code applies).
  • Status pages, error pages, JSON error bodies — all of these are HTTP-layer failures.

What's actually wrong

The status code is doing most of the diagnostic work for you. See what HTTP 403, 404, 429, 500, 502, and 503 errors actually mean for the six codes you'll encounter most often. The short version:

  • 4xx codes = the client (or the request) is the problem. Bad URL, missing auth, rate limit, refused by the WAF.
  • 5xx codes = the server is the problem. Application errored, proxy couldn't reach upstream, server refusing on purpose.

How to confirm

Terminal
$ 

If curl returns a 200 but your browser shows an error, the issue is client-side: a service worker, a CORS preflight, a CSP violation, a JS error in the page. DevTools → Console will name it directly.

The decision tree

The whole guide collapses to a five-step check:

  1. Does dig example.com +short return an IP? No → DNS.
  2. Does nc -v example.com 443 connect? No → TCP.
  3. Does openssl s_client -connect example.com:443 show Verify return code: 0 (ok)? No → TLS.
  4. Does curl -sI https://example.com/ return 200? No → HTTP (read the code).
  5. All four succeeded? The problem is in the page's JavaScript or your browser, not the network. Open DevTools → Console.

The Website Down Checker runs this exact sequence from our infrastructure and reports the result of each step. The advantage of running it server-side is that you eliminate your own network, your VPN, your DNS resolver, and your browser as variables — the result reflects the site's view from a third location, not yours.

Common combinations

A few patterns show up often enough to be worth recognising on sight:

  • DNS succeeds but every request returns 502. The site is up at the DNS level but the application is broken or the proxy can't reach the origin. The origin is the issue — check the vendor's status page.
  • TLS handshake fails only on mobile / old apps. The site's certificate chain is missing an intermediate. Modern browsers cached the intermediate and don't notice; the old client doesn't have the cached copy and fails. See reading SSL certificate errors.
  • ping works, curl times out. TCP-layer firewall block. The host is up; port 443 is being filtered.
  • Some users see the site, others don't. Either DNS is mid-propagation (the resolvers some users hit have the new record; others still have the old one), or the site is behind a geographically-distributed CDN and one POP is degraded. See why a website can be down in one country but working elsewhere.
  • Browser shows 200 but the page is blank. HTTP layer is fine; the page's JS errored after load. DevTools → Console is the only place that'll tell you anything.

Frequently asked

The browser shows 'your connection is not private' — is that always a TLS error?

Yes, that exact phrasing is reserved for TLS-layer certificate errors. The browser is telling you it completed the TCP handshake but rejected the certificate at the verification step. Click "Advanced" or "More info" — the browser will give you the specific subcode (AUTHORITY_INVALID, DATE_INVALID, etc.) which names the fix.

If `ping` works, does that mean DNS and TCP are both fine?

DNS yes; TCP no. ping uses ICMP, not TCP. A host can answer ICMP echo while having port 443 filtered or unlistening. Use nc -v host 443 (or telnet host 443) to confirm TCP specifically.

What's the difference between SSL and TLS?

Functionally, none, for our purposes. TLS is the modern successor to SSL; the protocol formerly known as SSL was rebranded to TLS in 1999. "SSL certificate" and "TLS certificate" mean the same thing in practice. Every modern site is using TLS 1.2 or 1.3 under the hood, regardless of which name the documentation uses.

How do I know if it's the site or my company's corporate proxy?

Try the site from your phone on cellular data. If it works there and fails on your work network, the corporate proxy is the cause — usually because it's intercepting TLS and the destination's cert pinning rejects the man-in-the-middle. Sites that work everywhere except your office are almost always a corporate-proxy issue.

StatusDetector

We check whether a website, app, API, or domain is working, broken, expired, parked, or permanently shut down. Free, no signup — run a check or open the shutdown radar.