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
The certificate does not list this host name
commonThe certificate covers other names (www., the apex domain, an old service name). Wildcards cover exactly one label, so *.example.com matches api.example.com but not example.com or a.b.example.com.
Connecting by IP address, localhost or a container alias
commonThe URL uses 127.0.0.1, a private IP, "localhost" or a docker-compose service name, none of which appear in a certificate issued for a public DNS name.
The server returned another site's certificate
occasionalShared hosts choose the certificate from the SNI name; a name without its own configuration gets the default certificate.
How to fix it
- 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.
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.
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
x509: certificate is valid for example.com, not api.example.comGo crypto/x509curl: (60) SSL: no alternative certificate subject name matches target hostname…curl (OpenSSL backend)Hostname/IP does not match certificate's altnames: Host: api.example.com. is no…Node.js tls.checkServerIdentity()Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1…requests / urllib3 (Python)