Troubleshoot SSLError in Python Requests
Diagnose certificate-chain, hostname, trust-store, proxy, and protocol failures in Requests without turning off TLS verification as a permanent fix.
A Requests SSLError means TLS negotiation or certificate validation failed. Read the underlying exception before choosing a fix: a missing issuer, an expired certificate, a hostname mismatch, and an unsupported protocol require different actions.
Inspect the environment and error
Check the target hostname, system clock, proxy settings, and the Python interpreter that runs the application. For the Requests installation in that interpreter:
python -m pip show requests certifi
python -c "import requests, ssl; print(requests.certs.where()); print(ssl.OPENSSL_VERSION)"
A certificate for another hostname or an expired server certificate will not be repaired by updating a local CA bundle. Likewise, a server missing an intermediate certificate should send a correct chain.
Update or select the right trust bundle
If your installed trust bundle is stale, update packages through your project's dependency process. An explicit local update is:
python -m pip install --upgrade certifi requests
For a private service or approved TLS-inspecting corporate proxy, obtain the organization's CA certificates through a trusted channel and point Requests at the appropriate bundle:
import requests
response = requests.get(
"https://internal.example.com",
verify="/path/to/ca-bundle.crt",
timeout=10,
)
response.raise_for_status()
The bundle must contain the trust anchors needed for that request. If you need both public and private roots, provide a bundle containing the required certificates rather than assuming a custom file is automatically added to every existing trust source. Requests also supports REQUESTS_CA_BUNDLE; prepared-request flows need to merge environment settings explicitly when appropriate.
Understand what disabling verification does
verify=False disables certificate and hostname verification. It may help isolate a trust-validation problem during a controlled reproduction, but it allows an impostor server to be accepted. It does not repair incompatible TLS protocols or other handshake failures.
Do not use it for production traffic or requests containing real credentials. InsecureRequestWarning describes that loss of verification; suppressing the warning with urllib3 only hides the warning and does not restore security. Fix the trust chain or endpoint instead.
Check other causes
- A missing intermediate certificate can work in one client because of cached certificates or different chain-building behavior and fail in another.
- A wrong system clock can make a valid certificate appear expired or not yet valid.
- A proxy can replace the server certificate with one issued by a private CA.
- A legacy server may support only protocols or ciphers disabled by a modern TLS library. Upgrade the server's TLS configuration rather than broadly weakening the client.
FAQ
What does “unable to get local issuer certificate” mean? The client could not build a trusted issuer chain. Check the server's intermediate certificates and the client's selected CA bundle; the message does not prove that one specific root is missing.
Why does a browser work? Browsers and Requests can use different trust stores, proxy settings, and intermediate-certificate handling. Compare the actual certificate and trust path rather than assuming browser success validates your Python configuration.
What about containers? Check the trust bundle inside the running image. Distribution ca-certificates packages and certifi are related but distinct sources of trust; installing one does not guarantee Requests uses it. Verify the effective bundle and preserve required private roots in the image or runtime configuration.
References
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan