How to Fix “SSL: CERTIFICATE_VERIFY_FAILED” Errors in Python Requests

Encountering an SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] while writing Python web scrapers, automation scripts, or API integrations can instantly halt your workflow. This error occurs when Python’s underlying transport layer cannot cryptographically verify the SSL/TLS certificate presented by the target server. It acts as a crucial security measure to protect your environment from man-in-the-middle (MITM) attacks, but it frequently triggers false positives due to outdated local certificate bundles, corporate interception proxies, or self-signed certificates.

Learning how to fix SSL CERTIFICATE_VERIFY_FAILED errors in Python requests safely requires distinguishing between development workarounds and production-grade security practices. This guide breaks down the core causes of SSL verification failures and provides actionable, step-by-step solutions to resolve them.

Key Takeaways

  • The Root Cause: The error happens because Python’s requests library relies on trusted Certificate Authorities (CAs) that may be missing, outdated, or intercepted by a local corporate network proxy.
  • Avoid verify=False in Production: While setting verify=False provides an immediate local workaround, it disables encryption validation entirely and leaves applications vulnerable to security exploits.
  • Update the certifi Package: Frequently, the easiest fix is ensuring your Python environment’s root certificate bundle is fully updated to the latest standard.
  • Handle Enterprise Proxies Correctly: Corporate SSL-inspection firewalls require injecting custom enterprise root .pem certificates into your environment paths or explicit request parameters.

Why the “SSL: CERTIFICATE_VERIFY_FAILED” Error Occurs

Before implementing a fix, it helps to understand why Python raises this exception. When your script executes an HTTPS request using the popular requests library, the system performs a cryptographic handshake with the remote server.

┌────────────────────────────────────────────────────────────────────────┐
│               PYTHON SSL VERIFICATION HANDSHAKE FAILURE                │
├───────────────────────────────┬────────────────────────────────────────┤
│ TRIGGER CONDITION             │ UNDERLYING REASON                      │
├───────────────────────────────┼────────────────────────────────────────┤
│ Outdated Python/OpenSSL       │ Local system trust store lacks modern  │
│                               │ root certificates.                     │
├───────────────────────────────┼────────────────────────────────────────┤
│ Corporate SSL Proxy           │ Firewall intercepts traffic and signs  │
│                               │ with an untrusted internal CA cert.    │
├───────────────────────────────┼────────────────────────────────────────┤
│ Self-Signed Certificates      │ Target domain uses a private key not   │
│                               │ recognized by public CAs.              │
├───────────────────────────────┼────────────────────────────────────────┤
│ Expired Domain Certificate    │ Target server's SSL certificate has    │
│                               │ passed its expiration date.            │
└───────────────────────────────┴────────────────────────────────────────┘

If the root certificate authority that signed the server’s certificate is not present in Python’s trusted bundle—or if your network traffic is being decrypted by a corporate gateway—the cryptographic check fails immediately.

Solution 1: Update the certifi Package

Python’s requests library depends on the certifi package to provide a curated collection of root certificates. If your local development environment runs an older version of certifi, it may fail to validate domains using modern intermediate certificates.

Step 1: Upgrade Certifi and Requests via Pip

Open your terminal and ensure your packages are running the latest versions:

Bash

pip install --upgrade requests certifi

Step 2: Reference Certifi Explicitly in Your Code

Pass certifi.where() directly into your request’s verify parameter to ensure Python uses the updated bundle:

Python

import requests
import certifi

url = "https://example.com"
response = requests.get(url, verify=certifi.where())

print(response.status_code)

Solution 2: Configure Custom CA Bundles for Corporate Proxies

If you are developing inside an enterprise network, your company firewall likely intercepts HTTPS traffic to scan for malware, re-signing requests with an internal corporate Root CA. Because Python does not trust your company’s private certificate authority by default, it throws a verification error.

Step 1: Export Your Corporate Certificate

Obtain your company’s root certificate file from your IT security team in .pem or .crt format (e.g., corp-root-ca.pem).

Step 2: Set the REQUESTS_CA_BUNDLE Environment Variable

You can configure your operating system environment so that every Python script automatically trusts your corporate certificate without modifying individual code files:

  • On Linux / macOS:Bashexport REQUESTS_CA_BUNDLE="/path/to/corp-root-ca.pem"
  • On Windows (PowerShell):PowerShell$env:REQUESTS_CA_BUNDLE="C:\path\to\corp-root-ca.pem"

Step 3: Pass the Certificate Path Explicitly in Code

Alternatively, target the local certificate file directly inside your script:

Python

import requests

url = "https://internal.enterprise-app.com"
cert_path = "/path/to/corp-root-ca.pem"

response = requests.get(url, verify=cert_path)
print(response.json())

Solution 3: Handle Self-Signed Certificates in Local Development

When testing against local microservices or staging environments utilizing self-signed certificates, public CAs will always reject the handshake.

You can explicitly point your request to your local development certificate file:

Python

import requests

local_url = "https://localhost:8443/api/v1/status"
ca_cert = "/certs/local-dev-root.crt"

# Bypass verification against public CAs by trusting the local cert file
response = requests.get(local_url, verify=ca_cert)
print(response.text)

Solution 4: The Development Workaround (verify=False)

If you are working in a strictly isolated local sandbox and need a quick workaround for debugging, you can disable SSL verification entirely by setting verify=False:

Python

import requests

url = "https://self-signed.badssl.com/"

# WARNING: Disables SSL certificate verification
response = requests.get(url, verify=False)
print(response.text)

Crucial Security Warning: Setting verify=False disables cryptographic certificate checks, exposing your script to Man-in-the-Middle (MITM) attacks. Never use verify=False in production environments or when transmitting sensitive user data. When enabled, Python will also raise an InsecureRequestWarning in your console logs.

Summary Checklist for Troubleshooting SSL Errors

Use this quick troubleshooting flow when diagnosing SSLError exceptions in Python:

  1. Are you on a corporate network? →→ Export your company’s root .pem certificate and set REQUESTS_CA_BUNDLE.
  2. Is your local certifi package outdated? →→ Run pip install --upgrade certifi and pass verify=certifi.where().
  3. Is the target server using a self-signed cert? →→ Download the .crt file and pass its file path into the verify parameter.
  4. Is this purely a local development test? →→ Use verify=False temporarily, but never deploy it to production.

Conclusion

Resolving the SSL: CERTIFICATE_VERIFY_FAILED error in Python requests requires balancing debugging speed with strict network security standards. While setting verify=False offers a fast temporary workaround for local testing,production applications should always maintain cryptographic validation by updating certifi bundles, configuring custom corporate CA paths, or trusting explicit self-signed certificates. By applying these structured solutions, you can maintain secure, uninterrupted API integrations across all environments.

Frequently Asked Questions (FAQs)

What does verify=False do in Python requests?

Setting verify=False tells the requests library to skip SSL/TLS certificate verification entirely. While this successfully bypasses the verification error, it leaves your application vulnerable to interception and man-in-the-middle attacks.

How do I fix SSL errors behind a corporate proxy?

Corporate firewalls often intercept and re-sign HTTPS traffic using private internal certificates. To fix this, export your company’s root certificate as a .pem file and either pass its file path to verify='/path/to/ca.pem' or set the REQUESTS_CA_BUNDLE environment variable.

Why does my script work on my local machine but fail on a production server?

Production servers often run isolated Linux environments with outdated operating system trust stores, older OpenSSL versions, or restricted outbound network policies. Ensuring that both certifi and your system’s OpenSSL packages are fully updated on the server resolves most environment-specific discrepancies.

1 thought on “How to Fix “SSL: CERTIFICATE_VERIFY_FAILED” Errors in Python Requests”

Leave a Comment