OpenSSL Guide
How to Check an SSL Certificate with OpenSSL: Every Command
On this page
- Check a live website's SSL certificate
- View a local certificate file with OpenSSL
- Read a DER-encoded certificate (.der, some .crt/.cer files)
- Check SSL certificate expiration with OpenSSL
- Show specific certificate fields
- Check the certificate chain with OpenSSL
- Download a certificate from a website with OpenSSL
- Verify a certificate against a CA bundle
- Check which TLS versions a server supports
- Check that a certificate matches its private key
- Quick reference
Every code example on this page will update as you type. Commands become copy-paste ready for your own site.
Check a live website's SSL certificate
To connect to a server and dump its certificate in human-readable form:
openssl s_client -connect example.com:443 -servername example.com \
</dev/null 2>/dev/null | openssl x509 -text -nooutWhat each part does:
s_client -connect example.com:443: opens a TLS connection to the server-servername example.com: sends SNI, so you get the right certificate on shared hosting (don't skip this)</dev/null: closes the connection immediately instead of hanging2>/dev/null: hides connection noiseopenssl x509 -text -noout: decodes the certificate into readable text
Typical output (truncated):
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 04:3a:...
Issuer: C=US, O=Let's Encrypt, CN=R13
Validity
Not Before: Jun 10 04:22:11 2026 GMT
Not After : Sep 8 04:22:10 2026 GMT
Subject: CN=example.com
...The two lines most people are looking for are Issuer (who signed it) and Not After (when it expires).
Prefer not to use the terminal? ChillSSL SSL monitoring watches your certificates automatically and alerts you before they expire. No commands required.
To check a non-standard port (a mail server, database, or admin panel), change the port. Common examples:
openssl s_client -connect mail.example.com:465 </dev/null 2>/dev/null | openssl x509 -noout -dates
openssl s_client -connect mail.example.com:993 </dev/null 2>/dev/null | openssl x509 -noout -dates
openssl s_client -connect mail.example.com:995 </dev/null 2>/dev/null | openssl x509 -noout -dates
openssl s_client -connect app.example.com:8443 </dev/null 2>/dev/null | openssl x509 -noout -datesPorts 465 (SMTPS), 993 (IMAPS), 995 (POP3S), 8443 and 9443 are common for mail servers and application admin panels.
View a local certificate file with OpenSSL
If the certificate is already on disk in PEM format (the Base64 text format starting with -----BEGIN CERTIFICATE-----), use openssl x509 directly. This is the command behind "openssl view certificate," "openssl read certificate," "openssl show certificate," and "openssl display certificate." They are all the same operation:
openssl x509 -in certificate.pem -text -noout-in certificate.pem: the file to read (.pem,.crt, and.cerare often PEM, but not always (see the DER section below))-text: full human-readable dump-noout: suppress re-printing the encoded certificate block
To dump everything including the Base64 block (useful when you're re-assembling a bundle), drop -noout:
openssl x509 -in certificate.pem -textRead a DER-encoded certificate (.der, some .crt/.cer files)
Some .crt and .cer files are PEM while others are DER (binary); the file extension alone doesn't tell you which. If openssl x509 complains with unable to load certificate, the file is probably DER. Tell OpenSSL the input format:
openssl x509 -inform der -in certificate.der -text -nooutTo convert DER to PEM so other tools can use it:
openssl x509 -inform der -in certificate.der -out certificate.pemCheck SSL certificate expiration with OpenSSL
For just the validity window of a local file:
openssl x509 -in certificate.pem -noout -datesnotBefore=Jun 10 04:22:11 2026 GMT
notAfter=Sep 8 04:22:10 2026 GMTOnly the expiry date:
openssl x509 -in certificate.pem -noout -enddateExpiry date of a live website:
openssl s_client -connect example.com:443 -servername example.com \
</dev/null 2>/dev/null | openssl x509 -noout -enddatenotAfter=Aug 29 21:41:26 2026 GMTTest whether a certificate expires within N seconds, handy in scripts and cron jobs. This checks for expiry within 30 days (2,592,000 seconds):
openssl x509 -in certificate.pem -noout -checkend 2592000It prints Certificate will not expire or Certificate will expire and sets the exit code accordingly, so you can alert on it:
if ! openssl x509 -in certificate.pem -noout -checkend 2592000; then
echo "Renew soon!" | mail -s "SSL expiry warning" [email protected]
fiScripts like this work until the server they run on is the thing that breaks. ChillSSL monitors your certificates externally and emails you before expiry. No cron required.
Show specific certificate fields
You rarely need the full dump. Combine -noout with field flags:
Subject (who the certificate is for):
openssl x509 -in certificate.pem -noout -subjectIssuer (who signed it):
openssl x509 -in certificate.pem -noout -issuerSerial number:
openssl x509 -in certificate.pem -noout -serialSHA-256 fingerprint (the value shown in browser certificate viewers and in ChillSSL's certificate details):
openssl x509 -in certificate.pem -noout -fingerprint -sha256On older OpenSSL releases, use openssl dgst -sha256 instead of piping to openssl sha256.
Subject Alternative Names: every domain the certificate actually covers:
openssl x509 -in certificate.pem -noout -ext subjectAltNameX509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.comModern browsers ignore the Subject Common Name for hostname validation. The SAN extension determines which hostnames the certificate is valid for. If a browser says the certificate doesn't match the domain, this is the field to check. Coverage is determined by the SAN list, not the subject CN.
Certificate purpose: which uses the certificate is valid for:
openssl x509 -in certificate.pem -noout -purposeSSL client : Yes
SSL server : Yes
S/MIME signing : NoUseful for diagnosing certificates that fail handshakes because they're not authorised for the intended purpose.
Signature Algorithm: commonly needed when checking whether a certificate uses SHA-256 or an older algorithm:
openssl x509 -in certificate.pem -noout -text | grep "Signature Algorithm"Flags combine freely:
openssl x509 -in certificate.pem -noout -subject -issuer -dates -fingerprint -sha256Check the certificate chain with OpenSSL
A valid leaf certificate still throws browser errors if the certificate chain is incomplete. To see every certificate a server actually sends:
openssl s_client -connect example.com:443 -servername example.com \
-showcerts </dev/nullYou'll get a numbered chain:
Certificate chain
0 s:CN=example.com
i:C=US, O=Let's Encrypt, CN=R13
1 s:C=US, O=Let's Encrypt, CN=R13
i:C=US, O=Internet Security Research Group, CN=ISRG Root X1s:is the certificate's subject,i:its issuer- Entry 0 is the leaf; each following entry should be the issuer of the one above it
- The exact intermediate label (here
CN=R13) varies by CA and changes when CAs rotate their intermediates - If entry 1 is missing, the server isn't sending its intermediate. This can cause some browsers, operating systems, and embedded clients to reject the certificate. Fix: How to Fix a Missing Intermediate Certificate
Then scroll to the bottom of the output and check the verdict:
Verify return code: 0 (ok)Anything other than 0 (ok) means validation failed. Common examples include:
21(unable to verify the first certificate): missing intermediate10(certificate has expired): expired somewhere in the chain19(self-signed certificate in certificate chain): untrusted root or self-signed cert
Download a certificate from a website with OpenSSL
To save a site's certificate as a PEM file:
openssl s_client -connect example.com:443 -servername example.com \
</dev/null 2>/dev/null | openssl x509 -out example.com.pemTo capture the full chain instead, use -showcerts and save everything between the BEGIN/END markers. This saves every certificate the server sends, including intermediates:
openssl s_client -connect example.com:443 -servername example.com \
-showcerts </dev/null 2>/dev/null \
| awk '/BEGIN CERT/,/END CERT/' > chain.pem(In ChillSSL, this is the one-click Download PEM button on any certificate's details page.)
Verify a certificate against a CA bundle
To validate a certificate the way a browser does, checking it chains to a trusted root, OpenSSL needs two things: a trusted root CA (or the system CA store) and any intermediate certificates required to build the chain.
Option A (recommended): supply a root CA file plus any intermediates
openssl verify \
-CAfile root.pem \
-untrusted intermediate.pem \
certificate.pem-CAfile should point at trusted root CA certificates, not merely a certificate chain. -untrusted supplies intermediate certificates needed to build the chain without treating them as trust anchors.
Success looks like:
certificate.pem: OKOption B: use the operating system trust store
On Linux, supply intermediates via -untrusted and let OpenSSL find the trusted root in the system store:
openssl verify \
-CApath /etc/ssl/certs \
-untrusted intermediate.pem \
certificate.pemOr, pointing at a single CA bundle file:
openssl verify \
-CAfile /etc/ssl/certs/ca-certificates.crt \
-untrusted intermediate.pem \
certificate.pemThe exact bundle path depends on your Linux distribution (/etc/ssl/certs/ca-certificates.crt on Debian/Ubuntu; /etc/pki/tls/certs/ca-bundle.crt on RHEL/CentOS).
Check which TLS versions a server supports
Force a specific protocol version to see whether the server accepts it:
openssl s_client -connect example.com:443 -tls1_2 </dev/null
openssl s_client -connect example.com:443 -tls1_3 </dev/nullIf the handshake completes, the version is supported. Add -brief (OpenSSL 3.x) to cut through the handshake noise and see just the result:
openssl s_client -connect example.com:443 -brief </dev/nullTesting legacy versions (only do this against your own servers):
openssl s_client -connect example.com:443 -tls1_1 </dev/nullModern OpenSSL builds often refuse TLS 1.0/1.1 client-side entirely, which is itself a sign those versions should be off. For the difference between the protocols and the certificates, see TLS vs SSL.
Check that a certificate matches its private key
Mismatched key and certificate is a common cause of servers failing to start after renewal. Compare the public keys derived from each:
openssl x509 -in certificate.pem -noout -pubkey | openssl sha256
openssl pkey -in private.key -pubout | openssl sha256If the two hashes match, the pair belongs together. (This method works for RSA and ECDSA keys alike, unlike the older modulus-comparison trick.)
On older OpenSSL releases, substitute openssl dgst -sha256 for openssl sha256.
Bonus: inspect a CSR before submitting it to a CA:
openssl req -in request.csr -noout -textQuick reference
| Task | Command |
|---|---|
| View live site cert | openssl s_client -connect host:443 -servername host </dev/null 2>/dev/null | openssl x509 -text -noout |
| View local PEM | openssl x509 -in cert.pem -text -noout |
| View DER file | openssl x509 -inform der -in cert.der -text -noout |
| Expiry dates | openssl x509 -in cert.pem -noout -dates |
| Expires in 30 days? | openssl x509 -in cert.pem -noout -checkend 2592000 |
| SHA-256 fingerprint | openssl x509 -in cert.pem -noout -fingerprint -sha256 |
| Subject + issuer | openssl x509 -in cert.pem -noout -subject -issuer |
| SAN list | openssl x509 -in cert.pem -noout -ext subjectAltName |
| Certificate purpose | openssl x509 -in cert.pem -noout -purpose |
| Full chain from server | openssl s_client -connect host:443 -servername host -showcerts </dev/null |
| Verify against bundle | openssl verify -CAfile root.pem -untrusted intermediate.pem cert.pem |
| Save site cert as PEM | openssl s_client -connect host:443 -servername host </dev/null 2>/dev/null | openssl x509 -out cert.pem |
| Cert matches key? | Compare x509 -pubkey and pkey -pubout hashes |
| TLS versions (brief) | openssl s_client -connect host:443 -brief </dev/null |
| Signature algorithm | openssl x509 -in cert.pem -noout -text | grep "Signature Algorithm" |
Or let monitoring do it for you
These commands are useful for a one-off check. If you are responsible for any of the certificates you are inspecting, ChillSSL SSL monitoring watches them continuously and emails you before expiry. No cron jobs, no manual checks.