Introduction

Python on macOS (especially Python.org distributions) does not use the macOS system keychain for SSL certificate verification. Instead, it relies on the certifi package which bundles Mozilla's root certificates. If certifi is not installed or not configured, every HTTPS connection fails with CERTIFICATE_VERIFY_FAILED.

Symptoms

  • urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)>
  • ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
  • pip install fails for all packages from PyPI
  • Works on Linux but fails on macOS with same code
bash
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/urllib/request.py", line 219, in urlopen
    return opener.open(url, timeout=timeout)
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/urllib/request.py", line 519, in open
    response = self._open(req, data)
  File ".../urllib/request.py", line 541, in _open
    return self._call_chain(self._handle_open, protocol, url)
  File ".../ssl.py", line 517, in wrap_socket
    context.load_verify_locations(cafile)
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED]
certificate verify failed: unable to get local issuer certificate

Common Causes

  • Python.org macOS installer does not configure certificates by default
  • certifi package not installed
  • SSL_CERT_FILE environment variable pointing to wrong location
  • Corporate network with MITM proxy replacing certificates
  • Using Homebrew Python without proper CA bundle

Step-by-Step Fix

  1. 1.Run the Python.org certificate installer:
  2. 2.```bash
  3. 3.# Python.org distributions include this script
  4. 4./Applications/Python\ 3.11/Install\ Certificates.command

# This runs: # pip install --upgrade certifi # ln -s /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/certifi/cacert.pem /Applications/Python\ 3.11/lib/python3.11/site-packages/certifi/cacert.pem ```

  1. 1.Install and configure certifi manually:
  2. 2.```bash
  3. 3.pip install --upgrade certifi

# Verify the certificate bundle exists python -c "import certifi; print(certifi.where())" # Expected: /Library/Frameworks/.../certifi/cacert.pem

# Set environment variable export SSL_CERT_FILE=$(python -c "import certifi; print(certifi.where())") ```

  1. 1.Configure at Python startup:
  2. 2.```python
  3. 3.import os
  4. 4.import certifi

os.environ['SSL_CERT_FILE'] = certifi.where()

import urllib.request response = urllib.request.urlopen('https://api.example.com') ```

  1. 1.Fix for Homebrew Python on macOS:
  2. 2.```bash
  3. 3.# Homebrew Python should use system certificates
  4. 4.brew install ca-certificates
  5. 5.brew postinstall openssl

# Verify python -c " import ssl ctx = ssl.create_default_context() print(f'CA file: {ctx.get_ca_certs()}') " ```

  1. 1.Handle corporate MITM proxy on macOS:
  2. 2.```bash
  3. 3.# Export corporate CA certificate from Keychain Access
  4. 4.# Then combine with certifi bundle
  5. 5.cat /path/to/corporate-ca.pem $(python -c "import certifi; print(certifi.where())") > /tmp/combined-ca.pem
  6. 6.export SSL_CERT_FILE=/tmp/combined-ca.pem
  7. 7.`

Prevention

  • Always run the Install Certificates.command after installing Python.org distribution
  • Add certifi as a dependency in requirements.txt
  • Set SSL_CERT_FILE in application startup code or environment config
  • For Docker on macOS, include CA certificates in the image
  • Test SSL connections in CI on macOS runners to catch certificate issues early