SSL certificate checker
One real TLS handshake from our servers, and the certificate your visitors are actually served: issuer, expiry, days left, TLS version. No account, nothing installed.
The check runs from our servers and needs JavaScript. Everything below works without it.
Free plan, ten checks, no card. This page checks once; an account checks on a schedule and tells you when it changes.
Nobody emails you before it expires any more
Two things changed, and together they moved certificate expiry from "solved problem" back onto the list of things that take a site down on a Sunday.
The safety net is gone. Let's Encrypt ended expiration notification emails in June 2025 — reasonably, since they were retaining millions of addresses to send warnings that automation should make unnecessary. Plenty of teams did not realise those emails were the only thing standing between them and an outage.
The window is shrinking. The CA/Browser Forum adopted Ballot SC-081v3, which walks the maximum lifetime of a public TLS certificate from 398 days down to 47 by March 2029. Renewal stops being an annual chore you can survive doing by hand and becomes something that happens roughly every six weeks, forever — and more renewals means more chances for one to fail quietly.
Automated renewal is not monitoring
A cron job running certbot renew
tells you a process ran. It does not tell you that visitors
are being served a valid certificate. Those are different
claims, and the gap between them is where the outages live:
- The reload never happened. nginx and Apache read the certificate into memory at startup; a renewal without a successful reload keeps serving the old one from a file that is perfectly up to date;
- The deploy hook failed but the exit code didn't. A typo'd service name, a permission change, a full disk — many of these end with a failed step inside a script that still exits 0;
- One node out of several. Renewed on web-1, broken on web-2 since a package upgrade. From a browser you are fine two times out of three;
- The edge has its own copy. CDN, load balancer, API gateway, mail server. The origin is healthy; the thing customers connect to is not;
- The container image has the certificate baked in. Renewal happens outside the image; the running pod keeps serving what it was built with.
Every one of these leaves your monitoring green if your monitoring is "did the renewal job run". The only claim worth alerting on is the one your visitors experience — and that is checked from the outside, over a real handshake. The long version, including what to watch besides the expiry date, is in nobody emails you before your certificate expires any more.
The same thing by hand
No tool required if you would rather not paste your hostname into someone's form:
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \ | openssl x509 -noout -subject -dates -issuer
Wrap it in a script, subtract the dates, alert under a threshold, run it from cron — and you have a working certificate monitor with one flaw: nothing watches the monitor. That cron job lives on a host that can reboot, lose its crontab or run out of disk, and its silence looks exactly like good news. If you go this route, at minimum put a heartbeat on the script itself.
Questions
What exactly does this check?
It opens a real TLS connection to the hostname from our servers and reads the certificate that is actually served: who issued it, when it expires, which TLS version the handshake negotiated, and whether a browser would trust the chain. It is the same handshake your visitors make, not a lookup in a database.
My certificate renews automatically. Why check it?
Because a renewal that ran is not a certificate that is being served. nginx and Apache read the certificate into memory at startup, so a renewal without a successful reload leaves the old one on the wire — from a file on disk that is perfectly up to date. The same gap opens when a deploy hook fails without a non-zero exit, when one node out of several is broken, or when the edge keeps its own copy.
Why is 14 days the warning line?
Because certificate lifetimes are shrinking. The CA/Browser Forum walks the maximum from 398 days down to 47 by March 2029, and the classic "warn 30 days ahead" is nearly two thirds of a 47-day certificate — a threshold like that fires constantly and gets muted within a week. Fourteen days is roughly the point where an ACME client has already failed at least one renewal attempt.
Do you store the hostname I check?
The result is cached for ten minutes so a repeated click does not hit your server again, and the hostname appears in our request log. Nothing else is kept, and no account is created.
One check now, or every hour from three regions
This page answers "is it valid right now". It cannot answer "was it still valid at 4 a.m. on Sunday" — and that is the question that costs money. An HTTP check watches the same handshake continuously from several regions and warns you 7, 14 or 30 days before expiry, in Telegram, Slack, email or a webhook.
Other free tools: HTTP status checker and the cron expression tester. All three are on the tools page.