Skip to content
ecdsa.com
Python urllib.requestPython cryptography

Error message

<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate

Also printed as

  • urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate

The text inside the brackets is the underlying ssl error and varies ("self-signed certificate in certificate chain", "certificate has expired", …). Python closes it with a source location and ">", e.g. "(_ssl.c:1082)>".

Python urllib.request — urllib.error.URLError wrapping ssl.SSLCertVerificationError

What it means

urllib.request.urlopen() wraps any connection problem in URLError, so the TLS failure appears inside "<urlopen error …>". When this happens for every public site, including www.python.org, the Python process has no usable CA certificates at all: the classic case is the python.org installer on macOS, whose bundled OpenSSL does not read the Keychain until "Install Certificates.command" has been run.

Why it happens

How to fix it

  1. 1.

    macOS: run Install Certificates.command

    Run it from Finder or the terminal for each python.org Python version, then confirm the default CA file path exists.

    bash
    # macOS, python.org installer (one script per installed version)
    "/Applications/Python 3.14/Install Certificates.command"
    python3 -c "import ssl; print(ssl.get_default_verify_paths().openssl_cafile)"
  2. 2.

    Pass a context built from certifi

    For scripts that must work everywhere, build the SSL context from certifi.where() explicitly; keep certifi updated so its roots stay current.

    python
    # Explicit, portable: use certifi's Mozilla bundle for this request
    # pip install certifi
    import certifi, ssl, urllib.request
    
    ctx = ssl.create_default_context(cafile=certifi.where())
    urllib.request.urlopen("https://www.python.org/", context=ctx)
  3. 3.

    Or use the operating system's trust store

    truststore.inject_into_ssl() makes urllib, http.client and libraries built on ssl verify through the OS, including company roots deployed by IT.

    python
    # Or verify with the operating system's store (macOS Keychain, Windows, Linux bundle)
    # pip install truststore==0.10.5
    import truststore
    truststore.inject_into_ssl()
  4. 4.

    Check for environment overrides

    Unset SSL_CERT_FILE and SSL_CERT_DIR if they point to files that do not contain the needed roots.

    bash
    env | grep -E '^SSL_CERT_(FILE|DIR)='
    python3 -c "import ssl; print(ssl.get_default_verify_paths())"

Related errors

Browse the full signature error database