<!-- https://pkizerotohero.com/errors/python-certificate-verify-failed/ | Markdown mirror of the HTML page | PKI Zero to Hero, by Duyutech BV -->

> Fix Python's CERTIFICATE_VERIFY_FAILED: unable to get local issuer certificate in urllib, requests and pip, without verify=False.

Source: https://pkizerotohero.com/errors/python-certificate-verify-failed/ · Last reviewed: 2026-10-20

- Python
- Exact text checked with the real tool

# \[SSL: CERTIFICATE\_VERIFY\_FAILED\] certificate verify failed: unable to get local issuer certificate

Also seen in: requests, urllib, pip, aiohttp, boto3

**In one sentence:**

Python could not link the server's certificate to a trusted root: the server omits its intermediate, or the company or proxy root is missing from the store Python uses.

[Check yours: Chain checker](https://pkizerotohero.com/tools/chain/)

## Where you see it

In any Python code that opens an HTTPS connection: `urllib`, `requests`, `pip`, SDKs built on them. The exception is `ssl.SSLCertVerificationError` (see the [ssl module documentation](https://docs.python.org/3/library/ssl.html#ssl.SSLCertVerificationError)); the number after `_ssl.c:` changes between Python versions.

```text
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1028)>
```

With `requests`:

```text
requests.exceptions.SSLError: HTTPSConnectionPool(host='api.example.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1028)')))
```

The same family includes `certificate verify failed: self-signed certificate in certificate chain` (a complete chain ending in an untrusted root). Recent pip on Windows may show the operating system’s wording instead: `A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.`

## What it means

Python checks the server’s [certificate chain](https://pkizerotohero.com/handbook/glossary/#certificate-chain) with OpenSSL. It needs the issuer of every certificate, from what the server sent or from its [trust store](https://pkizerotohero.com/handbook/glossary/#trust-store). It reached a certificate whose issuer it could not find, so it could not connect the server to a trusted root. Which store Python uses depends on the library, and that is why one script works and the next fails.

## Likely causes

### The server does not send its intermediate certificate

Browsers can fetch a missing [intermediate certificate](https://pkizerotohero.com/handbook/glossary/#intermediate-certificate) or may already have it; Python does not. Count what the server sends:

```bash
openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null | grep -c 'BEGIN CERTIFICATE'
```

`1` means only the server’s own certificate. **Fix it on the server:** serve the certificate followed by the intermediate (`fullchain.pem` for nginx and certbot, `SSLCertificateFile` with the chain for Apache, the intermediate store on IIS). See [verify error:num=21](https://pkizerotohero.com/errors/openssl-verify-error-21/).

### Your library uses a different store than you think

- **`ssl` and `urllib`** use `ssl.create_default_context()`. On Windows it loads the Windows certificate store; on Linux it uses OpenSSL’s default bundle, which you can override with the `SSL_CERT_FILE` environment variable.
- **`requests`** uses the `certifi` bundle, not the operating system’s store, and ignores `SSL_CERT_FILE`. Set `REQUESTS_CA_BUNDLE`, or pass `verify='/path/to/ca.pem'` ([requests documentation](https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification)).
- **pip 24.2 and later** uses the system certificates in addition to certifi; `--cert` or `PIP_CERT` point it at a bundle ([pip documentation](https://pip.pypa.io/en/stable/topics/https-certificates/)).
- **Python from the python.org installer on macOS** needs one extra step: double-click “Install Certificates.command” in its folder in Applications, which installs root certificates for that Python ([Using Python on macOS](https://docs.python.org/3/using/mac.html)).

Find out where `ssl` looks:

```bash
python -c "import ssl; print(ssl.get_default_verify_paths())"
```

### The root is a private CA or a TLS-inspection proxy

On a company network, internal servers use a company CA, and a [TLS-inspection](https://pkizerotohero.com/handbook/glossary/#tls-inspection) proxy may re-sign public sites. Check the issuer of a public site:

```bash
openssl s_client -connect pypi.org:443 -servername pypi.org </dev/null 2>/dev/null | openssl x509 -noout -issuer
```

If it names your company or a security product, get that root from IT (PEM format) and give it to Python. Because the custom bundle replaces the default for `requests`, include the public roots too:

```bash
cat "$(python -m certifi)" corp-root.pem > ca-bundle.pem
export REQUESTS_CA_BUNDLE="$PWD/ca-bundle.pem"   # requests
export SSL_CERT_FILE="$PWD/ca-bundle.pem"        # ssl and urllib
pip config set global.cert "$PWD/ca-bundle.pem"  # pip
```

Better still, add the root to the operating system’s store (`update-ca-certificates` on Debian and Ubuntu, `update-ca-trust extract` on RHEL) and point the variables at the system bundle, for example `/etc/ssl/certs/ca-certificates.crt` on Debian and Ubuntu. Do not edit the `cacert.pem` inside the certifi package: the next upgrade overwrites it.

### Python 3.13 is stricter

Python 3.13 turned on stricter X.509 checks in `create_default_context()`. Certificates from older private CAs can fail with messages such as `certificate verify failed: Basic Constraints of CA cert not marked critical`. The right fix is to reissue the CA or server certificates so they follow RFC 5280; see the [What’s New in Python 3.13](https://docs.python.org/3/whatsnew/3.13.html) notes.

Warning

Why verify=False is a trap

`verify=False` in requests, `ssl._create_unverified_context()` and pip’s `--trusted-host` all accept a certificate from anyone, so your credentials can go to whoever intercepts the connection. They also hide the real problem, which then appears somewhere else. Give Python the right root, or fix the server’s chain.

## Check yours

*Interactive tool: Chain checker (runs in the browser at [/tools/chain/](https://pkizerotohero.com/tools/chain/))*

Paste the certificates from `openssl s_client -showcerts`. The checker shows whether the intermediate is missing or the chain ends at a root you need to trust.

## Learn why

- [Certificate chains and path validation](https://pkizerotohero.com/handbook/certificate-chains/)
- [Who do we trust? CAs, trust stores and self-signed certificates](https://pkizerotohero.com/handbook/trust-stores/): why each language has its own store.
- Related: [Hostname mismatch in Python](https://pkizerotohero.com/errors/python-hostname-mismatch/) and [verify error:num=20](https://pkizerotohero.com/errors/openssl-verify-error-20/).

**Early edition.** Checked against the standards; an independent expert review is in progress. Found a mistake? [Tell us](https://pkizerotohero.com/contact/?topic=content-error&page=/errors/python-certificate-verify-failed/).

Last reviewed 20 October 2026Edition 0.9

## Learn why it happens

- [Chapter 13: Certificate chains and path validation](https://pkizerotohero.com/handbook/certificate-chains/)
- [Chapter 12: Who do we trust? CAs, trust stores and self-signed certificates](https://pkizerotohero.com/handbook/trust-stores/)

## Fix it step by step

- [How to build the full chain file your server needs](https://pkizerotohero.com/guides/build-fullchain/)
- [How to work behind a TLS-inspecting corporate proxy, safely](https://pkizerotohero.com/guides/corporate-proxy-certificates/)
- [How to trust a private root CA on macOS](https://pkizerotohero.com/guides/add-root-ca-macos/)
- [How to make Python, Node.js and npm trust a private CA](https://pkizerotohero.com/guides/trust-ca-python-node/)

## Everything on this topic

- [Chains and trust stores](https://pkizerotohero.com/topics/chains-and-trust/)
