How to check an SSL certificate's expiration date (5 ways)
By Nick Phillips, Founder
An expired SSL certificate is one of those problems that goes from "fine" to "every visitor sees a scary red warning page" with no middle ground. The good news is that the expiration date is public — anyone, including you, can read it off your site in a few seconds.
Here are five ways to do it, ordered from "no terminal required" to "I want to script this." Pick whichever fits the moment.
1. Click the padlock in your browser
The fastest check, no install required.
- Visit the site in Chrome, Firefox, Safari, or Edge.
- Click the padlock in the address bar.
- Look for "Certificate" or "Connection is secure → Certificate is valid".
- The certificate panel will show "Issued on" and "Expires on" dates.
This is fine for a one-off check on a site you can load. It's not great for sites that are already broken (you'll see the warning instead of the padlock), and it doesn't scale past a handful of domains.
2. Use openssl s_client from the terminal
If you want the truth straight from the handshake, this is the canonical way:
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
| openssl x509 -noout -dates
You'll get back two lines:
notBefore=Jan 1 00:00:00 2026 GMT
notAfter=Apr 1 23:59:59 2026 GMT
notAfter is the expiration date.
A few notes that trip people up:
- The
-servernameflag matters. Without it, you'll get whatever cert the server hands out for an empty SNI — often the wrong one on shared hosts or CDNs. - The
echo |at the start is what tellss_clientto close the connection after the handshake. Without it, it'll sit there waiting for HTTP input. - This works even when the cert is expired or invalid —
opensslwill still print the dates, it just won't trust the chain.
If you want a more human format:
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
| openssl x509 -noout -enddate \
| cut -d= -f2
That spits out just the date string.
3. Use curl -vI
If you have curl handy and don't want a second tool:
curl -vI https://example.com 2>&1 | grep -E "expire date|start date"
You'll see something like:
* start date: Jan 1 00:00:00 2026 GMT
* expire date: Apr 1 23:59:59 2026 GMT
curl actually prints the cert chain in the verbose output, so you can drop the grep if you want to see the issuer, SANs, and the rest. The trade-off vs. openssl s_client: curl is more permissive about how it surfaces handshake details, but it's also more likely to give you a useful answer when the only thing you remember to type is "the curl one."
4. Use a free online checker
For sites you don't control, or when you're on a machine without a shell handy, an online checker is the path of least resistance.
We built Otterwatch's free SSL checker for exactly this case — paste a domain, get back the expiration date, the issuer, the SAN list, and a few common configuration findings. No signup, no tracking, no ads.
A few others worth knowing about:
- SSL Labs Server Test by Qualys — the deepest read on your TLS configuration overall, including cipher suites and protocol versions. Slower (it does a thorough scan) and overwhelming if you only want the date, but the gold standard for one-off "is my whole TLS setup OK" reviews.
- whatsmychaincert.com — narrower focus, useful when you suspect an intermediate-chain problem rather than a date problem.
The advantage of any online checker over the browser path is that it works for sites that are already broken — the checker doesn't refuse to connect just because the cert is expired or self-signed.
5. Read it from Python (or any language)
If you want to script this — say, as part of a CI check or a homegrown monitoring loop — Python's standard library can do it without any third-party dependencies:
import socket
import ssl
from datetime import datetime, timezone
def expiry(host, port=443):
ctx = ssl.create_default_context()
with socket.create_connection((host, port), timeout=10) as sock:
with ctx.wrap_socket(sock, server_hostname=host) as ssock:
cert = ssock.getpeercert()
expires = datetime.strptime(cert["notAfter"], "%b %d %H:%M:%S %Y %Z")
return expires.replace(tzinfo=timezone.utc)
print(expiry("example.com"))
Two things to watch out for in a script:
- The default context verifies the chain. If you want to read the date off an already-broken certificate, you need to disable verification (
ctx.check_hostname = False; ctx.verify_mode = ssl.CERT_NONE). Don't do that in production code that relies on trust — only when the goal is purely informational. notAfteris in GMT. The example above tags it as UTC, which is what you almost always want.
The same pattern works in any language with a TLS library: open a socket, complete the handshake, ask the library for peer_cert, read the notAfter field.
Which one should you use?
| If you want to… | Use |
|---|---|
| Quickly eyeball one site | The browser padlock |
| Get exact dates from any site, including broken ones | openssl s_client |
Verify the cert is what curl would actually negotiate |
curl -vI |
| Check a site from a phone or borrowed laptop | An online checker |
| Bake the check into a script or CI step | The Python snippet (or your language's equivalent) |
There's no single "right" tool — they're all reading the same notAfter field off the same certificate. Pick the one that's already at hand.
Why this is worth a checklist item
A certificate expiring on a Saturday is a recurring small disaster in our industry. Every few months a major service hits the headlines for it; the GitHub Pages CA mishap and the Microsoft Teams outage are the public examples, but the long tail of "small SaaS goes down for six hours on a weekend because nobody noticed the renewal failed" is the part that doesn't make the news.
Five seconds to read a date is the cheapest insurance there is. The harder part is remembering to do it — which is why this whole site exists. If you'd rather have someone send you an email 30 days ahead instead of running a command on a date you'd otherwise forget, start watching a site for free and Otis will take it from here.
Either way, now you have five different ways to answer the question "when does this thing expire?" — pick a favorite and bookmark this page for the next time you forget which flags openssl s_client wants.
Catch the next cert expiry before your users do.
Otterwatch checks your SSL certificates daily and emails you 30 days before they expire. Five sites free.
Start watching →