Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes
Sponsored Reserved space — layout preview until AdSense is connected

How to Validate SSL Certificates for Multiple Domains in Python

A Python utility that checks SSL certificate expiry dates for a list of domains using the standard library ssl and socket modules.

Medium Python 3.9+ Jun 28, 2026 Automation & scripting 2 views 0 copies

Python code

42 lines
Python 3.9+
import ssl
import socket
from datetime import datetime

def check_ssl_certificate(hostname: str, port: int = 443) -> dict:
    """Validate SSL certificate for a given hostname."""
    context = ssl.create_default_context()
    with socket.create_connection((hostname, port), timeout=5) as sock:
        with context.wrap_socket(sock, server_hostname=hostname) as ssock:
            cert = ssock.getpeercert()
    
    expiry_date = datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z')
    days_remaining = (expiry_date - datetime.now()).days
    
    return {
        'hostname': hostname,
        'expires': expiry_date.strftime('%Y-%m-%d'),
        'days_remaining': days_remaining,
        'valid': days_remaining > 0,
        'issuer': dict(cert['issuer'][0][0]),
        'subject': dict(cert['subject'][0][0])
    }

def validate_domains(domains: list) -> list:
    """Validate certificates for multiple domains."""
    results = []
    for domain in domains:
        try:
            result = check_ssl_certificate(domain)
        except Exception as e:
            result = {'hostname': domain, 'error': str(e), 'valid': False}
        results.append(result)
    return results

if __name__ == "__main__":
    test_domains = ['example.com', 'google.com', 'nonexistent.domain']
    ssl_results = validate_domains(test_domains)
    for result in ssl_results:
        status = "✓" if result.get('valid', False) else "✗"
        print(f"{status} {result['hostname']}: "
              f"expires {result.get('expires', 'N/A')} "
              f"({result.get('days_remaining', 'N/A')} days)")

Output

stdout
✓ example.com: expires 2025-XX-XX (XXX days)
✓ google.com: expires 2025-XX-XX (XXX days)
✗ nonexistent.domain: expires N/A (N/A days)

How it works

The script uses ssl.create_default_context() to set up a secure context with default trusted CA certificates. It creates a TCP connection to the hostname on port 443, wraps it in an SSL/TLS socket, and retrieves the peer certificate with getpeercert(). The 'notAfter' field is parsed to a datetime object to calculate days remaining. A timeout of 5 seconds prevents hanging on unreachable hosts. Each domain is processed individually and errors are caught per domain so a single failure does not stop the entire batch.

Common mistakes

  • Not setting a timeout on socket.create_connection, causing the script to hang on unreachable hosts.
  • Assuming the certificate issuer or subject fields always have a predictable structure without checking for nested tuples.
  • Forgetting to close sockets properly, though the 'with' statement handles this.

Variations

  1. Use aiohttp and asyncio to check many domains concurrently for faster batch validation.
  2. Leverage the cryptography library to parse and validate certificate chains in more detail.

Real-world use cases

  • Automated monitoring of SSL certificate expiry for a portfolio of client websites before renewal deadlines.
  • Integrating into a CI/CD pipeline to verify that staging and production endpoints have valid certificates.
  • Generating a daily report for IT operations to proactively flag domains with certificates expiring soon.

Sponsored

Sponsored Reserved space — layout preview until AdSense is connected

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Automation & scripting

Related tutorials and quizzes for this topic.