Python “CERTIFICATE_VERIFY_FAILED” on macOS: why it happens and the right fix
The website’s certificate is usually fine. The problem is that this copy of Python can’t find a list of trusted certificate authorities to check it against. The python.org installer for macOS doesn’t use the Mac’s Keychain and ships without that list until you run one small script.
The error
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED]
certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)>
Python uses its own copy of OpenSSL. OpenSSL looks for trusted root certificates in a file and a folder it was built to expect. The python.org macOS installer leaves those empty and puts a helper script, Install Certificates.command, in /Applications/Python 3.x/. Until it runs, every HTTPS connection made with the standard library fails, even to sites that work perfectly in your browser.
Why requests works but urllib doesn’t
The requests library uses the certifi package’s certificate list directly, so it doesn’t care what OpenSSL finds. urllib, http.client, asyncio, smtplib and tools built on them (some pip plugins, nltk.download(), torchvision dataset downloads, yt-dlp in some setups) use the default context and fail. aiohttp and httpx vary by version.
Fixes, in order
| Your setup | Fix |
|---|---|
| Python from python.org | Run Install Certificates.command once per Python version (Finder: Applications, Python 3.x, double-click it) |
| Can’t find the script, or a virtual environment | pip install --upgrade certifi then export SSL_CERT_FILE="$(python3 -m certifi)" in your shell profile |
| Homebrew, pyenv or conda Python | Usually fine. If not: brew reinstall ca-certificates openssl@3, or rebuild the pyenv version after it; for conda, conda update ca-certificates certifi |
| Company network that inspects HTTPS (Zscaler, Netskope and similar) | Get the company root certificate as a .pem, append it to a copy of the certifi bundle and point SSL_CERT_FILE and REQUESTS_CA_BUNDLE at that copy |
| You’d rather trust what the Mac trusts | Python 3.10+: pip install truststore, then import truststore; truststore.inject_into_ssl() at the top of your program uses the Keychain |
Check what Python is using
python3 -c "import ssl; print(ssl.get_default_verify_paths())"
python3 -c "import ssl, urllib.request; urllib.request.urlopen('https://example.com'); print('ok')"
python3 -m certifi # path of the certifi bundle
If cafile points at a file that doesn’t exist, that’s the whole problem.
What not to do
ssl._create_unverified_context(), verify=False and PYTHONHTTPSVERIFY=0 make the error go away by accepting any certificate at all, including one from someone sitting on the same café Wi-Fi. Fine for a throwaway test against your own laptop; never in code that ships or handles passwords and tokens.
Related errors
The same message on Linux, in Node or in git usually means a missing intermediate certificate on the server or a proxy: see unable to get local issuer certificate. A real expired certificate is a different fix: certificate has expired. And wrong version number means you spoke HTTPS to a plain HTTP port: SSL wrong version number. Want to peek inside a PEM block someone sent you? Paste it into What is this?.
Questions
How do I fix CERTIFICATE_VERIFY_FAILED in Python on a Mac?
If Python came from python.org, run Install Certificates.command in /Applications/Python 3.x/. Otherwise install certifi and set SSL_CERT_FILE to the path printed by python3 -m certifi.
Why does requests work but urllib fails with CERTIFICATE_VERIFY_FAILED?
requests uses the certifi certificate bundle directly, while urllib uses OpenSSL's default locations, which the python.org macOS installer leaves empty until Install Certificates.command runs.
Do I need to run Install Certificates.command again?
Yes, once for each new Python version you install from python.org, because each has its own OpenSSL folder.
Is it OK to disable SSL verification to fix it?
Only for a quick local test. Turning verification off accepts any certificate, so anyone on the network could read or change the traffic.
Published .