Free SSL Certificate Check: How to Test and Validate Your HTTPS
How to check an SSL/TLS certificate for expiry, chain issues, weak ciphers, and misconfigurations using free command-line tools and online scanners.
An expired or misconfigured SSL certificate doesn't just trigger browser warnings — it breaks your site for all visitors, tanks conversion rates, and signals to search engines that your domain may be unsafe. SSL errors are also a common cause of failed SaaS trial sign-ups and payment flow abandonment.
This guide covers every tool and technique to check an SSL certificate, understand what the output means, and fix the most common problems.
What to Check in an SSL Certificate
A complete SSL check covers:
- Validity period — Is the certificate currently valid and not expiring soon?
- Certificate chain — Is the full chain sent, from leaf to root?
- Hostname match — Does the cert cover the domain (and www subdomain)?
- Protocol version — Is TLS 1.2+ in use? Is TLS 1.0/1.1 disabled?
- Cipher strength — Are weak ciphers disabled?
- Certificate Transparency — Is the cert logged in CT logs?
- OCSP stapling — Is revocation status being stapled?
- Mixed content — Are all resources loaded over HTTPS?
Check SSL with openssl
The openssl command-line tool is available on macOS, Linux, and Windows Subsystem for Linux.
View the certificate
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com < /dev/null 2>/dev/null | openssl x509 -noout -text
This outputs the full certificate, including Subject, Issuer, validity dates, Subject Alternative Names (SANs), and key details.
Check expiry date only
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com < /dev/null 2>/dev/null | openssl x509 -noout -dates
Output:
notBefore=Jan 1 00:00:00 2025 GMT
notAfter=Mar 1 00:00:00 2026 GMT
Days until expiry (script-friendly)
expiry=$(openssl s_client -connect yourdomain.com:443 -servername yourdomain.com \
< /dev/null 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
expiry_epoch=$(date -d "$expiry" +%s 2>/dev/null || date -j -f "%b %d %T %Y %Z" "$expiry" +%s)
now_epoch=$(date +%s)
days_left=$(( ($expiry_epoch - $now_epoch) / 86400 ))
echo "Days until expiry: $days_left"
Check the full certificate chain
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com -showcerts < /dev/null 2>/dev/null
Count the -----BEGIN CERTIFICATE----- blocks. You should see at least 2 (leaf + intermediate). If only 1, your server isn't sending the intermediate certificate and some clients will reject it.
Check TLS protocol support
# Does TLS 1.3 work?
openssl s_client -connect yourdomain.com:443 -tls1_3 < /dev/null 2>&1 | grep "Protocol\|Cipher"
# Is TLS 1.1 disabled? (should fail)
openssl s_client -connect yourdomain.com:443 -tls1_1 < /dev/null 2>&1 | grep "alert\|Protocol"
Check certificate SANs (hostname coverage)
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com < /dev/null 2>/dev/null \
| openssl x509 -noout -ext subjectAltName
Make sure both yourdomain.com and www.yourdomain.com are listed.
Check SSL with curl
# Verbose SSL handshake info
curl -vI https://yourdomain.com 2>&1 | grep -A5 "SSL connection\|certificate\|expire"
# Check if cert is valid (exit code 0 = valid)
curl --silent --output /dev/null --write-out "%{http_code}" https://yourdomain.com
Check SSL with nmap
# Full TLS audit including protocols, ciphers, and vulnerabilities
nmap --script ssl-enum-ciphers,ssl-cert,ssl-dh-params -p 443 yourdomain.com
Common SSL Certificate Problems
Expired certificate
The most common and avoidable problem. Your certificate has passed its notAfter date.
Fix: Renew before expiry. Set calendar reminders at 60 days, 30 days, and 7 days. Better: use Let's Encrypt with auto-renewal via Certbot or your hosting platform's built-in renewal.
Missing intermediate certificate
The server only sends the leaf certificate, not the full chain. Browsers with the CA cached will work fine, but others will show an error.
Fix: Configure your server to send the full chain. In nginx:
ssl_certificate /path/to/fullchain.pem; # Contains leaf + intermediate
ssl_certificate_key /path/to/privkey.pem;
Make sure fullchain.pem contains both certificates, not just the leaf.
Certificate/hostname mismatch
The certificate was issued for a different hostname than the one being accessed.
Common cause: certificate issued for yourdomain.com but accessed as www.yourdomain.com, or vice versa.
Fix: Issue a certificate with both names as Subject Alternative Names (SANs). Let's Encrypt makes this free:
certbot certonly --nginx -d yourdomain.com -d www.yourdomain.com
Self-signed certificate
The certificate was signed by the server itself, not a trusted CA. Will always trigger browser warnings in production.
Fix: Replace with a certificate from a trusted CA. Let's Encrypt provides free, trusted certificates valid for 90 days with auto-renewal.
Weak cipher suites
Server supports RC4, 3DES, export ciphers, or TLS 1.0/1.1.
Fix: Update your TLS configuration (see our TLS 1.3 guide).
Mixed content
The page is served over HTTPS, but some resources (images, scripts, stylesheets) are loaded over HTTP.
# Check page for mixed content
curl -s https://yourdomain.com | grep -i "http://"
Fix: Update all resource URLs to use https:// or protocol-relative // URLs. Add this CSP directive to prevent it:
Content-Security-Policy: upgrade-insecure-requests
Setting Up Certificate Expiry Alerts
Manual checks don't scale. Use monitoring:
Cron job approach:
#!/bin/bash
DOMAIN="yourdomain.com"
THRESHOLD=30
ALERT_EMAIL="ops@yourdomain.com"
expiry=$(openssl s_client -connect "$DOMAIN:443" -servername "$DOMAIN" \
< /dev/null 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
days_left=$(( ($(date -d "$expiry" +%s) - $(date +%s)) / 86400 ))
if [ "$days_left" -lt "$THRESHOLD" ]; then
echo "SSL certificate for $DOMAIN expires in $days_left days" | mail -s "SSL Expiry Warning" "$ALERT_EMAIL"
fi
Better: Use an automated scanner that checks all your domains daily and alerts when expiry is within 30 days.
Let's Encrypt: Free SSL for Any Domain
Let's Encrypt issues free DV certificates valid for 90 days, designed to be auto-renewed by Certbot:
# Install Certbot
sudo apt install certbot python3-certbot-nginx
# Issue and install certificate for nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Auto-renewal is set up automatically; test it:
sudo certbot renew --dry-run
The 90-day validity period is intentional — it forces automation, which means you're much less likely to have an expired certificate in production.