Skip to content
ecdsa.com
Python ssl module (OpenSSL host check)Python cryptography

Error message

[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'api.example.com'.

Also printed as

  • [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: IP address mismatch, certificate is not valid for '127.0.0.1'.

The quoted name is the host you connected to. For IP addresses Python says "IP address mismatch, certificate is not valid for '…'." A source location such as "(_ssl.c:1082)" follows the message.

Python ssl module (OpenSSL host check) — ssl.SSLCertVerificationError, X509_V_ERR_HOSTNAME_MISMATCH (62)

What it means

The certificate chain is trusted, but the name Python was asked to verify (the host in the URL, or server_hostname) is not among the certificate's Subject Alternative Names. Since Python 3.7 the check is done by OpenSSL during the handshake, so it surfaces as a certificate verification failure rather than the old ssl.CertificateError.

Why it happens

How to fix it

  1. 1.

    List the names the certificate covers

    Compare the subjectAltName entries with the host you pass to Python.

    bash
    echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \
      | openssl x509 -noout -subject -ext subjectAltName
  2. 2.

    Reissue with all names in subjectAltName

    Add every DNS name and, for IP-based access, IP entries. Names only in the Common Name are not used for matching.

    bash
    # Include every DNS name and IP address clients use
    openssl req -new -key server.key -out server.csr -subj "/CN=api.example.com" \
      -addext "subjectAltName=DNS:api.example.com,DNS:api.internal.example.com,IP:10.0.0.5"
  3. 3.

    Verify the certificate's name while connecting to an address

    When you must reach a specific address (a load balancer node, a tunnel), keep server_hostname set to the name in the certificate instead of disabling the hostname check.

    python
    import socket, ssl
    
    # Connect to an address, but verify (and send SNI) for the certificate's name
    ctx = ssl.create_default_context()
    with socket.create_connection(("10.0.0.5", 443)) as raw:
        with ctx.wrap_socket(raw, server_hostname="api.example.com") as tls:
            print(tls.version())

Related errors

Browse the full signature error database