Skip to main content

Fixed: "[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate" in Python on macOS

· 7 min read
Jagdish Kumawat
Founder @ Dewiride

A Python script on my Mac couldn't open an HTTPS address: ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate. curl opened the same address without a problem. Python from python.org brings its own OpenSSL, which doesn't use the Mac's certificates, and the fix is a script that comes with it: Install Certificates.

What I Was Doing​

I first got this error in a small Python script that checks image addresses over HTTPS, run with an older Python from python.org. It's the same with the newest one, Python 3.15.2, installed with python.org's macOS installer. This script opens one address and prints the HTTP status:

check_url.py
import urllib.request

url = "https://www.python.org/"
with urllib.request.urlopen(url, timeout=30) as response:
print(response.status, url)
Terminal
python3 --version
python3 check_url.py

What I Expected​

Python 3.15.2, then 200 https://www.python.org/.

What I Got​

Output (the lines that matter)
Python 3.15.2
Traceback (most recent call last):
...
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1147)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
...
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1147)>

A terminal where python3 --version prints Python 3.15.2, and python3 check_url.py fails with ssl.SSLCertVerificationError: CERTIFICATE_VERIFY_FAILED, unable to get local issuer certificate, then urllib.error.URLError with the same message.

Two errors, one cause: the ssl module refused the server's certificate during the TLS handshake, and urllib passed that on as a URLError.

What I Checked​

Whether the site and the network were fine. curl, which comes with macOS, asked the same address for its headers:

Terminal
curl -sI https://www.python.org/ | head -1
Output
HTTP/2 200

So the server's certificate was valid for curl. The problem was in Python.

Where Python looks for certificates. The ssl module can say which OpenSSL it uses and where that OpenSSL looks for trusted certificates:

Terminal
python3 -c "import ssl; print(ssl.OPENSSL_VERSION); print(ssl.get_default_verify_paths())"
Output
OpenSSL 3.5.9 29 Sep 2026
DefaultVerifyPaths(cafile=None, capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/Library/Frameworks/Python.framework/Versions/3.15/etc/openssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/Library/Frameworks/Python.framework/Versions/3.15/etc/openssl/certs')

Python's own OpenSSL 3.5.9 expects a file of trusted certificates at /Library/Frameworks/Python.framework/Versions/3.15/etc/openssl/cert.pem.

What's in that folder.

Terminal
ls -la /Library/Frameworks/Python.framework/Versions/3.15/etc/openssl/
Output
total 0
drwxrwxr-x@ 2 root admin 64 Oct 26 02:53 .
drwxrwxr-x@ 3 root admin 96 Oct 26 02:53 ..

Empty: no cert.pem, so this OpenSSL trusted no certificate authority at all.

What python.org says. The installer's ReadMe, also in /Applications/Python 3.15/ReadMe.rtf: "This package includes its own private copy of OpenSSL 3. The trust certificates in system and user keychains managed by the Keychain Access application and the security command line utility are not used as defaults by the Python ssl module. A sample command script is included in /Applications/Python 3.15 to install a curated bundle of default root certificates from the third-party certifi package". Python's own Using Python on macOS page lists it as the last step of installing: "Double-click on the Install Certificates.command icon or file in the /Applications/Python 3.15/ window to complete the installation."

Why It Happens​

Python from python.org's macOS installer uses its own copy of OpenSSL, not the Mac's certificate store. That OpenSSL trusts the certificates in one file, cert.pem in the Python version's etc/openssl folder, and the installer doesn't create it. Without it, Python can't link any server's certificate to an authority it trusts, the "local issuer" in the message, so every HTTPS request from the ssl module fails. The installer leaves that step to the Install Certificates script.

The Fix​

Run the Install Certificates script that came with this Python version: double-click Install Certificates.command in the /Applications/Python 3.15 folder, or run it from Terminal:

Terminal
"/Applications/Python 3.15/Install Certificates.command"
Output
-- pip install --upgrade certifi
Collecting certifi
Downloading certifi-2026.10.23-py3-none-any.whl.metadata (2.5 kB)
Downloading certifi-2026.10.23-py3-none-any.whl (135 kB)
Installing collected packages: certifi
Successfully installed certifi-2026.10.23
-- removing any existing file or link
-- creating symlink to certifi certificate bundle
-- setting permissions
-- update complete

The script does two things, both visible in its output:

  • It installs certifi with pip, a package that carries a curated set of root certificates. pip could download it before the fix because, as the ReadMe says, "The bundled pip has its own default certificate store for verifying download connections."
  • It links cert.pem to certifi's certificate file, the file Python's OpenSSL was looking for:
Output (ls -la …/Versions/3.15/etc/openssl/)
total 0
drwxrwxr-x@ 3 root admin 96 Nov 3 14:41 .
drwxrwxr-x@ 3 root admin 96 Oct 26 02:53 ..
lrwxr-xr-x 1 you admin 53 Nov 3 14:41 cert.pem -> ../../lib/python3.15/site-packages/certifi/cacert.pem

Each python.org Python version has its own etc/openssl folder and its own Install Certificates script. On this Mac, the older versions differed: two of them had a cert.pem, two didn't. Run the script for every version you use.

After the Fix​

The same script, run again:

Output (python3 check_url.py)
200 https://www.python.org/

A terminal where Install Certificates.command installs certifi 2026.10.23, creates the symlink and prints update complete, and python3 check_url.py then prints 200 https://www.python.org/.

200: Python verified python.org's certificate and opened the page.

Common Mistakes​

MistakeWhat happensDo this instead
Turning off certificate checks in the codeAny server can pretend to be the one you asked forInstall the certificates
Running Install Certificates for one Python version onlyThe other python.org versions keep failingRun each version's own script
Testing the address with curl and concluding it can't be a certificate problemcurl uses different certificates than python.org's PythonCheck ssl.get_default_verify_paths()

Troubleshooting​

SymptomLikely causeFix
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate with python.org's Python on macOSIts OpenSSL has no certificate file yetRun Install Certificates for that version
curl opens the address, Python doesn'tPython uses its own OpenSSL and its own certificate fileThe same fix
The etc/openssl folder of your version has no cert.pemInstall Certificates hasn't run for that versionRun it
It worked until you installed a newer Pythonpython3 now runs the new version, which has its own empty certificate folderRun the new version's Install Certificates

FAQ​

Do I need to run it again later?​

Run it again to update the certificates: the script runs pip install --upgrade certifi, and a newer certifi brings the current set of root certificates.

Why did pip work before the fix?​

The ReadMe explains it: "The bundled pip has its own default certificate store for verifying download connections." That's how the script could download certifi in the first place.

Conclusion​

"[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate" in Python on macOS, when curl reaches the same address, means python.org's Python has no certificates to trust yet: its private OpenSSL looks for cert.pem in the version's etc/openssl folder, and nothing put one there. Run Install Certificates.command from /Applications/Python 3.x, once per version, and HTTPS works.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.