What is the quickest command to check SSL certificate expiry?
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates prints the notBefore and notAfter timestamps in UTC.
Guide
Four methods, in the order most people need them. Every command below was run against a live host, and the output is what it printed — including the one that fails on macOS.
The most direct answer. Pipe a handshake into x509 and ask for the dates. The -servername flag sends SNI, which is required on any host that serves more than one certificate — omit it and you may be shown the wrong one.
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
| openssl x509 -noout -datesnotBefore=Jul 29 22:10:08 2026 GMT
notAfter=Oct 27 22:17:21 2026 GMTBoth timestamps are GMT/UTC. notAfter is the expiry date.
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
| openssl x509 -noout -subject -issuersubject= /CN=example.com
issuer= /C=US/O=SSL Corporation/CN=Cloudflare TLS Issuing ECC CA 3echo | openssl s_client -servername example.com -connect example.com:443 2>&1 \
| grep 'Verify return code' Verify return code: 0 (ok)Any non-zero code is a trust failure. This is a separate question from expiry — a current certificate can still fail here.
echo | openssl s_client -servername example.com -connect example.com:443 -showcerts 2>/dev/null \
| grep -c 'BEGIN CERTIFICATE'4A count of 1 on a publicly issued certificate usually means the intermediate is missing from the server configuration.
Already installed nearly everywhere, and the verbose output includes the certificate summary without a second command.
curl -sS -o /dev/null -vI https://example.com 2>&1 \
| grep -E 'start date|expire date|subject:|issuer:'* subject: CN=example.com
* start date: Jul 29 22:10:08 2026 GMT
* expire date: Oct 27 22:17:21 2026 GMT
* issuer: C=US; O=SSL Corporation; CN=Cloudflare TLS Issuing ECC CA 3curl sends SNI automatically from the URL, so there is no equivalent of the -servername trap here.
For a cron job or a CI step, you want a pass/fail rather than text to read. openssl x509 -checkend does exactly that.
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
| openssl x509 -noout -checkend 2592000
echo "exit=$?"exit=02592000 is 30 days in seconds. Exit 0 means it will still be valid then; exit 1 means it expires within the window. Note the inversion — the failing case is the one that exits non-zero, which is what you want in CI.
These are the differences that turn a working command into a confusing error on someone else's machine.
Useful for a quick look, unreliable as a verification method, for the reasons listed underneath.
Select the padlock in the address bar, then the connection or certificate entry. Every major browser exposes the validity window and the issuer this way.
The “not after” or “expires on” date is the one that matters. Browsers usually render it in your local timezone rather than UTC.
A browser can complete a chain using an intermediate it cached from another site. That makes it the worst tool for spotting a server that is not sending its full chain.
Every method above is a snapshot that is true only at the moment you run it. The failure mode of manual checking is forgetting.
The ExpiryBeacon checker performs the same server-side handshake and returns validity, trust, issuer, covered names, chain depth, protocol, cipher, and fingerprint in one result.
Signing in with Google puts the endpoint on a daily scheduled check at 08:00 UTC and keeps a durable history of what each check found.
Choose 30, 14, or 7 days per monitor. With email alerts enabled, a state change sends one message — entering the window, losing trust, expiring, failing a check, or recovering — with repeats suppressed.
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates prints the notBefore and notAfter timestamps in UTC.
Use openssl x509 -noout -checkend followed by a number of seconds. It exits 1 if the certificate expires within that window and 0 if it does not, so a CI step fails only when action is needed.
macOS ships LibreSSL rather than OpenSSL, and LibreSSL's x509 command has no -ext option. openssl x509 -noout -text | grep -A1 'Subject Alternative Name' returns the same information on both.
Yes — change the port after the colon in -connect. ExpiryBeacon's own checker supports 443, 8443, and 9443.