Certificate chain checker

See each certificate a server sends, in order, and whether the chain leads to a root that browsers trust. Free, and no account needed.

We read the chain it serves on port 443.

Try example.com , incomplete-chain.badssl.com or untrusted-root.badssl.com .

The chain prints here

Enter a domain above. Each certificate the server sends prints as its own ticket, site certificate first, with anything missing or untrusted marked.

How a certificate chain works

Your site’s certificate is signed by an intermediate certificate, which is signed by a root certificate. Browsers and operating systems ship with a list of trusted roots. To trust your certificate, a client has to follow the signatures from it, through the intermediates, to one of those roots.

The server’s job is to send its own certificate followed by the intermediates. The root stays on the client. If an intermediate is missing, the client can’t make the link and the connection fails, unless the client fills the gap itself.

How to read the result

  1. Certificate 1 is the site certificate: it should list your domain and be within its dates.
  2. The certificates after it are the intermediates the server sent, each issued by the next one down.
  3. The last one is the root, taken from the trust store when the chain leads to one. If it doesn’t, the result marks the root as untrusted, or shows a torn ticket where the missing intermediate should be.

Common chain errors and how to fix them

Missing intermediate

The server sends only its own certificate. Fix it by serving the full chain file your CA or ACME client provides. With certbot and nginx, that means fullchain.pem, not cert.pem:

nginx
ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

Hosting panels often have a separate “CA bundle” or “chain” field for the intermediates.

Untrusted root or self-signed certificate

The chain ends in a root that isn’t in the public trust stores: a self-signed certificate, a company’s private CA, or a test setup. For a public site, replace it with a certificate from a public CA. Let’s Encrypt is free.

Expired intermediate

The site certificate is current but an intermediate in the chain has expired. This usually means an old bundle saved on the server. Download the current chain from your CA and serve that.

Hostname mismatch

Not a chain problem, but often reported alongside one: the certificate doesn’t list the domain you visited. Issue one that does, or check that the domain points at the right server.

Check a chain from the command line

This prints every certificate the server sends, with its subject and issuer:

Terminal
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null

Each certificate appears as a block, starting with “s:” (subject) and “i:” (issuer). The issuer of each should be the subject of the next. More in Fix “unable to get local issuer certificate”.

Questions

Short answers about this check.

Is the certificate chain checker free?

Yes, with no account. Monitoring with email alerts when a certificate breaks or nears expiry is free for up to 3 domains.

The site works in my browser. Why does the checker say an intermediate is missing?

Browsers cover for it: Chrome downloads the missing intermediate, and Firefox ships a list of known intermediates.

Most other clients don’t: curl, scripts, payment and webhook senders, many apps and monitoring tools. They fail until the server sends the full chain.

Should the server send the root certificate too?

It doesn’t need to. Clients already have the root in their trust store, and sending it only adds bytes to every handshake. The result shows the root from the trust store when the chain leads to one.

Which roots count as trusted?

The ones bundled with Node.js, which come from Mozilla’s root store, the list Firefox and many Linux systems use. Private and company roots show as untrusted.

Can I check a chain on an internal server?

No. The checker connects only to public domain names on port 443, and refuses private, internal and reserved addresses.

Get an email before it expires

Expiry Watch checks the domain every day and emails you 30, 14, 7, 3 and 1 day before the certificate or the registration expires. Free for up to 3 domains.

We check its certificate and registration every day.

We send a link to confirm it first.

Free for up to 3 domains. Every email has a one-click unsubscribe.