ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1007)
ID: python/ssl-certificate-verify-failed
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 311 | active | — | — | — |
| 310 | active | — | — | — |
Root Cause
On macOS, the official python.org installer ships with its own OpenSSL that does not use the macOS Keychain certificate store. The installer includes an 'Install Certificates.command' script that installs the certifi CA bundle, but users often skip this step. Running the script or manually installing certifi resolves the issue in nearly all cases.
genericWorkarounds
-
95% success Run the 'Install Certificates.command' script bundled with the python.org installer
Navigate to /Applications/Python 3.11/ and double-click 'Install Certificates.command', or run it from terminal: '/Applications/Python\ 3.11/Install\ Certificates.command'. This script uses pip to install the certifi package and creates a symlink from OpenSSL's expected cert path to certifi's CA bundle.
Sources: https://github.com/python/cpython/blob/main/Mac/BuildScript/resources/install_certificates.command
-
90% success Install certifi and configure SSL_CERT_FILE
Run 'pip install certifi', then set the environment variable: 'export SSL_CERT_FILE=$(python -c "import certifi; print(certifi.where())")'. Add this to your .zshrc for persistence. This tells OpenSSL where to find trusted CA certificates.
Sources: https://pypi.org/project/certifi/
-
88% success Use Homebrew Python instead of python.org installer
Install Python via 'brew install [email protected]'. Homebrew's Python links against Homebrew's OpenSSL which is configured to use the system certificate store. This avoids the certificate issue entirely.
Dead Ends
Common approaches that don't work:
-
Downgrading or replacing the ssl module
95% fail
The ssl module is compiled into CPython and linked against a specific OpenSSL version. It cannot be independently downgraded via pip. Attempting to replace it with pyOpenSSL or other libraries does not change the default SSL context used by urllib, requests, and other standard libraries.
-
Disabling SSL verification globally with ssl._create_unverified_context()
55% fail
While this suppresses the error, it disables all certificate verification, making the application vulnerable to man-in-the-middle attacks. It is a security regression, not a fix. Code using this will fail security audits, and it does not work for libraries that create their own SSL contexts.
-
Setting PYTHONHTTPSVERIFY=0 environment variable
75% fail
This is an undocumented legacy workaround that only affects urllib in older Python versions. It does not affect the requests library, aiohttp, or any library that constructs its own SSL context. Like disabling verification, it is a security hazard.