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
- Outdated or missing CA bundle: The
certifipackage or the bundled certificate file is stale or not present - Corporate proxy or firewall: A network appliance performs TLS interception and presents a self-signed or enterprise CA certificate that Python doesn't trust
- Expired system certificates: On Linux systems, the
ca-certificatespackage hasn't been updated - Python compiled without SSL support: A custom-built Python interpreter lacks the necessary SSL module
- Incorrect system time: Certificate validity checks fail because the system clock is significantly off
- Virtual environment issues: The virtual environment's Python doesn't have access to the correct certificate bundle
- Outdated pip version: Very old versions of pip may use deprecated SSL/TLS protocols
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:
- Use an official Python installer from python.org (Windows/macOS)
- Install Python from your distribution's package manager (Linux):
sudo apt install python3 python3-pip python3-certifi - Use a Docker image with full Python:
python:3.11-sliminstead ofpython:3.11-alpine(alpine may requireapk add openssl ca-certificates) - Use conda/miniconda which bundles its own SSL stack
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
- Keep Python and pip updated: Regularly run
pip install --upgrade pip setuptools certifias part of environment maintenance - Use official Python distributions: Avoid minimal or custom-compiled Python interpreters unless you explicitly need them and understand the trade-offs
- Maintain system certificates: On Linux servers, include
ca-certificatesupdates in your regular OS patching cycle - Use virtual environments consistently: Create fresh virtual environments with
python -m venv --copies venv(the--copiesflag avoids symlink issues that can cause certificate resolution problems) - Never disable SSL verification permanently: Avoid setting
trusted-hostin global pip.conf. If you must bypass verification temporarily, use command-line flags and remove them immediately after - In Docker, install CA certificates explicitly: Add
RUN apt-get update && apt-get install -y ca-certificates && update-ca-certificatesto your Dockerfile for Debian-based images, or the equivalent for Alpine - Set SSL_CERT_FILE in CI/CD pipelines: Ensure continuous integration environments explicitly point to a valid CA bundle, especially if running on minimal container images
- Document corporate CA requirements: If your organization uses TLS interception, document the process of adding internal CA certificates in your onboarding guide so new developers don't waste hours troubleshooting
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.