Introduction
urllib3 emits InsecureRequestWarning: Unverified HTTPS request is being made when SSL certificate verification is disabled with verify=False. This warning indicates a security vulnerability -- without verification, the connection is susceptible to man-in-the-middle attacks. While it is tempting to simply suppress the warning, the proper fix is either to configure correct certificate verification or to understand the risks and suppress the warning only in controlled environments like internal testing or development where MITM attacks are not a concern.
Symptoms
/usr/local/lib/python3.11/site-packages/urllib3/connectionpool.py:1099: InsecureRequestWarning: Unverified HTTPS request is being made to host 'api.example.com'. Adding certificate verification is strongly advised.
InsecureRequestWarning,Or deprecation warnings:
DeprecationWarning: 'urllib3.contrib.pyopenssl' module is deprecated and will be removed in a future release of urllib3 2.xCommon Causes
- verify=False in requests: Quick fix for self-signed certificates that triggers warning
- Self-signed certificates in development: Internal APIs without proper CA
- Missing certifi package: No CA bundle available for verification
- Corporate CA not in system trust store: Company proxy uses custom CA
- Warning suppression done incorrectly: Using wrong warning category
- urllib3 2.x breaking changes: Stricter SSL defaults in urllib3 2.0
Step-by-Step Fix
Step 1: Properly configure SSL verification
```python import requests import certifi
# Best: Use proper CA bundle response = requests.get( 'https://api.example.com/data', verify=certifi.where(), # Use certifi's CA bundle )
# For corporate environments, use custom CA bundle response = requests.get( 'https://internal-api.company.com/data', verify='/path/to/corporate-ca-bundle.crt', ) ```
Step 2: Handle self-signed certificates safely
```python import requests from requests.adapters import HTTPAdapter import urllib3
# For development/testing ONLY - understand the security implications def create_insecure_session(): session = requests.Session() adapter = HTTPAdapter(max_retries=3) session.mount('https://', adapter)
# Suppress InsecureRequestWarning urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Make requests without verification session.verify = False return session
# Better: Add custom certificate to verification import ssl
def create_secure_session_with_custom_ca(ca_path): session = requests.Session() session.verify = ca_path return session ```
Step 3: Configure SSL context for fine-grained control
```python import ssl import urllib3
# Create custom SSL context ctx = ssl.create_default_context()
# For self-signed cert: load specific certificate ctx.load_verify_locations('/path/to/server-cert.pem')
# Create pool manager with custom context http = urllib3.PoolManager( cert_reqs='CERT_REQUIRED', ca_certs=certifi.where(), ssl_context=ctx, )
response = http.request('GET', 'https://api.example.com/data') ```
Prevention
- Never use verify=False in production code -- configure proper CA certificates
- Use certifi for consistent CA bundles across environments
- For internal services, deploy a private CA and add it to all clients' trust stores
- Only suppress InsecureRequestWarning in development/testing with clear documentation
- Add SSL certificate expiry monitoring to prevent outages from expired certs
- Use requests.Session() with configured verify path for consistent behavior
- Test SSL configuration as part of your integration test suite