Why Do the Certificate Verify Failed: Self-Signed Certificate in Certificate Chain Occur?
The Python “Certificate Verify Failed: Self-Signed Certificate in Certificate Chain” error occurs when Python cannot verify the SSL/TLS certificate of a website during HTTPS requests. This issue happens because Python detects a self-signed certificate instead of one from a trusted Certificate Authority (CA).
To fix this error, you can add the certificate to your trusted CA store, use the verify=False parameter in your requests (not recommended for production), or install required root certificates. The error commonly appears in development environments where self-signed certificates are used for testing purposes.
What Does “Certificate Verify Failed” Mean in Python?
The “Certificate Verify Failed” error in Python means SSL/TLS certificate validation has failed during a secure HTTPS connection. This happens when Python’s security system cannot confirm if a website’s certificate is trustworthy. The error shows up when Python finds an invalid, expired, or self-signed certificate in the chain of trust.
Think of it as Python’s security guard stopping you from connecting to a website because its ID card looks suspicious. The error protects users from potential security risks like man-in-the-middle attacks and data breaches, but it can block legitimate connections if certificates are not properly configured.
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)
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)
This bypasses the SSL authentication and certificate errors.
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.
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
New-SelfSignedCertificate -DnsName "example.com" -CertStoreLocation "Cert:\CurrentUser\My"
Priya Mervana
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.