urllib and SSL CERTIFICATE_VERIFY_FAILED Error
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The Python error SSL: CERTIFICATE_VERIFY_FAILED means the TLS handshake could not establish a certificate chain that the client trusts. When this happens through urllib, the problem is rarely urllib itself. It is usually a certificate trust issue such as a missing CA bundle, a self-signed server certificate, a corporate proxy certificate, or an environment whose trust store is outdated.
Understand What Verification Is Doing
When urllib.request.urlopen() connects to an HTTPS URL, Python validates the server certificate before sending sensitive application data. That validation checks things such as:
- whether the certificate chain leads to a trusted CA
- whether the hostname matches the certificate
- whether the certificate is expired
Basic request:
If certificate verification fails, Python raises an SSL-related exception rather than silently trusting the connection. That is the correct and secure behavior.
Start by Checking the Real Cause
Before changing code, confirm whether the problem is with:
- the target server
- your local CA store
- a self-signed or internal certificate
- a man-in-the-middle corporate proxy
A quick sanity check is to try the same URL in a browser or with openssl:
If the certificate chain is broken there too, the issue is server-side. If the server looks fine elsewhere but Python still fails, the local trust environment is the likely cause.
Use the Default Verified Context Explicitly
In most cases, the correct code is simply to let Python use a verified default SSL context:
This is explicit and keeps verification enabled. It also gives you a place to inject custom CA settings when needed.
Fix Missing or Custom CA Trust
If the target service uses a private CA or corporate certificate, point the SSL context at the correct CA bundle:
This is the correct fix for self-managed infrastructure. Do not work around a trusted internal CA problem by disabling verification globally.
For some Python installations, especially on local development machines, the system CA store may also be incomplete or misconfigured. Updating the runtime or CA bundle is often the real solution.
Avoid Disabling Verification Except in Throwaway Debugging
You can bypass certificate checks:
This may help prove that the failure is certificate-related, but it should not be the production fix. Turning off verification means the client no longer knows whether it is talking to the real server.
In other words, disabling verification is useful as a temporary diagnostic step, not as a security strategy.
Consider certifi When the Environment Trust Store Is Weak
In some environments, using a maintained CA bundle can help:
This is often useful in isolated environments where the system CA store is not dependable. It does not solve an invalid server certificate, but it can solve trust-store packaging issues.
Common Pitfalls
- Disabling certificate verification permanently instead of fixing the trust problem.
- Assuming
urllibis broken when the real issue is server certificate configuration. - Ignoring hostname mismatch and focusing only on whether the certificate file exists.
- Forgetting about internal proxies or enterprise certificates that alter the TLS chain.
- Changing application code before verifying whether the environment CA store is actually the problem.
Summary
- '
CERTIFICATE_VERIFY_FAILEDmeans Python could not trust the server certificate chain.' - Start by determining whether the issue is with the server or the local trust store.
- Keep verification enabled and use
ssl.create_default_context()as the normal path. - Add the correct CA bundle explicitly for private or internal certificates.
- Treat unverified SSL contexts as temporary debugging tools, not production fixes.

