Search for an SSL test and you get a page of sites that all promise to check your certificate. They do not all check the same thing. Behind the word "test" sit at least three different measurements, and a tool built for one of them can give a clean result while the problem you actually have sits in another.
So instead of ranking look-alike sites, this post sorts the free options by what they can see. We build one of the tools below, our SSL Inspector, and it is deliberately limited in ways the others are not, so we will be plain about where it stops. If you want the background on certificates first, our guide to how SSL certificates work covers it.
Three kinds of SSL test#
- Handshake scanners connect to the server and negotiate TLS over and over, each time offering different protocol versions and cipher suites, to map exactly what it accepts. This is the only way to learn whether a server still allows TLS 1.0, prefers weak ciphers, or sends an incomplete chain.
- Certificate readers look at the certificate itself: who issued it, which hostnames it covers, when it expires. Some fetch it from the live server and some read it from Certificate Transparency logs, the public, append-only record that certificate authorities submit certificates to.
- Client tests point the other way. They serve deliberately broken certificates so you can check whether your browser, app or HTTP library rejects them as it should.
Most confusion about SSL testing comes from expecting the answer to one question from a tool built for another.
Qualys SSL Labs: the familiar grade#
The SSL Labs Server Test is the one most people mean. It is free, runs in the browser, and describes itself as a deep analysis of any SSL web server on the public internet. A full test is not instant, and the report is long: certificate details and chain, every protocol version, every cipher suite in preference order, simulated handshakes from a list of real browsers and operating systems, and checks for known weaknesses.
The letter grade comes from a published rating guide. A numerical score is built from protocol support (30%), key exchange (30%) and cipher strength (40%), and then caps apply on top. The caps matter more than the score. Since 2020, a server that still accepts TLS 1.0 or TLS 1.1 is capped at B, and so is one with no forward secrecy or an incomplete certificate chain. The guide's May 2025 revision added a cap of A- for a server that does not support TLS 1.3. An A+ needs a clean configuration with no warnings plus HSTS with a max-age of at least six months.
Two practical notes. The form has a "Do not show the results on the boards" checkbox; tick it if you would rather the hostname not appear in the site's public lists of recent tests. And SSL Labs is built for public web servers. It cannot reach anything on a private network, and it is not the tool for a mail server's STARTTLS port.
testssl.sh and SSLyze: scanners you run yourself#
When the server is internal, the port is not 443, or you want to test on a schedule, a command-line scanner does the same job from your own machine.
testssl.sh is a free, GPLv2-licensed shell script. It needs bash and standard Unix tools, ships with its own copy of OpenSSL, and runs on Linux, macOS, the BSDs and Windows through WSL2 or Cygwin. It checks protocols, ciphers and a list of known cryptographic flaws on any port, and it handles STARTTLS services, so testssl.sh --starttls smtp mail.example.com:587 tests the submission port of a mail server, something the web-based scanners do not do. Output can be written as JSON, CSV or HTML as well as to the terminal. Our post on SMTP ports 465 and 587 explains why that port upgrades to TLS mid-conversation rather than starting encrypted.
SSLyze is a Python scanner under the AGPL that covers similar ground and adds two things. It can grade a server against Mozilla's published TLS recommendations, using the intermediate profile by default or old or modern with --mozilla_config. And it has a documented Python API and is designed to run from a CI/CD pipeline, so a configuration that drifts can fail a build instead of waiting for someone to notice. It also scans non-HTTP services, SMTP, IMAP, LDAP and Postgres among them.
If the scan shows a configuration you want to fix, the Mozilla SSL Configuration Generator, now hosted as the TLSRef Configurator, produces a matching config for nginx, Apache, HAProxy, Postfix and around twenty other servers. It offers the same three profiles. Intermediate, described there as recommended for almost all systems, is the sensible default; Modern is for services whose clients all support TLS 1.3.
openssl s_client: the raw view#
Every scanner above is, underneath, a more patient version of this:
openssl s_client -connect example.com:443 -servername example.com -showcerts
It performs one handshake and prints what came back: every certificate the server sent, the negotiated protocol and cipher, and whether verification succeeded. The -servername flag matters. It sends the hostname through SNI, and a server hosting many sites will hand back a default certificate without it, which looks exactly like a wrong-certificate bug when it is not.
To check just the expiry date and names, pipe the result into a second command:
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates
One handshake shows one negotiation, not the full range a server will accept, so s_client is for confirming a specific fact rather than auditing a configuration. It is also the quickest way to see the chain the server really sends. A missing intermediate certificate is one of the most common faults, and some browsers quietly fetch the missing piece while other clients fail. Our guide to certificate chains covers why.
Our SSL Inspector: the certificate from the public record#
Our SSL Inspector is a certificate reader, not a handshake scanner, and the difference is structural. It runs on Cloudflare's network, where code cannot open the raw TCP socket a TLS handshake needs. So it cannot list protocol versions or cipher suites, and it says so on the page.
What it does instead is look the domain up in Certificate Transparency logs, pick the newest certificate that has not expired, and report its issuer, validity window, days remaining, SHA-256 fingerprint and the hostnames it covers. It checks that the name you asked about is one of them, directly or through a wildcard one level up. In parallel it makes a request to the site over HTTPS to confirm something answers there and to read the Strict-Transport-Security header. The A+ to F grade combines those signals. An expired, revoked or wrong-name certificate is an automatic F, an expiry within 30 days costs points, and a full HSTS setup earns them. Every point comes with a line saying why.
The trade-off cuts both ways. Because the data comes from public logs, a check takes seconds and never touches the server's TLS stack. But the newest certificate in the log is not always the one being served. If a renewal was issued and never deployed, the logs show the new certificate while visitors still get the old one. When an expiry warning in a browser disagrees with our report, trust the browser and confirm with s_client. The chain the inspector shows is the leaf plus its issuer's name, not the full path to a root. To see every certificate ever issued for a name, use our CT log search; our explainer on Certificate Transparency covers why those logs exist.
Expiry is the check worth running most often, and it is getting more urgent. The CA/Browser Forum has voted to cut the maximum lifetime of a public TLS certificate from 398 days to 47 days in steps, starting in March 2026 and finishing in March 2029. Shorter lifetimes mean more renewals, and more chances for automation to fail quietly.
Testing the client instead of the server#
If you write code that makes HTTPS requests, the question may be whether your client rejects bad certificates. badssl.com answers it with a set of subdomains that are broken on purpose: expired.badssl.com, wrong.host.badssl.com, self-signed.badssl.com, untrusted-root.badssl.com, incomplete-chain.badssl.com and many more. Point your app at each one. If any request succeeds, certificate verification is off somewhere, often in a "temporary" line someone added to get past an error in development.
Which tool for which question#
- "Is our public web server configured well?" Qualys SSL Labs.
- "Is the internal server, or the mail server's STARTTLS port, configured well?" testssl.sh or SSLyze, run from a machine that can reach it.
- "Does our config match current recommendations, every deploy?" SSLyze with
--mozilla_configin CI. - "What should the config say?" The Mozilla SSL Configuration Generator, at its TLSRef home.
- "Exactly which certificate does the server send right now?"
openssl s_client. - "When does the certificate expire, does it cover this name, and is HSTS set?" Our SSL Inspector, in seconds, without touching the server.
- "Does my app reject bad certificates?" badssl.com.
A sensible routine uses two of these: a quick certificate check whenever you deploy, and a full handshake scan whenever the server or its TLS library changes. If the scan flags old protocol versions, our comparison of TLS 1.2 and 1.3 explains what you give up by turning them off, which is usually very little.
Check a site's certificate
See the issuer, expiry, covered hostnames and HSTS setup for any domain, with a grade that shows exactly which signals earned or cost points.
Inspect a certificate →