Fetch a certificate from a live server
To fetch a server's certificate, run `openssl s_client -connect example.com:443 -servername example.com </dev/null`. The `-servername` flag sends SNI and is essential — without it a virtual-hosted server answers with its default certificate, so you inspect the wrong one. Add `-showcerts` to see the full chain the server sends, and pipe the output through `openssl x509` to decode it. The `</dev/null` closes stdin so the command exits instead of waiting for input.
The basic command #
openssl s_client -connect example.com:443 -servername example.com </dev/null Replace these values
| Placeholder | What to put there |
|---|---|
-connect host:port | Where to connect. Port 443 for HTTPS. |
-servername host | Sends SNI. Omit this and you may inspect the wrong certificate. |
</dev/null | Closes stdin so the command exits rather than waiting for input. |
Just the certificate, decoded #
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName Expected output
subject=CN = example.com issuer=C = US, O = Example CA, CN = Example Intermediate CA notBefore=Aug 16 00:00:00 2026 GMT notAfter=Nov 14 23:59:59 2026 GMT X509v3 Subject Alternative Name: DNS:example.com, DNS:www.example.com
Saving the certificate to a file #
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -out example.com.crt Saving the whole chain #
-showcerts prints every certificate the server sent. Extract them all with sed:
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null \
| sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' \
> chain.pem Then inspect what came back:
openssl crl2pkcs7 -nocrl -certfile chain.pem | openssl pkcs7 -print_certs -noout Reading the verification result #
The last useful line of s_client output is the verdict:
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| grep "Verify return code" Expected output
Verify return code: 0 (ok)
| Code | Meaning | Page |
|---|---|---|
0 (ok) |
Chain validated against your trust store | — |
10 |
Certificate has expired | expiry |
18 |
Self-signed certificate | self-signed vs CA-signed |
19 |
Self-signed certificate in chain | that error |
20 |
Unable to get local issuer certificate | that error |
21 |
Unable to verify the first certificate | incomplete chain |
Counting what the server sends #
A quick way to spot a missing intermediate. A publicly trusted site should send at least two:
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null \
| grep -c "BEGIN CERTIFICATE" Expected output
2
Other protocols #
openssl s_client -connect mail.example.com:587 -starttls smtp </dev/null openssl s_client -connect mail.example.com:143 -starttls imap </dev/null
openssl s_client -connect db.example.com:5432 -starttls postgres </dev/null
openssl s_client -connect ldap.example.com:389 -starttls ldap </dev/null Pinning down the TLS version #
Adding a version flag constrains the handshake, which is how you find out what a server still accepts:
openssl s_client -connect example.com:443 -servername example.com -tls1_2 </dev/null A handshake failure here is the expected result when the server has disabled that version — but on OpenSSL 3 it can equally be your own client refusing to make the offer. Interrogating versions and cipher suites properly is its own job: see check which TLS versions a server supports.
Checking a server that is not yet live #
To test a certificate before DNS points at the new host, resolve elsewhere but keep SNI honest:
openssl s_client -connect 203.0.113.10:443 -servername example.com </dev/null Frequently asked questions
- Why do I need </dev/null?
s_clientopens an interactive session and waits on stdin so you can type an HTTP request by hand. Redirecting from /dev/null closes stdin immediately, so the command prints its output and exits — which is what you want in a script.- What does -servername actually do?
- It sends the Server Name Indication TLS extension, telling the server which hostname you are asking for. On shared hosting, omitting it means the server replies with its default certificate and you end up debugging a certificate nobody uses.
- How do I check a mail server or another protocol?
- Use
-starttls. For exampleopenssl s_client -connect mail.example.com:587 -starttls smtp. It also supports imap, pop3, ftp, xmpp, ldap and postgres. - Why does verification fail here but work in my browser?
- Browsers repair incomplete chains by caching intermediates and fetching missing ones over HTTP. OpenSSL does neither, so it fails where a browser succeeds. The server is genuinely misconfigured — see that error.
References
- openssl-s_client(1) — -connect, -showcerts and -servername