Home » Wiki » Fix CERTIFICATE_VERIFY_FAILED Error in Python

Fix CERTIFICATE_VERIFY_FAILED Error in Python

by | SSL Errors

Fix CERTIFICATE_VERIFY_FAILED Error in Python

Step-by-Step Guide for Fixing CERTIFICATE_VERIFY_FAILED Error in Python

The CERTIFICATE_VERIFY_FAILED error in Python occurs when trying to make HTTPS requests and the certificate verification fails. This usually happens because the certificate is self-signed, expired, or not trusted by your system. Here is a step-by-step guide to fix CERTIFICATE_VERIFY_FAILED error in Python.

Understanding the CERTIFICATE_VERIFY_FAILED Error

When you make HTTPS requests in Python using libraries like requests, urllib, etc., the connection is encrypted using SSL/TLS certificates. As part of establishing the secure connection, the certificate provided by the server is verified against the trusted certificate authorities stored on your system.

If this verification fails for any reason, you will see an SSL certification verification failed error. The most common causes are:

The certificate is self-signed rather than signed by a trusted CA. Self-signed certificates are not trusted by default.

  • The certificate has expired and is no longer valid.
  • The CA that signed the certificate is not trusted by your local system.
  • The hostname in the certificate does not match the server you are trying to connect to.
  • There are problems with the certificate chain like missing Intermediate certificates.

10 Best Ways to Fix CERTIFICATE_VERIFY_FAILED Error in Python

The CERTIFICATE_VERIFY_FAILED is the most common manifestation of this issue in Python. So to resolve it, you need to properly configure certificate verification on your system.

  • Check Certificate Details
  • Add Certificate as Trusted
  • Use certifi Certificate Bundle
  • Disable Certificate Verification
  • Update System Root CAs
  • Use Python Requests Properly
  • Configure Protocols and Ciphers
  • Use Client Certificate Authentication
  • Check for Intermediates
  • Upgrade Outdated Dependencies

1. Check Certificate Details

As a first step, check the details of the certificate causing issues. You can use the openssl command to do this:

openssl s_client -connect host:port -servername hostname -showcerts

This will print out the full certificate sent by the server and highlight any issues with it.

Check that:

  • The certificate is signed by a trusted authority like Let’s Encrypt or trusted commercial CAs. Self-signed certificates will be untrusted by default.
  • The certificate is still valid and not expired.
  • The hostname matches what you are trying to connect to.
  • The chain of trust is complete with intermediate/root certificates present.

This will help you identify the reason your system is rejecting the certificate.

2. Add Certificate as Trusted

If the certificate itself is valid but simply not trusted by your system, you can add it as a trusted certificate. 

Get the certificate from the server in PEM format and add it to your trusted CA list:

# Get certificate
openssl s_client -connect host:443 -servername hostname -showcerts </dev/null 2>/dev/null| openssl x509 -outform PEM > mycert.pem
# Add to trusted CA list
sudo cp mycert.pem /usr/local/share/ca-certificates/
sudo update-ca-certificates

Now your system will trust this particular self-signed certificate.

3. Use certifi Certificate Bundle

The certifi package provides Mozilla’s curated bundle of Root CAs to verify certificates. This contains certificates trusted by all major browsers and operating systems.

You can use this directly instead of relying on your system CA store:

import certifi
import ssl
context = ssl.create_default_context(cafile=certifi.where())

Pass the context when making requests to use certifi for verification.

4. Disable Certificate Verification

If you understand the risks and want to disable certificate verification entirely, you can do:

import ssl
context = ssl._create_unverified_context()

And use this context for requests.

Warning: This disables all protection provided by SSL and makes your application vulnerable to MITM attacks. Only do this in development environments, never in production!

5. Update System Root CAs

On Linux systems, the root CA certificates are stored in /etc/ssl/certs. Updating them may resolve issues:

sudo update-ca-certificates

On Mac, run:

sudo /Applications/Python 3.6/Install Certificates.command

And on Windows, use the Certificate Manager to update trusted root certificates. 

Keep your system CA stores up-to-date to avoid problems verifying newly issued certificates.

6. Use Python Requests Properly

The Requests library has some convenient ways to handle certificates that avoid verification issues:

Verify Hostname

requests.get('https://example.com', verify=True)

This will verify both the CA and hostname by default.

Specify CA Bundle

requests.get('https://example.com', verify='/path/to/ca/bundle')

Use your own CA bundle instead of system default.

Disable Verifications

requests.get('https://example.com', verify=False)

Not recommended but allows ignoring verification errors.

Using Requests properly prevents many SSL errors.

7. Configure Protocols and Ciphers

Sometimes issues arise if servers don’t support modern TLS versions or cipher suites.

You can configure the SSL protocols and ciphers supported in Python:

import ssl
ssl.PROTOCOL_TLSv1_2
ssl.OP_NO_SSLv3
context.options |= ssl.OP_NO_SSLv2
context.options |= ssl.OP_NO_SSLv3
context.set_ciphers('ECDHE+AESGCM:!aNULL')

This forces Python to use TLS v1.2+ with strong encryption ciphers only.

8. Use Client Certificate Authentication

For client certificate authentication:

context = ssl.SSLContext()
context.load_cert_chain('/path/to/client/cert', '/path/to/private/key')

And use this context to present certificates to the server.

9. Check for Intermediates

If you get certificate chain errors, it means intermediate certificates are missing.

Fetch the intermediate certs in PEM format and append them to your certificate:

cat domain.crt intermediate1.pem intermediate2.pem > chained.pem

Now pass the chained PEM file for successful verification.

10. Upgrade Outdated Dependencies

Older versions of libraries like urllib3, PyOpenSSL etc. can sometimes trigger certificate issues.

Make sure you upgrade them to their latest versions to get fixes for SSL/TLS bugs:

pip install --upgrade urllib3 pyopenssl requests certify

Keep your packages upgraded to avoid known SSL/TLS issues.

Final Thoughts

Certificate verification is crucial for secure HTTPS connections. Make sure to properly validate certificates in your Python applications and avoid disabling verification without understanding the implications.

Use the latest SSL module, check certificates thoroughly, keep system CAs updated, configure protocol and ciphers appropriately, and upgrade related libraries regularly to avoid SSL errors.

With some diligent troubleshooting and SSL configuration, you can resolve CERTIFICATE_VERIFY_FAILED and other certificate problems in Python. This will enable your apps to securely leverage HTTPS connections with proper validation.

Frequently Asked Questions

1. Why am I suddenly getting certificate verification failed errors?

There are a few possible reasons:

  • The server certificate expired and needed to be renewed.
  • The web host changed the server certificate.
  • Your system root CA certificates are outdated.
  • The requests library or dependencies got upgraded with stricter verification.

Updating CAs, getting new server certs or pinning to known good certs will resolve it.

2. How do I know which certificate is causing issues?

Use the openssl s_client command to view certificates from a server and debug problems:

openssl s_client -connect host:443 -servername hostname -showcerts

This will print the certificate chain and highlight any issues with them.

3. Should I permanently disable certificate verification in production?

No, disabling verification makes your application vulnerable to serious MITM attacks. Only disable it temporarily in development after verifying the risks.

In production, properly configure certificate verification using root CAs, certificate pinning, etc. Never permanently disable verification.

4. What is the difference between CERTIFICATE_VERIFY_FAILED and SSLError?

Python raises different exceptions based on the issue:

  • CERTIFICATE_VERIFY_FAILED – Certificate verification failed.
  • SSLError – Generic SSL error like protocol mismatch, bad cipher, etc.

But both mean issues establishing a secure SSL/TLS connection. Debug the root cause based on your environment.

5. How can I recreate the Requests library behavior in Python 3.7+?

Python 3.7+ enables hostname checking by default. To match Requests behavior:

ssl.match_hostname = lambda cert, hostname

6. How do I solve OpenSSL.SSL.Error errors in Python?

The OpenSSL.SSL.Error happens when there are issues with your specific SSL configuration like protocol mismatches, bad ciphers, etc. Try these steps:

  • Upgrade OpenSSL to the latest version.
  • Configure the proper SSL protocols and ciphers to match your server.
  • Make sure you have the complete certificate chain and intermediates.
  • Validate hostnames match properly.
  • Check for issues with your local SSL config and certificates.

Tuning your SSL setup will help resolve OpenSSL.SSL.Error exceptions in most cases.

7. Why am I getting SSL validation errors with urllib but not with requests?

The Requests library disables hostname validation for SSL connections by default while urllib does certificate and hostname verification.

To replicate Requests behavior in urllib, disable hostname checking:

import ssl
ssl._https_verify_certificates(False)
Priya Mervana

Priya Mervana

Verified Badge Verified Web Security Experts

Priya Mervana is working at SSLInsights.com as a web security expert with over 10 years of experience writing about encryption, SSL certificates, and online privacy. She aims to make complex security topics easily understandable for everyday internet users.