SSL Verification and urllib3 Warnings in Python Requests
Provide a valid CA bundle path to verify='/path/to/cert.pem' or disable warnings explicitly with urllib3.disable_warnings() when using verify=False.
Root Cause Analysis
This error occurs when Python tries to establish a secure TLS/SSL socket connection with an HTTPS server, but the server's certificate validation fails against the local OpenSSL trust store or CA bundle.
1. Self-Signed and Internal Enterprise Certificates
In enterprise, staging, or local development environments, APIs frequently use self-signed certificates or certificates issued by private internal CAs. Because Python's certifi bundle only includes public trusted root authorities, the TLS handshake fails with SSLCertVerificationError.
2. InsecureRequestWarning Floods
When developers bypass the error by passing verify=False, urllib3 emits InsecureRequestWarning on every single request. In automated pipelines or scripts, unhandled warnings can cause test failures or pollute log files.
3. Strict TLS Protocol Mismatches in Modern urllib3 2.0+
Urllib3 2.0+ deprecated legacy TLS 1.0/1.1 and insecure ciphers. Servers running legacy TLS stacks will fail even if certificate verification is ignored.
4. Expired or Revoked Certificates
Production endpoints with expired SSL certificates will immediately reject client requests until updated certificates are installed on the server.
Reproduction Code (MCVE)
import requests
# Simulating an SSL certificate verification failure
raise requests.exceptions.SSLError(
'HTTPSConnectionPool(host="api.internal", port=443): Max retries exceeded with url: / '
'(Caused by SSLError(SSLCertVerificationError(1, "[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate")))'
)
Solution 1: Disable InsecureRequestWarning for Local Testing
When verify=False is necessary in development, suppress the associated InsecureRequestWarning cleanly.
import urllib3
import requests
# Suppress InsecureRequestWarning for development testing
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
print('InsecureRequestWarning successfully disabled for testing.')
Solution 2: Pass Custom CA Bundle Path to verify Parameter
Point verify to your enterprise CA bundle (.pem or .crt file) for production security without disabling verification.
import os
import requests
# Proper enterprise configuration using CA bundle
ca_cert_path = '/etc/ssl/certs/custom-ca-bundle.pem'
print(f'Configured custom CA trust store: {ca_cert_path}')
print('Pass verify=ca_cert_path in requests.get() or set REQUESTS_CA_BUNDLE environment variable.')
A dangerous security mistake is leaving verify=False in production code. Disabling SSL verification leaves all API communication vulnerable to Man-in-the-Middle (MITM) attacks. Always install the private CA certificate into the system trust store or point REQUESTS_CA_BUNDLE to the .pem file. Edge cases occur in Docker containers where ca-certificates package is missing: run apt-get install -y ca-certificates to install root CAs. Contrast this error with requests.exceptions.ConnectionError, which occurs when the server is unreachable or refused connection.