DEV Community

Cover image for How to Check an SSL Certificate in 10 Minutes (and Fix the Most Common HTTPS Errors)
Muhammad Ali Mughal
Muhammad Ali Mughal

Posted on

How to Check an SSL Certificate in 10 Minutes (and Fix the Most Common HTTPS Errors)

An expired SSL certificate is one of the most avoidable outages on the web. The site is fine, the server is fine, but every visitor gets a full-page browser warning and most of them leave. Less dramatic certificate problems, like a missing intermediate certificate, are worse in a way: the site works in your desktop browser, so you don't notice, while API clients, mobile apps and curl quietly fail.

I'm Muhammad Ali Mughal, and I build free developer and privacy tools at PixelValut. This is the checklist I run whenever I launch a site, move a server or get a "your connection is not private" report. It takes about ten minutes, and I've included the OpenSSL commands so you can verify everything yourself.

A monitor showing a website security dashboard with certificate details, a broken chain link being repaired and a list of security header toggles

What a certificate check should cover

A useful check answers five questions:

  1. Is the certificate valid right now, and when does it expire?
  2. Does it cover the exact hostname visitors use, including www and any subdomains?
  3. Is the chain complete, so every client can link it to a trusted root?
  4. Is the server configured sensibly: modern TLS versions, HTTP redirecting to HTTPS?
  5. Are the important security headers set, such as HSTS?

The quickest way to get the overview is the free SSL Checker on PixelValut. Enter a domain and it shows the issuer, an expiry countdown and the HTTP security headers the site returns, with fix tips and OpenSSL commands. Then use the commands below to dig into anything that looks wrong.

Step 1: Check expiry and issuer

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates
Enter fullscreen mode Exit fullscreen mode

You'll see notBefore and notAfter. If notAfter is in the past, browsers show NET::ERR_CERT_DATE_INVALID.

The -servername flag matters. It sends SNI (Server Name Indication), which tells a server hosting many sites which certificate to present. Without it, you may be looking at the server's default certificate rather than the one your visitors get.

The real fix is automated renewal. Free certificates from Let's Encrypt are short-lived by design, so a manual renewal process will eventually be forgotten. If you use Certbot, test renewal without waiting for it to fail:

sudo certbot renew --dry-run
Enter fullscreen mode Exit fullscreen mode

Common reasons renewal breaks: port 80 is blocked by a firewall (the HTTP-01 challenge needs it), a redirect rule interferes with /.well-known/acme-challenge/, or the DNS now points to a different server. Also confirm the web server reloads after renewal; a renewed file on disk doesn't help if Nginx is still serving the old one from memory.

Step 2: Check the hostname matches

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -ext subjectAltName
Enter fullscreen mode Exit fullscreen mode

Browsers check the Subject Alternative Name (SAN) list, not just the common name. If visitors use www.example.com and the SAN list only has example.com, they get NET::ERR_CERT_COMMON_NAME_INVALID.

Things to remember:

  • A wildcard like *.example.com covers shop.example.com but not example.com itself, and not a.b.example.com.
  • When you add a new subdomain, reissue the certificate to include it, or use a wildcard via DNS validation.

Step 3: Check the chain is complete

This is the error that hides from you. Your server should send its own certificate plus the intermediate certificate(s). Desktop browsers can often fill a missing intermediate themselves, so the site looks fine to you. Many other clients can't.

echo | openssl s_client -connect example.com:443 -servername example.com -showcerts 2>/dev/null \
  | grep -E "^ *[0-9] s:|Verify return code"
Enter fullscreen mode Exit fullscreen mode

You want to see more than one certificate in the list and Verify return code: 0 (ok). A result like unable to get local issuer certificate or unable to verify the first certificate usually means the intermediate is missing.

Fix: point your server at the full chain file, not just the leaf certificate. With Certbot on Nginx that's:

ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
Enter fullscreen mode Exit fullscreen mode

Using cert.pem instead of fullchain.pem is one of the most common mistakes I see.

Step 4: Check TLS versions and redirects

Modern clients expect TLS 1.2 or 1.3. You can confirm what the server accepts:

openssl s_client -connect example.com:443 -servername example.com -tls1_3 </dev/null
openssl s_client -connect example.com:443 -servername example.com -tls1_1 </dev/null
Enter fullscreen mode Exit fullscreen mode

The first should connect. The second should fail on a well-configured server (assuming your OpenSSL build still supports TLS 1.1 for testing). In Nginx, ssl_protocols TLSv1.2 TLSv1.3; is a sensible baseline.

Then confirm plain HTTP redirects to HTTPS with a single permanent redirect:

curl -sI http://example.com | grep -iE "^HTTP|^location"
Enter fullscreen mode Exit fullscreen mode

You want a 301 (or 308) pointing to the https:// URL. Long redirect chains (http → https → www → trailing slash) slow down the first visit and are worth flattening.

Step 5: Check security headers

A valid certificate secures the connection. Headers tell the browser how to behave on top of it:

Header What it does Example
Strict-Transport-Security Forces HTTPS on future visits max-age=31536000; includeSubDomains
Content-Security-Policy Limits where scripts, styles and frames can load from Start with a report-only policy
X-Content-Type-Options Stops MIME-type sniffing nosniff
X-Frame-Options or CSP frame-ancestors Prevents clickjacking via framing DENY or SAMEORIGIN
Referrer-Policy Controls how much URL data leaks to other sites strict-origin-when-cross-origin
curl -sI https://example.com | grep -iE "strict-transport|content-security|x-content-type|x-frame|referrer-policy"
Enter fullscreen mode Exit fullscreen mode

A word of caution on HSTS: once browsers cache it, they refuse plain HTTP for that domain until max-age runs out. Start with a short max-age (a few minutes or a day), confirm everything, including subdomains, works over HTTPS, and only then raise it. Only add includeSubDomains when every subdomain has a valid certificate.

Step 6: Fix mixed content

If the padlock shows a warning even though the certificate is fine, the page is probably loading something over http://, like an image, script or font. Open your browser's developer console; mixed content warnings list the exact URLs. Update them to https:// or relative paths, and check hard-coded URLs in your database or CMS settings after a migration.

Common errors at a glance

  • ERR_CERT_DATE_INVALID: expired (or the visitor's clock is wrong). Renew and automate.
  • ERR_CERT_COMMON_NAME_INVALID: hostname missing from SAN. Reissue with every hostname.
  • unable to get local issuer certificate: incomplete chain. Serve fullchain.pem.
  • ERR_CERT_AUTHORITY_INVALID: self-signed or untrusted issuer. Use a publicly trusted CA.
  • Wrong certificate on a shared server: SNI or virtual host misconfiguration. Check server_name blocks.
  • Padlock warning, valid cert: mixed content. Fix the http:// asset URLs.

Make it routine

My habit: check every domain after any server change, and keep an eye on expiry dates monthly even with auto-renewal, because automation fails silently. If DNS changes are involved, the DNS Lookup tool helps confirm the domain points where you expect before you debug certificates.

Run your own domain through the SSL Checker now and see what comes back. The other free tools are on pixelvalut.com, and if you want to find it again later, just search for pixelvalut.com on Google.

What's the strangest SSL issue you've had to debug? Share it in the comments.

ssl #https #security #webdev #devops #tls #cybersecurity #sysadmin #nginx #webdevelopment #privacy #infosec

Top comments (0)