# How to Fix Python SSL Certificate Verify Failed
SSL certificate verification errors occur when Python cannot validate the SSL certificate of a remote server. This guide covers common causes and solutions.
Error Patterns
requests Library
requests.exceptions.SSLError: HTTPSConnectionPool(host='example.com', port=443):
Max retries exceeded with url: /api/data (Caused by SSLError(
SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED]
certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)')))urllib Library
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED]
certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)>httpx Library
httpx.ConnectError: [SSL: CERTIFICATE_VERIFY_FAILED]
certificate verify failed: self signed certificateaiohttp Library
aiohttp.client.ClientConnectorCertificateError:
Cannot connect to host example.com:443 ssl:True
[SSLCertVerificationError: (1, 'certificate verify failed')]Common Causes
- 1.Self-signed certificates - Server uses certificate not signed by trusted CA
- 2.Expired certificates - Server certificate has expired
- 3.Missing CA bundle - Python cannot find root certificates
- 4.Corporate proxy - Proxy intercepts SSL with custom certificate
- 5.Certificate chain incomplete - Server missing intermediate certificates
- 6.System clock incorrect - Time skew causes validation failure
Diagnosis Steps
Step 1: Check Certificate with OpenSSL
openssl s_client -connect example.com:443 -showcertsStep 2: Verify System Time
date # Linux/macOS
# or
Get-Date # Windows PowerShellStep 3: Check Certificate Details
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -datesStep 4: Test URL in Browser
Open the URL in a browser and check for certificate warnings.
Solutions
Solution 1: Update CA Certificates
```bash # macOS (after Homebrew Python installation) /Applications/Python\ 3.x/Install\ Certificates.command
# Or run this Python script import certifi import ssl print(ssl.get_default_verify_paths()) print(certifi.where()) ```
```bash # Linux (Ubuntu/Debian) sudo apt-get update && sudo apt-get install ca-certificates sudo update-ca-certificates
# Linux (RHEL/CentOS) sudo yum update ca-certificates sudo update-ca-trust ```
# Update certifi package
pip install --upgrade certifiSolution 2: Disable Verification (Development Only)
WARNING: Only use for development/testing, never in production
```python import requests
# Disable SSL verification (NOT RECOMMENDED for production) response = requests.get('https://example.com', verify=False)
# Suppress warnings import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) response = requests.get('https://example.com', verify=False) ```
Solution 3: Specify Custom CA Bundle
```python import requests
# Use custom CA bundle response = requests.get( 'https://example.com', verify='/path/to/ca-bundle.crt' )
# Or set environment variable import os os.environ['REQUESTS_CA_BUNDLE'] = '/path/to/ca-bundle.crt' os.environ['SSL_CERT_FILE'] = '/path/to/ca-bundle.crt' ```
Solution 4: Handle Self-Signed Certificates
```python import requests
# For self-signed certificate response = requests.get( 'https://self-signed.example.com', verify='/path/to/server.crt' )
# Or use certifi with custom cert import certifi import requests
# Add custom cert to certifi bundle # Then use normally response = requests.get('https://internal.example.com') ```
Solution 5: Corporate Proxy Certificates
```python import os import requests
# Set proxy certificate os.environ['REQUESTS_CA_BUNDLE'] = '/path/to/corporate-proxy-ca.pem' os.environ['HTTP_PROXY'] = 'http://proxy.company.com:8080' os.environ['HTTPS_PROXY'] = 'http://proxy.company.com:8080'
response = requests.get('https://example.com') ```
Solution 6: Fix urllib SSL Issues
```python import ssl import urllib.request
# Create SSL context ssl_context = ssl.create_default_context() ssl_context.load_verify_locations('/path/to/ca-bundle.crt')
# Use with urlopen with urllib.request.urlopen('https://example.com', context=ssl_context) as response: content = response.read() ```
Solution 7: Async Libraries (aiohttp)
```python import ssl import aiohttp
ssl_context = ssl.create_default_context() ssl_context.load_verify_locations('/path/to/ca-bundle.crt')
async with aiohttp.ClientSession() as session: async with session.get('https://example.com', ssl=ssl_context) as response: content = await response.text() ```
Solution 8: httpx Library
```python import httpx
# Custom verify response = httpx.get('https://example.com', verify='/path/to/ca-bundle.crt')
# Or with client with httpx.Client(verify='/path/to/ca-bundle.crt') as client: response = client.get('https://example.com') ```
Extract and Use Server Certificate
Extract Certificate from Server
# Get certificate from server
openssl s_client -connect example.com:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM > server.crtUse Extracted Certificate
```python import requests
response = requests.get( 'https://example.com', verify='server.crt' ) ```
Combine Multiple Certificates
# Create a custom CA bundle
cat /etc/ssl/certs/ca-certificates.crt > custom-ca-bundle.crt
cat corporate-proxy.pem >> custom-ca-bundle.crt
cat self-signed-server.crt >> custom-ca-bundle.crtimport os
os.environ['REQUESTS_CA_BUNDLE'] = '/path/to/custom-ca-bundle.crt'Prevention Tips
- 1.Keep certifi updated:
pip install --upgrade certifi - 2.Use proper certificates in production
- 3.Set up certificate rotation before expiry
- 4.Monitor certificate expiry with automation
```python # Check certificate expiry import ssl import socket from datetime import datetime
def check_cert_expiry(hostname, port=443): context = ssl.create_default_context() with socket.create_connection((hostname, port)) as sock: with context.wrap_socket(sock, server_hostname=hostname) as ssock: cert = ssock.getpeercert() expiry = datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z') days_left = (expiry - datetime.now()).days return days_left
days = check_cert_expiry('example.com') print(f"Certificate expires in {days} days") ```
Related Errors
ConnectionRefusedError- Server not accepting connectionssocket.timeout- Connection timed outCertificateError- Hostname mismatch