How to Check SSL Certificate Expiry with OpenSSL from the Command Line

VigilDog Team · August 31, 2026 · 6 min read

A certificate that expires at 2 a.m. doesn't warn you first, it just starts throwing errors in every browser, mobile app, and API client that touches your domain. The good news is that OpenSSL, already installed on nearly every server you run, can tell you the exact moment that will happen. This guide walks through how to check SSL expiry with OpenSSL from the command line: a quick one-liner, a scriptable pass/fail check, and how to verify the whole chain rather than just the leaf.

Read the expiry straight off the wire

The fastest way to check a live site is to open a TLS connection and print the certificate's validity dates. This single command connects, pulls the leaf certificate, and shows its notBefore and notAfter timestamps:

The -servername flag matters more than it looks: without it, a host serving multiple domains over SNI may hand back the wrong certificate, and you'll read the expiry of a cert that isn't the one your users see. Always pass the hostname there, and use port 443 for HTTPS (or 465/993/587 with -starttls for mail).

If you only need a human-readable sanity check for one domain, the free SSL checker gives you the same information in a browser without touching a terminal, handy when you're on someone else's machine.

  • Live site dates: echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
  • Full certificate detail: append -text instead of -dates to see the issuer, SANs, and key type
  • Mail servers: add -starttls smtp before -connect for port 587

Check a certificate file on disk

When you already have the .pem or .crt file, say, straight from your ACME client or a load-balancer export, you don't need a network round trip at all. Point OpenSSL at the file and ask for the end date only:

openssl x509 -enddate -noout -in cert.pem prints a single line like notAfter=Nov 3 12:00:00 2026 GMT. The -noout flag suppresses the base64 certificate body so you get just the date, which is exactly what you want when you're grepping across a directory of certs.

Ask a yes/no question with -checkend

Parsing dates is fragile, so OpenSSL gives you a cleaner primitive for automation. The -checkend flag takes a number of seconds and exits 0 if the certificate is still valid that far into the future, or 1 if it will have expired by then. No date math on your end.

openssl x509 -checkend 2592000 -noout -in cert.pem; echo $? asks whether the cert survives the next 30 days (2,592,000 seconds). An exit code of 1 is your trigger to renew. Because it returns a real exit status, you can drop it straight into a shell if, a Makefile target, or a CI step that fails the build when a bundled cert is about to lapse.

Verify the whole chain, not just the leaf

A surprising share of 'expired certificate' incidents aren't the leaf certificate at all, they're an expired or missing intermediate. Clients build a path from your server's certificate up to a trusted root, and if any link in that path has lapsed or your server forgot to send the intermediate, the connection fails even though your leaf looks fine.

Pull the full set your server actually presents with openssl s_client -connect example.com:443 -servername example.com -showcerts, then validate the path with openssl verify -untrusted chain.pem cert.pem. If verification complains about a missing issuer, your server is under-sending the chain; if it reports an expired certificate for something you didn't touch, an intermediate is the culprit. Our walkthrough on what to do when an SSL certificate has expired covers the fixes for each case.

The diagram below shows why checking only the leaf is not enough, every certificate above it has its own clock.

Root CAin the trust storeIntermediatemust be installedYour certificateleaf, for your domain
The TLS certificate chain of trust

Turn the check into an alert

A check you run by hand is a check you'll eventually forget. The usual home-grown answer is a small script wrapped around -checkend, run from cron, that emails you when any cert drops under a threshold:

That works for a handful of hosts. The trouble starts when you're responsible for dozens of domains across different registrars and load balancers, the cron job runs from one box, can't see certs behind other firewalls, silently dies if that box reboots, and has no memory of which alerts already fired. OpenSSL is the right tool for a spot check; it's the wrong tool for a fleet.

  • days_left=$(( ( $(date -d "$(openssl x509 -enddate -noout -in cert.pem | cut -d= -f2)" +%s) - $(date +%s) ) / 86400 ))
  • Alert when days_left is under 14, 7, and 1, one warning is easy to miss
  • Watch the intermediate expiry too, not just the leaf

When one-off checks stop scaling

OpenSSL should stay in your toolkit for debugging a single handshake, nothing beats it for answering 'what is this server actually presenting right now.' But once expiry tracking becomes a standing responsibility across many client domains, you want something that watches from the outside, remembers state, and nags the right person before the deadline. That's exactly what VigilDog's monitoring does for SSL, domain expiry, DNS drift, and email authentication in one place, with white-label reports if you're running this for clients. Let the dog watch the calendar so you don't have to.

Questions

Frequently asked

Do I need the private key to check a certificate's expiry?

No. Expiry lives in the public certificate, so both the s_client and file-based commands here work with only the certificate. The private key is never required just to read validity dates.

Why does OpenSSL show a different expiry than my browser?

Almost always SNI. If you omit -servername, a server hosting multiple domains may return its default certificate instead of the one your browser negotiates. Add -servername with the exact hostname and the dates should match.

What does -checkend actually return?

It's an exit code, not printed output. OpenSSL exits 0 if the certificate is still valid for the number of seconds you pass, and 1 if it will have expired by then, which makes it ideal for scripts and CI gates.

Stop checking certs by hand

VigilDog watches SSL, domain, DNS, and email health from the outside and warns you well before anything expires, with reports you can white-label for clients.

Your first domain is free forever · no card