Home » Wiki » Python Certificate Verify Failed: Self-Signed Certificate in Certificate Chain

Python Certificate Verify Failed: Self-Signed Certificate in Certificate Chain

by | Last updated Mar 14, 2025 | Self-Signed

Python Certificate Verify Failed: Self-Signed Certificate in Certificate Chain
The Python error ‘SSL: CERTIFICATE_VERIFY_FAILED’ occurs when connecting to servers with self-signed certificates. This happens because Python cannot verify the certificate chain against trusted authorities. To fix it, you can add the certificate to your trusted root store, create a custom SSL context, or disable verification (not recommended for production). The solution depends on your security needs and server control.

What Causes the “Certificate Verify Failed” Error in Python?

When Python tries to establish an HTTPS connection, it verifies the server’s SSL certificate against a list of trusted Certificate Authorities (CAs). If the certificate is self-signed (not issued by a trusted CA), Python throws the error:

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1000)

This error is common in scenarios like:

  • Working with internal APIs or servers.
  • Using development environments with self-signed certificates.
  • Testing HTTPS endpoints without valid certificates.

How to Trust a Self-Signed Certificate in Python?

If you control the server and have access to the self-signed certificate, you can add it to Python’s trusted certificate store.

Here’s how:

Step 1: Export the Self-Signed Certificate

  • If you have the certificate file (e.g., server.crt), skip this step.
  • If not, use OpenSSL to export the certificate:
openssl s_client -connect yourserver.com:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM > server.crt

Step 2: Add the Certificate to Python’s CA Bundle

  • Locate Python’s CA bundle file. On most systems, it’s at:
  • Linux: /etc/ssl/certs/ca-certificates.crt
  • macOS: /Applications/Python <version>/Install Certificates.command
  • Windows: <Python installation path>\lib\site-packages\certifi\cacert.pem
  • Append the self-signed certificate to the CA bundle:
cat server.crt >> /path/to/ca-certificates.crt

Step 3: Verify the Fix

  • Restart your Python application and try the HTTPS request again.

How to Fix Certificate Verify Failed: Self-Signed Certificate in Certificate Chain [6 Easy Steps]

Here are some ways to fix the “python certificate verify failed: self-signed certificate in certificate chain” error caused by a self-signed certs:

  • Disable Certificate Verification
  • Specify Certificate Path
  • Update SSL Context
  • Add Certificate to Trusted CA Store
  • Use Certifi to Manage Trusted CAs
  • Use IP Address Instead of Domain

1. Disable Certificate Verification

You can disable certificate verification in Python requests using:

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

And in urllib:

import urllib.request
urllib.request.urlopen("https://example.com", cafile=None, capath=None, cadefault=False)

However, this is insecure and not recommended. It turns off protection against MITM attacks and should only be used for testing.

2. Specify Certificate Path

A better option is to provide the path to the self-signed certificate:

requests.get("https://example.com", verify="path/to/self-signed.crt")

This will tell Python requests to use that certificate to verify the SSL handshake.

For urllib:

import urllib.request
urllib.request.urlopen("https://example.com", cafile="self-signed.crt")

This is safer than disabling verification completely.

3. Update SSL Context

You can also update the default SSL context in Python to trust the self-signed certificate:

import ssl
ssl_context = ssl.create_default_context(cafile="self-signed.crt")
requests.get("https://example.com", verify=ssl_context)

And for urllib:

import ssl
import urllib.request

ssl_context = ssl.create_default_context(cafile="self-signed.crt")
urllib.request.urlopen("https://example.com", context=ssl_context)

This is a bit more flexible than providing the cert path each time.

4. Add Certificate to Trusted CA Store

Rather than providing the self-signed cert each time, you can add it to the trusted CA store:

On Linux/MacOS:

sudo cp self-signed.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

On Windows:

Import it to the system’s root certificates either through the Certificates MMC snap-in or using the CertUtil tool.

This will make Python and other applications trust the self-signed certificate automatically.

5. Use Certifi to Manage Trusted CAs

The Certifi package provides an up-to-date collection of trusted root CA certificates. You can use it to supplement or override the default CA store in Python.

For example, to use Certifi and disable the system CAs:

import certifi
import ssl

ssl_context = ssl.create_default_context(cafile=certifi.where())
requests.get("https://example.com", verify=ssl_context) 
Certifi also makes it easy to add your self-signed cert as a trusted CA:
import certifi

custom_ca = certifi.where() + "\n" + "self-signed.crt" 
requests.get("https://example.com", verify=custom_ca)

This gives you more control over trusted CAs in Python without modifying the system store.

6. Use IP Address Instead of Domain

If you connect to a server using a self-signed certificate locally, you can use the IP address instead of the domain name.

Certificate verification only happens for HTTPS connections based on domain names. Connecting directly to an IP does not trigger certificate validation.

For example:

requests.get("https://127.0.0.1:443", verify=False)

How to Bypass SSL Verification in Python Requests

If you’re using the requests library and need a quick workaround, you can bypass SSL verification. However, this is not recommended for production as it exposes you to security risks.

Example:

import requests
response = requests.get('https://yourserver.com', verify=False)
print(response.text)

Warning:

  • Disabling SSL verification (verify=False) makes your application vulnerable to man-in-the-middle attacks.
  • Use this only in development or testing environments.

Using a Custom CA Bundle to Fix SSL Errors

If you don’t want to modify the global CA bundle, you can specify a custom CA bundle in your Python code.

Step 1: Create a Custom CA Bundle

  • Combine your self-signed certificate with the default CA bundle:
cat server.crt /path/to/ca-certificates.crt > custom-bundle.crt

Step 2: Use the Custom Bundle in Python

  • Pass the custom bundle to the verify parameter in requests:
import requests
response = requests.get('https://yourserver.com', verify='/path/to/custom-bundle.crt')
print(response.text)

How to Ignore Self-Signed Certificate Errors in Python

If you’re working in a controlled environment and want to ignore SSL errors entirely, you can disable SSL verification globally.

Example:

import ssl
import urllib.request

# Disable SSL verification
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE

response = urllib.request.urlopen('https://yourserver.com', context=ssl_context)
print(response.read().decode())

Warning:

  • Disabling SSL verification globally is highly insecure and should only be used in trusted environments.

Best Practices for Handling Self-Signed Certificates in Python

While the above solutions work, it’s important to follow best practices to ensure security:

  1. Use Valid Certificates in Production:
  • Avoid self-signed certificates in production environments.
  • Use certificates issued by trusted CAs (e.g., Let’s Encrypt).
  1. Test with Staging Environments:
  • Use self-signed certificates only in development or staging environments.
  1. Monitor SSL/TLS Configurations:
  • Regularly update your server’s SSL/TLS configurations to avoid vulnerabilities.

Final Thoughts

Python giving a “certificate verify failed” error means it could not validate the server’s SSL certificate chain due to an untrusted self-signed cert.

The best solutions are correctly trusting the self-signed certificate or updating the SSL context rather than simply disabling verification.

Following the outlined troubleshooting steps can help identify and resolve tricky certificate issues using Python requests and other network libraries. Proper SSL certificate handling is important for maintaining security.

Frequently Asked Questions

Why am I suddenly getting certificate verification errors in Python?

Some common reasons you might suddenly get SSL certificate errors in Python include:

  • The server certificate has expired and needs to be renewed.
  • An intermediate CA certificate expired or was revoked.
  • You’re connecting to a new server that uses a self-signed certificate.
  • The web server was reconfigured to use a new certificate.
  • The server disabled TLS 1.2 support, which Python requires.

Inspecting the full certificate chain on the server with openssl can help identify the issue.

How can I inspect certificates on Linux/MacOS?

Use the openssl command to view certificate details. For example:

# View certs provided by a server 
openssl s_client -connect example.com:443 -showcerts

# View a certificate file
openssl x509 -in certificate.crt -text -noout

This will let you inspect certificates, validation paths, expiration dates, etc.

What’s the difference between IP address and domain verification?

Using an IP address doesn’t trigger certificate validation. The domain name is required for the cert common name check.

So using an IP can workaround self-signed certificate errors, but eliminates the security of SSL. Only use IP in development environments when needed.

Can I disable certificate verification permanently in Python?

It is strongly recommended to keep SSL certificate validation enabled whenever possible. Disabling it permanently compromises security.

The best practice is to trust any required self-signed/private certificates at an OS/CA store level instead. That way, Python and other apps have the necessary certificates but keep verification intact.

Why Does Python Reject Self-Signed Certificates?

Python’s SSL module validates certificates against a list of trusted CAs. Self-signed certificates are not in this list, causing the CERTIFICATE_VERIFY_FAILED error.

Is It Safe to Disable SSL Verification?

No. Disabling SSL verification exposes your application to security risks like man-in-the-middle attacks. Use it only in trusted environments.

How do I generate a self-signed certificate for testing?

On Linux/MacOS, you can generate a self-signed certificate using OpenSSL:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
On Windows, you can use PowerShell:
New-SelfSignedCertificate -DnsName "example.com" -CertStoreLocation "Cert:\CurrentUser\My" 
Keep the private key and certificate file to use for testing purposes.
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.

Stay Secure with SSLInsights!

Subscribe to get the latest insights on SSL security, website protection tips, and exclusive updates.

✅ Expert SSL guides
✅ Security alerts & updates
✅ Exclusive offers