This site is an archive and is no longer updated.
    Back to Guides
    TroubleshootingPython

    Python SSL Certificate Errors - The Complete Fix

    The dreaded CERTIFICATE_VERIFY_FAILED - every Python developer hits it eventually. Here's how to fix it properly.

    15 min readJuly 2026
    LinkedInX
    Python SSL certificate errors and solutions

    pip SSL error: certificate verify failed on pip install

    The exact error text pip shows:

    Could not fetch URL https://pypi.org/simple/...: There was a problem confirming the ssl certificate: ... SSL: CERTIFICATE_VERIFY_FAILED

    Three causes, in order of likelihood:

    1. Corporate TLS-inspection proxy — your network device (Zscaler, Palo Alto, Bluecoat) intercepts the connection to pypi.org and re-signs it with a corporate root CA that Python's certifi bundle doesn't know about.
    2. Stale certifi bundle or old pip/Python build — a root CA was removed or rotated, and your locally installed certifi no longer includes it.
    3. macOS python.org installer — the "Install Certificates.command" step was never run after installation, so the interpreter has no CA bundle wired in at all.

    First: upgrade pip (this alone often fixes it)

    Modern pip (24.2 and later, on Python 3.10+) validates TLS against the operating system trust store by default via truststore. If your machine already trusts the corporate root — which it usually does after your IT team pushes it — upgrading pip fixes the error with no further configuration.

    python -m pip install --upgrade pip

    Corporate proxy: point pip at the corp root CA

    If upgrading pip doesn't resolve it, tell pip explicitly where your corporate CA bundle lives:

    # Persist for all pip commands on this machine
    pip config set global.cert /path/to/corp-bundle.pem
    
    # Or one-off per install
    pip install --cert /path/to/corp-bundle.pem <package>

    The bundle must contain the full chain including public roots if the proxy only intercepts some traffic — the same full-bundle rule that applies to Git's sslCAInfo setting.

    macOS: run Install Certificates.command

    Python installers from python.org ship without CA certs wired to the macOS system keychain. Run the installer script that came with your Python version:

    # Adjust the version number to match your Python install
    open "/Applications/Python 3.12/Install Certificates.command"

    This runs a one-time script that installs certifi for that interpreter and symlinks it correctly. After running it, pip installs should succeed without any cert flags.

    What not to do

    Avoid this shortcut: pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org disables certificate verification for those hosts entirely. It carries the same risk profile as git config --global http.sslVerify false — acceptable only as a scoped, temporary escape hatch while you track down the real CA issue, and never something to commit into requirements docs or CI configuration.

    The same TLS-inspection root cause breaks Git clone and push in the same environments. SSL certificate problem in Git covers the equivalent diagnosis and fixes for Git.

    Understanding Python SSL Errors

    Why Python SSL errors happen:

    • •Python has its own certificate bundle (certifi) - it doesn't use your system's trust store
    • •Corporate proxies intercept HTTPS (MITM inspection) - the #1 cause in enterprise environments
    • •Self-signed certificates in dev/test environments
    • •Outdated Python/certifi with expired or removed root CAs
    • •System clock wrong (rare but happens)

    Common error messages you'll see:

    ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED]
    urllib3.exceptions.SSLError: HTTPSConnectionPool
    requests.exceptions.SSLError: certificate verify failed
    pip._vendor.urllib3.exceptions.SSLError
    conda.exceptions.CondaSSLError

    pip Install SSL Errors

    The error:

    pip install requests
    WARNING: Retrying... after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED]...'))'

    Fixes (in order of preference):

    1. Upgrade pip and certifi first:

    python -m pip install --upgrade pip certifi

    2. Corporate proxy? Add your company's root cert:

    # Find where certifi stores certs
    python -c "import certifi; print(certifi.where())"
    
    # Append your corporate CA
    cat corporate-root-ca.pem >> /path/to/certifi/cacert.pem

    3. Temporary bypass (NOT for production):

    pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org <package>

    4. Permanent config (pip.conf/pip.ini):

    [global]
    trusted-host = pypi.org
                   pypi.python.org
                   files.pythonhosted.org
    Why --trusted-host is dangerous: You're disabling certificate verification, making yourself vulnerable to man-in-the-middle attacks. Only use temporarily for troubleshooting.

    requests Library SSL Errors

    The error:

    requests.get("https://internal-server.company.com")
    # requests.exceptions.SSLError: HTTPSConnectionPool...
    # (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED]')))

    Solutions:

    1. Point to your CA bundle:

    import requests
    response = requests.get("https://internal-server.company.com", verify="/path/to/ca-bundle.crt")

    2. Add cert to certifi permanently:

    import certifi
    print(certifi.where())  # Find the bundle
    # Then append your CA cert to this file

    3. Environment variable:

    export REQUESTS_CA_BUNDLE=/path/to/ca-bundle.crt
    # or
    export SSL_CERT_FILE=/path/to/ca-bundle.crt

    4. The "I just need it to work" approach:

    import requests
    response = requests.get("https://example.com", verify=False)
    
    # Suppress warning
    import urllib3
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    Never use verify=False in production. You're accepting ANY certificate, including attacker-controlled ones.

    conda SSL Errors

    The error:

    CondaSSLError: Encountered an SSL error. Most likely a certificate verification issue.

    Solutions:

    1. Update conda:

    conda update conda
    conda update --all

    2. Configure custom certs:

    conda config --set ssl_verify /path/to/corporate-ca-bundle.crt

    3. Check .condarc:

    ssl_verify: /path/to/corporate-ca-bundle.crt

    4. Corporate proxy:

    conda config --set proxy_servers.http http://proxy.company.com:8080
    conda config --set proxy_servers.https https://proxy.company.com:8080

    Corporate Proxy / MITM Inspection (THE REAL PROBLEM)

    This is the root cause for most enterprise users. If you're on a corporate network, start here.

    What's happening:

    Corporate networks use SSL inspection (Zscaler, Bluecoat, Palo Alto) that:

    1. Intercepts your HTTPS connection
    2. Decrypts with their CA
    3. Inspects the content
    4. Re-encrypts with corporate certificate
    5. Your apps see "untrusted" certificate because they don't know the corporate CA

    The permanent fix:

    # 1. Get corporate root CA from IT or export from browser
    # Chrome: Settings > Security > Manage certificates > Export
    
    # 2. Find Python's cert bundle
    python -c "import certifi; print(certifi.where())"
    
    # 3. Append your corporate CA
    cat corporate-root-ca.pem >> /path/to/certifi/cacert.pem
    
    # 4. Verify it works
    python -c "import requests; requests.get('https://pypi.org')"
    Pro tip: Create a script that does this automatically for new Python installations or virtual environments.

    Self-Signed Certificates (Dev/Test)

    Option 1: Add to trust store (recommended)

    import requests
    response = requests.get("https://internal-server:8443", verify="/path/to/self-signed-cert.pem")

    Option 2: Use mkcert for local dev

    brew install mkcert
    mkcert -install
    mkcert localhost 127.0.0.1 ::1

    mkcert creates locally-trusted certificates that work with Python automatically.

    Hostname Mismatch

    The error:

    ssl.CertificateError: hostname 'wrong-name.com' doesn't match 'correct-name.com'

    Common causes:

    • •Connecting by IP address when certificate has hostname
    • •Certificate missing Subject Alternative Name (SAN)
    • •Wrong hostname hardcoded in your application

    Solutions:

    1. Use the exact hostname from the certificate
    2. Add IP to certificate's SAN field when generating
    3. Reissue certificate with correct names

    Jupyter Notebook SSL Errors

    # In notebook cell
    import os
    os.environ['REQUESTS_CA_BUNDLE'] = '/path/to/ca-bundle.crt'
    
    # Or configure pip from notebook
    !pip config set global.trusted-host "pypi.org pypi.python.org files.pythonhosted.org"

    macOS-Specific Issues

    The problem: Python installed from python.org on macOS doesn't use system certificates by default.

    The fix:

    # Run the certificate installer (adjust version number)
    /Applications/Python\ 3.12/Install\ Certificates.command
    
    # Or manually
    pip install --upgrade certifi

    Debugging SSL Errors

    Enable debug logging:

    import ssl
    import logging
    logging.basicConfig(level=logging.DEBUG)
    
    import http.client
    http.client.HTTPConnection.debuglevel = 1

    Check certificate with Python:

    import ssl
    import socket
    
    hostname = 'example.com'
    context = ssl.create_default_context()
    
    with socket.create_connection((hostname, 443)) as sock:
        with context.wrap_socket(sock, server_hostname=hostname) as ssock:
            print(ssock.getpeercert())

    Use OpenSSL for detailed analysis:

    openssl s_client -connect example.com:443 -showcerts

    See our OpenSSL s_client guide for more debugging techniques.

    Quick Reference Table

    ErrorLikely CauseQuick Fix
    CERTIFICATE_VERIFY_FAILEDCorp proxy / self-signedAdd CA to certifi
    pip SSL errorCorp proxy / old certifipip install --upgrade certifi
    hostname mismatchWrong hostnameUse hostname from cert
    certificate expiredOutdated certifiUpdate certifi / check clock
    unable to get local issuerMissing intermediateGet full chain

    The Right Way vs The Wrong Way

    DON'T do this in production:

    requests.get(url, verify=False)
    urllib3.disable_warnings()
    ssl._create_default_https_context = ssl._create_unverified_context

    DO this instead:

    import certifi
    import requests
    # Add your CA to certifi bundle, then:
    response = requests.get(url, verify=certifi.where())

    FAQ

    Q: Why does Python use its own certificate store?

    Python includes certifi for cross-platform consistency. System trust stores vary significantly between Windows, macOS, and Linux distributions.

    Q: Is verify=False safe for internal APIs?

    No. Internal networks can be compromised. Configure proper trust even for internal services.

    Q: How do I find my corporate proxy's CA certificate?

    Export from your browser (Chrome → Settings → Security → Manage Certificates) or ask your IT department.

    Q: Why did SSL work yesterday but not today?

    Common causes: certificate expired, certifi updated with removed roots, or system time changed.

    Related Resources