How to Check SSL Certificates with OpenSSL

OpenSSL commands for checking SSL certificates: view expiry dates, decode certificates, verify chains, and test TLS connections. Copy-paste commands included.

OpenSSL is the Swiss Army knife for SSL certificates. It's the tool you reach for when browser inspections aren't enough, when you need to automate checks, or when you're debugging a certificate chain issue at 2 AM. Here are the commands you'll use most, with copy-paste examples.

OpenSSL on Windows

OpenSSL isn't installed by default on Windows. You can get it through Git Bash (included with Git for Windows), WSL (Windows Subsystem for Linux), or a standalone installer from slproweb.com. If you're using Git Bash, OpenSSL is already available in your terminal.

1. Connect to a Server and View the Certificate

The most fundamental command -- connect to a server and see what certificate it presents:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null

This outputs the full TLS handshake, including the certificate in PEM format, the certificate chain, and the negotiated protocol and cipher. It's a lot of output, so you'll usually pipe it to another command.

Key flags:

  • -connect host:port -- The server and port to connect to (443 for HTTPS)
  • -servername -- Sends the SNI (Server Name Indication) header, essential for servers hosting multiple domains
  • </dev/null -- Prevents OpenSSL from waiting for input
  • 2>/dev/null -- Suppresses stderr noise

Always use -servername

Without -servername, servers using SNI (most modern servers) may return the wrong certificate or a default certificate. This is the most common reason people get unexpected results with OpenSSL.

2. Check Certificate Expiry Dates

Get just the validity dates:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates

Output:

notBefore=Jan 15 00:00:00 2025 GMT
notAfter=Apr 15 23:59:59 2025 GMT

Check if the certificate expires within a specific window (e.g., 30 days = 2592000 seconds):

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -checkend 2592000

This returns exit code 0 if the cert is still valid beyond 30 days, or 1 if it expires sooner. Perfect for scripting alerts:

if ! openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -checkend 2592000; then
  echo "WARNING: Certificate expires within 30 days!"
fi

3. View Full Certificate Details

See everything about the certificate in human-readable form:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -text

This outputs the complete certificate including:

  • Issuer -- The Certificate Authority
  • Subject -- The entity the cert was issued to
  • Validity -- Not Before and Not After dates
  • Subject Alternative Names -- All domains covered
  • Public Key -- Algorithm and key size
  • Signature Algorithm -- SHA-256, SHA-384, etc.
  • Extensions -- Key usage, basic constraints, CRL distribution points, OCSP responder URL
  • Authority Information Access -- Where to find the issuer's certificate

To extract specific fields:

# Just the subject (domain)
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -subject

# Just the issuer
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -issuer

# Just the SANs
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltName

# Serial number
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -serial

4. Verify the Certificate Chain

Check that the full chain validates properly:

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

The -showcerts flag shows every certificate in the chain, not just the leaf. Look for the Verify return code at the bottom of the output:

  • Verify return code: 0 (ok) -- Chain is valid
  • Verify return code: 21 (unable to verify the first certificate) -- Missing intermediate
  • Verify return code: 20 (unable to get local issuer certificate) -- Root CA not in trust store
  • Verify return code: 10 (certificate has expired) -- Expired certificate in chain

To verify a downloaded certificate against a CA bundle:

openssl verify -CAfile ca-bundle.crt certificate.pem

Or verify a chain where you have the intermediate separately:

openssl verify -CAfile root.pem -untrusted intermediate.pem certificate.pem

OpenSSL is great for debugging. Monitoring is great for sleeping.

Automate your certificate checks and get alerts before expiry.

5. Decode a PEM Certificate File

If you have a certificate file (.pem, .crt, .cer), decode it without connecting to a server:

openssl x509 -in certificate.pem -text -noout

Just the dates:

openssl x509 -in certificate.pem -noout -dates

Just the subject and SANs:

openssl x509 -in certificate.pem -noout -subject -ext subjectAltName

For DER-encoded certificates (binary format):

openssl x509 -in certificate.der -inform DER -text -noout

For PKCS#12 files (.pfx, .p12):

openssl pkcs12 -in certificate.pfx -nokeys -clcerts | openssl x509 -text -noout

6. Test a Specific TLS Version

Check if a server supports a particular TLS version:

# Test TLS 1.2
openssl s_client -connect example.com:443 -servername example.com -tls1_2 </dev/null 2>/dev/null

# Test TLS 1.3
openssl s_client -connect example.com:443 -servername example.com -tls1_3 </dev/null 2>/dev/null

If the connection succeeds, you'll see the handshake output. If the server doesn't support that version, you'll get an error like no protocols available or handshake failure.

To see which protocol and cipher were actually negotiated:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | grep -E "Protocol|Cipher"

7. Check a Certificate on a Non-Standard Port

SSL doesn't only run on port 443. Email servers, databases, and internal services use different ports:

# HTTPS on a custom port
openssl s_client -connect example.com:8443 -servername example.com </dev/null

# SMTP with STARTTLS
openssl s_client -connect mail.example.com:587 -servername mail.example.com -starttls smtp </dev/null

# IMAP with STARTTLS
openssl s_client -connect mail.example.com:143 -servername mail.example.com -starttls imap </dev/null

# MySQL over SSL
openssl s_client -connect db.example.com:3306 -servername db.example.com -starttls mysql </dev/null

The -starttls flag handles the protocol-specific negotiation that happens before the TLS handshake on protocols that upgrade from plain text.

Quick Reference: OpenSSL Commands Cheat Sheet

TaskCommand
Check expiry datesopenssl s_client -connect HOST:443 ... | openssl x509 -noout -dates
Full certificate detailsopenssl s_client -connect HOST:443 ... | openssl x509 -noout -text
View certificate chainopenssl s_client -connect HOST:443 -showcerts ...
Expiry within N seconds... | openssl x509 -noout -checkend SECONDS
Decode a PEM fileopenssl x509 -in cert.pem -text -noout
Test TLS 1.3 supportopenssl s_client -connect HOST:443 -tls1_3 ...
Verify chain manuallyopenssl verify -CAfile root.pem -untrusted intermediate.pem cert.pem
Check SMTP certificateopenssl s_client -connect HOST:587 -starttls smtp ...

When OpenSSL Isn't Enough

OpenSSL is unmatched for debugging and one-off checks. But it has real limitations for ongoing certificate management:

  • No memory. It checks the certificate right now. It doesn't remember what it was yesterday or alert you about tomorrow.
  • No scheduling. You have to run the command. If you don't, nothing happens.
  • No dashboards. Piping output to grep works for one domain. It doesn't scale to 50.
  • No team visibility. The results live in your terminal. Nobody else sees them.

For anything beyond personal debugging, pair OpenSSL with a monitoring tool that watches your certificates continuously. Use OpenSSL to investigate. Use monitoring to prevent.


OpenSSL: because sometimes you need to see exactly what the server is doing, not what the browser thinks it's doing.

Never miss an SSL certificate expiry

Monitor your certificates and get alerts before they expire. Free for up to 3 certificates.