requests — SSLError: certificate verify failed (hostname mismatch)
Diagnose certificate verify failures by separating hostname mismatch, missing CA trust and expired certificates.
Symptoms
- SSLError: certificate verify failed: unable to get local issuer certificate
- SSLError mentioning hostname mismatch or self-signed certificate
- curl succeeds with -k but fails without it
- The error appears only for some hosts or after a network change
Possible causes
- The server certificate does not match the requested hostname
- The issuing CA is not in the client trust store
- The certificate chain is incomplete so verification cannot build a path
- The certificate is expired or the system clock is wrong
Diagnosis steps
Inspect the certificate chain
openssl s_client -connect host:443 -servername host -showcertsInterpretation
The output shows the presented chain, the subject alternative names and the validity dates, revealing mismatch, incomplete chain or expiry.
Compare hostname with subject alternative names
openssl s_client -connect host:443 -servername host 2>/dev/null | openssl x509 -noout -ext subjectAltNameInterpretation
If the requested name is absent from the SAN list, verification fails regardless of trust.
Check the client trust store
python -c "import certifi; print(certifi.where())"Interpretation
A missing or outdated CA bundle explains unable to get local issuer certificate even when the chain is valid.
Root cause
Certificate verification failed because the presented certificate did not match the hostname, was not trusted by the client CA store, or the chain was incomplete or invalid.
Fix
Request the correct hostname, install or update the CA bundle so the issuer is trusted, and fix the server to present a complete chain. Never disable verification as a permanent fix.
Verify the fix
Repeat the request and confirm it succeeds without verification errors, then recheck the chain to confirm the issuer and hostname match.
Symptom walkthrough
A request raises SSLError with certificate verify failed, sometimes adding unable to get local issuer certificate or hostname mismatch. The distinction matters: message text varies with whether the problem is a missing CA, an incomplete chain, a name mismatch or an expired certificate. Passing verify=False or curl -k makes it work, which confirms the failure is verification rather than connectivity.
Fix in practice
Diagnose which failure mode applies by inspecting the chain and SAN list, then fix the specific cause: use the correct hostname, install or refresh the CA bundle, or correct the server chain. Disabling verification is not a fix, because it removes the protection that detected the problem.
Verification
Rerun the request and confirm it succeeds with verification enabled, then re-inspect the chain to confirm the issuer is trusted and the hostname matches the certificate.
Diagnostic commands
Check the behavior with commands like these:
openssl s_client -connect host:443 -servername host -showcerts
openssl s_client -connect host:443 -servername host 2>/dev/null | openssl x509 -noout -ext subjectAltName
python -c "import certifi; print(certifi.where())"