Fixing 'ssl.SSLCertVerificationError: certificate verify failed' on macOS

beginner🍎 macOS2026-05-30| macOS (Monterey, Ventura, Sonoma, Sequoia), Python 3.6 - 3.13 (official python.org installer)

Error Message

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)
#python#ssl#macos#certifi#requests

The SSL Handshake Deadlock

Nothing halts a productive coding session like a sudden SSL handshake failure. Your code might run perfectly on a Linux server, and the URL loads instantly in Safari, yet your Python script dies the moment it tries to fetch data. You're left staring at a traceback that ends in a stubborn error message.

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)

This isn't a code bug or a server failure. It's a configuration gap. Official Python.org installers for macOS don't use the system keychain for root certificates. Instead, they look for a specific certificate bundle that remains inactive by default. Essentially, Python is looking for a list of trusted authorities (like DigiCert or Let's Encrypt) and coming up empty-handed.

Diagnosing the Scope

Start by checking if the issue is limited to Python or affects your entire system. Run a quick test with curl in your terminal:

curl -I https://google.com

If you see a HTTP/2 200 response, your macOS network stack is healthy. The problem is isolated to Python's internal SSL module. Since version 3.6, Python on macOS has bundled its own OpenSSL copy, but it doesn't automatically link it to your system's trust store to prevent permission conflicts.

Solution 1: The "One-Click" Official Fix

If you used the .pkg installer from Python.org, a small utility script is already sitting on your hard drive. This 1KB script installs the certifi package—which contains a bundle of about 150+ root certificates—and creates the symbolic link Python needs.

Open your terminal and run this command for your specific version (e.g., 3.12 or 3.13):

/Applications/Python\ 3.12/Install\ Certificates.command

Not sure which version you're running? Use this wildcard command to find and execute the script automatically:

open /Applications/Python\ 3.*/Install\ Certificates.command

Wait five seconds for the process to finish. It will update pip, install certifi, and link the certificate paths.

Solution 2: The Environment Variable Workaround

Virtual environments or Homebrew installations sometimes skip the Applications folder entirely. In these cases, you can manually point Python to a valid certificate bundle. First, ensure the certifi library is present:

pip install --upgrade certifi

Next, determine the exact path of the certificate store:

python -c "import certifi; print(certifi.where())"

This usually returns a path like .../site-packages/certifi/cacert.pem. To make this change permanent, add an environment variable to your .zshrc (the default shell for modern macOS):

echo "export SSL_CERT_FILE=$(python -c 'import certifi; print(certifi.where())')" >> ~/.zshrc
source ~/.zshrc

Verifying the Fix

Does it actually work now? Run this snippet to verify that even basic Python libraries can now negotiate an HTTPS connection:

python3 -c "import urllib.request; print(urllib.request.urlopen('https://google.com').getcode())"

If it returns 200, you're back in business. If you rely on the requests library, try this as well:

python3 -c "import requests; print(requests.get('https://google.com').status_code)"

Best Practices for the Future

Relying on defaults can be tricky when moving between Windows, Linux, and macOS.

Keep these rules in mind:

  • Post-Install Habits: Always run Install Certificates.command immediately after installing a new Python version on macOS.
  • Virtual Environments: Each environment might need its own certifi installation if it's isolated from system site-packages.
  • Avoid the "Verify=False" Trap: Never bypass this error using verify=False or ssl._create_unverified_context() in a production app. It disables encryption verification, leaving your data wide open to Man-In-The-Middle (MITM) attacks.

Related Error Notes