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 input2>/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 validVerify return code: 21 (unable to verify the first certificate)-- Missing intermediateVerify return code: 20 (unable to get local issuer certificate)-- Root CA not in trust storeVerify 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
| Task | Command |
|---|---|
| Check expiry dates | openssl s_client -connect HOST:443 ... | openssl x509 -noout -dates |
| Full certificate details | openssl s_client -connect HOST:443 ... | openssl x509 -noout -text |
| View certificate chain | openssl s_client -connect HOST:443 -showcerts ... |
| Expiry within N seconds | ... | openssl x509 -noout -checkend SECONDS |
| Decode a PEM file | openssl x509 -in cert.pem -text -noout |
| Test TLS 1.3 support | openssl s_client -connect HOST:443 -tls1_3 ... |
| Verify chain manually | openssl verify -CAfile root.pem -untrusted intermediate.pem cert.pem |
| Check SMTP certificate | openssl 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.
Related Articles
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.