← Back to DevBytes

Fix 'pip install fails' with SSL Certificate Error: Complete Troubleshooting Guide

Understanding the SSL Certificate Error When Using pip

When you run a command like pip install requests and encounter an SSL certificate error, the output typically looks something like this:

SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:XXX)
Could not fetch URL https://pypi.org/simple/requests/: There was a problem confirming the ssl certificate
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:XXX) - skipping

This error occurs because pip uses the requests library under the hood to download packages over HTTPS. When pip attempts to establish a secure connection to PyPI (the Python Package Index) or any other package repository, Python's SSL module verifies the server's certificate against a bundle of trusted Certificate Authorities (CAs). If that verification fails for any reason, the connection is aborted and pip refuses to install the package—this is a deliberate security measure to prevent man-in-the-middle attacks.

The core issue revolves around Python's certificate store. Python ships with its own CA bundle (typically located in certifi or a bundled cacert.pem file), and it also relies on the operating system's certificate store depending on the platform and Python version. When these certificates are missing, outdated, misconfigured, or when a corporate proxy intercepts TLS traffic with a self-signed certificate, the SSL handshake fails and pip stops dead in its tracks.

Why This Error Matters

🚀 Deploy your AI agent in 10 minutes

Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.

Try it free →

Beyond the immediate frustration of being unable to install packages, this error signals a deeper configuration problem that can affect any Python tool relying on HTTPS connections—from Jupyter Notebook extensions to API clients like httpx or requests itself. Ignoring the error by disabling certificate verification (while tempting) creates a significant security vulnerability, especially in production environments where dependency integrity is critical. Understanding the root cause and applying the correct fix ensures that your development workflow remains both functional and secure.

Common Causes of SSL Certificate Errors

Solution 1: Upgrade pip and Related Tools

The simplest first step is to upgrade pip itself. Newer versions of pip bundle an updated certifi package and handle SSL verification more robustly. If your current pip is too old to even bootstrap an upgrade over HTTPS, you can use the get-pip.py script with certificate verification temporarily disabled or download it via curl.

Method A: Upgrade pip directly (if possible)

python -m pip install --upgrade pip

If the above command also fails with the same SSL error, try the bootstrap method:

Method B: Bootstrap pip upgrade using get-pip.py

# Download get-pip.py (use --insecure if curl also has cert issues, but try without first)
curl -O https://bootstrap.pypa.io/get-pip.py

# Run with certificate verification disabled (temporary, for bootstrapping only)
python get-pip.py --trusted-host pypi.org --trusted-host files.pythonhosted.org --trusted-host bootstrap.pypa.io

Once pip is upgraded, also upgrade certifi and setuptools:

pip install --upgrade certifi setuptools

Solution 2: Update System Certificate Stores

On Linux systems, Python often relies on the system's CA certificates. Updating these can resolve the issue without touching Python-specific configuration.

On Debian/Ubuntu:

sudo apt update
sudo apt install --reinstall ca-certificates
sudo update-ca-certificates

On RHEL/CentOS/Fedora:

sudo yum update ca-certificates   # or: sudo dnf update ca-certificates
sudo update-ca-trust

On macOS:

macOS stores certificates in the system keychain. Python 3.6+ on macOS uses the system trust store by default thanks to the Security framework. If you're experiencing issues, ensure your macOS is up to date and that no corporate MDM profiles have altered the trust store incorrectly. You can also manually install additional CA certificates via Keychain Access and mark them as trusted.

Solution 3: Using the certifi Package and Setting SSL_CERT_FILE

The certifi package provides a curated CA bundle from Mozilla. You can explicitly point Python to use this bundle by setting the SSL_CERT_FILE environment variable or by configuring pip to use it.

Step 1: Install certifi (if possible)

pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org certifi

Step 2: Locate the certifi CA bundle path

python -c "import certifi; print(certifi.where())"
# Output example: /usr/local/lib/python3.11/site-packages/certifi/cacert.pem

Step 3: Set the environment variable

# On Linux/macOS (add to ~/.bashrc, ~/.zshrc, or ~/.profile for persistence)
export SSL_CERT_FILE=$(python -c "import certifi; print(certifi.where())")

# On Windows (PowerShell)
$env:SSL_CERT_FILE = (python -c "import certifi; print(certifi.where())")

# On Windows (Command Prompt)
set SSL_CERT_FILE=path\to\certifi\cacert.pem

Alternatively, you can set the REQUESTS_CA_BUNDLE variable, which the requests library specifically honors:

export REQUESTS_CA_BUNDLE=$(python -c "import certifi; print(certifi.where())")

After setting these variables, pip should work normally:

pip install requests  # Now works with proper SSL verification

Solution 4: Configure pip.conf to Use a Custom CA Bundle

You can permanently configure pip to use a specific certificate bundle by editing its configuration file. This avoids having to set environment variables in every shell session.

Linux/macOS configuration file location:

~/.config/pip/pip.conf   # or ~/.pip/pip.conf (legacy)

Windows configuration file location:

%APPDATA%\pip\pip.ini

Sample configuration content:

[global]
cert = /usr/local/lib/python3.11/site-packages/certifi/cacert.pem
# Or on Windows:
# cert = C:\Users\YourName\AppData\Local\Programs\Python\Python311\Lib\site-packages\certifi\cacert.pem

To verify pip is reading your configuration:

pip config list
# Should display: global.cert='...path to your cert bundle...'

Solution 5: Download CA Bundle from Mozilla's Curl Site

If you cannot install certifi via pip (chicken-and-egg problem), you can manually download Mozilla's CA certificate bundle and reference it directly.

# Download the latest CA bundle from Mozilla (via curl's official extract)
curl -O https://curl.se/ca/cacert.pem

# Verify the download (optional but recommended)
sha256sum cacert.pem
# Compare checksum with the one published at https://curl.se/ca/cacert.pem.sha256

# Move it to a persistent location
sudo mkdir -p /usr/local/share/ca-certificates/custom
sudo mv cacert.pem /usr/local/share/ca-certificates/custom/

# Use it with pip
pip config set global.cert /usr/local/share/ca-certificates/custom/cacert.pem

Alternatively, you can set the environment variable on the fly:

SSL_CERT_FILE=/usr/local/share/ca-certificates/custom/cacert.pem pip install requests

Solution 6: Handle Corporate Proxy and TLS Interception

In enterprise environments, a forward proxy or SSL inspection appliance may intercept all HTTPS traffic and re-sign it with an internal CA certificate. Since Python doesn't trust this internal CA by default, pip fails. The proper fix is to add the corporate CA certificate to Python's trust chain.

Step 1: Obtain the corporate CA certificate

Ask your IT department for the PEM-encoded root or intermediate CA certificate. Save it as corporate-ca.pem.

Step 2: Append it to an existing CA bundle

# Locate the existing certifi bundle
python -c "import certifi; print(certifi.where())"

# Append your corporate CA
cat corporate-ca.pem >> $(python -c "import certifi; print(certifi.where())")

Alternatively, create a combined bundle:

cat $(python -c "import certifi; print(certifi.where())") corporate-ca.pem > combined-cacert.pem
pip config set global.cert /path/to/combined-cacert.pem

Step 3: Configure pip proxy settings (if needed)

If your corporate proxy requires specific configuration, add it to pip.conf:

[global]
cert = /path/to/combined-cacert.pem
proxy = http://proxy.company.com:8080

Step 4: Set proxy environment variables (alternative)

export HTTP_PROXY=http://proxy.company.com:8080
export HTTPS_PROXY=http://proxy.company.com:8080
export NO_PROXY=localhost,127.0.0.1,.local

Solution 7: Fix System Time Issues

SSL certificate validation depends heavily on accurate system time. If your system clock is significantly off (wrong timezone, drifted clock, dead CMOS battery on a VM), certificates may appear expired or not-yet-valid. Check and correct your system time:

On Linux:

# Check current system time
date
timedatectl status

# Sync with NTP (Network Time Protocol)
sudo timedatectl set-ntp true
sudo ntpdate -u pool.ntp.org   # if ntpdate is available

# Alternatively, with chrony
sudo chronyd -q 'server pool.ntp.org iburst'

On macOS:

# Check time
date

# Enable automatic time sync
sudo sntp -sS pool.ntp.org

On Windows:

# In PowerShell (run as Administrator)
w32tm /resync /force

After syncing your clock, retry pip install—the SSL error should disappear if time was the culprit.

Solution 8: Reinstall Python with Proper SSL Support

If none of the above solutions work, your Python installation itself might be compromised—compiled without SSL support or with a broken _ssl module. This is common with minimal Docker images or custom-built Pythons. Verify SSL support first:

python -c "import ssl; print(ssl.OPENSSL_VERSION)"
# Should output something like: OpenSSL 1.1.1t  7 Sep 2023

python -c "import urllib.request; print(urllib.request.urlopen('https://pypi.org').status)"
# Should output: 200

If these commands fail with ModuleNotFoundError or ImportError, your Python lacks SSL. Solutions include:

Solution 9: The --trusted-host Flag (Temporary Workaround)

If you absolutely must install a package immediately and understand the security implications, pip provides the --trusted-host flag to bypass SSL verification for specific hosts. This should only be used as a temporary diagnostic measure or on fully trusted internal networks.

pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org package-name

You can also disable verification entirely with --index-url pointing to a plain HTTP mirror, but this is strongly discouraged:

# NOT RECOMMENDED for production or any sensitive environment
pip install --index-url http://pypi.org/simple/ --trusted-host pypi.org package-name

For persistent trusted-host configuration (again, use with caution):

[global]
trusted-host = pypi.org
               files.pythonhosted.org
               pypi.python.org

Debugging SSL Certificate Errors: Diagnostic Commands

Before applying fixes, it's helpful to diagnose exactly where the failure occurs. Here are several diagnostic commands to isolate the problem:

1. Test Python's SSL connectivity:

python -c "
import socket
import ssl
context = ssl.create_default_context()
with socket.create_connection(('pypi.org', 443)) as sock:
    with context.wrap_socket(sock, server_hostname='pypi.org') as ssock:
        print('SSL version:', ssock.version())
        print('Cipher:', ssock.cipher())
        print('Certificate chain:')
        for cert in ssock.getpeercert()['subject']:
            print(' ', cert)
"

2. Check which CA bundle Python is using:

python -c "
import ssl
import os
# Check SSL_CERT_FILE environment variable
print('SSL_CERT_FILE env:', os.environ.get('SSL_CERT_FILE', 'Not set'))
# Check default paths Python searches
print('Default verify paths:', ssl.get_default_verify_paths())
# Check if certifi is available
try:
    import certifi
    print('certifi bundle:', certifi.where())
except ImportError:
    print('certifi not installed')
"

3. Verify a certificate bundle manually:

openssl verify -CAfile /path/to/cacert.pem -untrusted /path/to/cacert.pem /path/to/cacert.pem
# Or to verify PyPI's certificate specifically:
openssl s_client -connect pypi.org:443 -CAfile /path/to/cacert.pem -verify_return_error

4. Test pip's configuration:

pip config list -v
pip debug --verbose

Best Practices to Prevent SSL Certificate Errors

Environment-Specific Quick Reference

Docker Alpine Quick Fix:

FROM python:3.11-alpine
RUN apk add --no-cache ca-certificates openssl
RUN pip install --upgrade pip certifi

macOS with Python from python.org:

# Install certifi and configure pip
pip install certifi
pip config set global.cert $(python -c "import certifi; print(certifi.where())")

Windows with Anaconda:

# Conda environments ship their own SSL stack
conda activate base
conda install certifi -y
pip config set global.cert (python -c "import certifi; print(certifi.where())")

Ubuntu Server (system Python):

sudo apt update && sudo apt install -y ca-certificates python3-certifi
pip config set global.cert /etc/ssl/certs/ca-certificates.crt

Conclusion

The SSL certificate error when running pip install is one of those frustrating roadblocks that can halt productivity, but it almost always stems from a handful of well-understood causes: missing or outdated CA certificates, corporate TLS interception, system clock drift, or a Python installation lacking SSL support. Rather than reaching for the quick but dangerous --trusted-host workaround, methodically diagnose the root cause using the diagnostic commands outlined above, then apply the targeted fix—whether that means upgrading pip, updating system certificates, setting the SSL_CERT_FILE environment variable, or appending a corporate CA to the certifi bundle. By treating SSL verification as a required security feature rather than an inconvenience, you maintain the integrity of your dependency supply chain while keeping your development workflow smooth and predictable. With the solutions in this guide, you should be equipped to resolve any pip SSL certificate error you encounter across Linux, macOS, Windows, containerized, and enterprise environments.

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles