# InsecureRequestWarning "Unverified HTTPS request": what to do

> urllib3 prints InsecureRequestWarning when an HTTPS request skips certificate checks. Find the verify=False and fix the trust problem behind it.

Source: https://ssl.sh/errors/urllib3-insecure-request-warning/
Last updated: 2026-11-10

**`InsecureRequestWarning: Unverified HTTPS request is being made to host 'example.com'` means your program made an HTTPS request without checking the server's certificate.** The request succeeded, but some code, usually a `verify=False` added to get past a certificate error, switched off verification. Find that switch, fix the certificate problem it hid, and remove it.

## What the warning means

The warning means a request went out with certificate verification turned off. urllib3, the library under requests, pip, botocore and many SDKs, checks every HTTPS connection right before sending a request. If the connection was made with `cert_reqs='CERT_NONE'` (which is what `verify=False` in requests turns into) and no certificate fingerprint was pinned, it calls `warnings.warn()` with this text:

```text
InsecureRequestWarning: Unverified HTTPS request is being made to host 'example.com'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
```

Python prefixes it with the file and line that triggered it, for example `.../urllib3/connectionpool.py:<line>:`. That location is inside urllib3, not in your code, which is why the cause is often hard to find. The traffic is still encrypted, but without verification the encryption is with whoever answered. A proxy, a hijacked DNS record or a hostile Wi-Fi network can present any certificate and read the data.

## Causes, most common first

### 1. Your code passes verify=False

The usual story: a request failed with [CERTIFICATE_VERIFY_FAILED](https://ssl.sh/errors/python-certificate-verify-failed/), someone added `verify=False`, and the warning replaced the error.

- **Confirm:** search the code base.

```bash
grep -rnE "verify\s*=\s*False|CERT_NONE|_create_unverified_context" --include=*.py .
```

- **Fix:** remove it and fix the original error (sections below).

### 2. A session, client or SDK option disables verification

`session.verify = False`, a client option such as `ssl_verify=False`, or a command-line flag like the AWS CLI's `--no-verify-ssl` all end up as an unverified urllib3 connection. Configuration files and environment-specific settings (a `DEBUG` or `DEV` profile) are common places to hide it.

- **Confirm:** turn the warning into an exception to get a full traceback:

```bash
python -W error::urllib3.exceptions.InsecureRequestWarning app.py
```

- **Fix:** switch the option back on and provide a CA bundle through the library's own setting.

### 3. A third-party library disables verification on its own

Some older SDKs and scrapers hardcode `verify=False`. The traceback from step 2 ends inside that package.

- **Fix:** upgrade the package, or pass it a session or option with verification enabled. If it offers neither, report it to the maintainers; that is a vulnerability in the library.

### 4. Direct urllib3 use with CERT_NONE

Code that builds `urllib3.PoolManager(cert_reqs="CERT_NONE")` triggers the warning on every request. Remove the argument: urllib3 2.x verifies by default.

## Fix commands by platform

Each of these gives Python a way to trust the server, so `verify=False` becomes unnecessary. Check the server first with the [SSL checker](https://ssl.sh/tools/ssl-checker/); if its chain is incomplete, fix the server rather than the client.

**Debian / Ubuntu / containers:**

```bash
cp company-root.crt /usr/local/share/ca-certificates/company-root.crt
update-ca-certificates
export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
```

**RHEL family:**

```bash
cp company-root.crt /etc/pki/ca-trust/source/anchors/ && update-ca-trust
export REQUESTS_CA_BUNDLE=/etc/pki/tls/certs/ca-bundle.crt
```

**Windows and macOS:** use the operating system trust store, including roots deployed by IT, with truststore (Python 3.10+):

```python
import truststore
truststore.inject_into_ssl()
```

**One internal service only:**

```python
import requests
requests.get("https://intranet.example.com", verify="/etc/ssl/certs/company-root.pem")
```

**A lab device with a self-signed certificate you cannot change:** export the certificate with `openssl s_client -connect 203.0.113.10:443 -showcerts`, inspect it in the [certificate decoder](https://ssl.sh/tools/certificate-decoder/), and either pass it as `verify=` or pin its fingerprint with urllib3:

```python
import urllib3
http = urllib3.PoolManager(
    cert_reqs="CERT_NONE",
    assert_fingerprint="<sha256 fingerprint of the device certificate>",
)
http.request("GET", "https://203.0.113.10/")
```

With `assert_fingerprint` urllib3 marks the connection as verified, so no warning is printed, and a different certificate is rejected.

## Don't silence the warning

`urllib3.disable_warnings()`, `requests.packages.urllib3.disable_warnings()`, `warnings.filterwarnings("ignore")` and `PYTHONWARNINGS=ignore` remove the message but not the risk. The urllib3 documentation states that making unverified HTTPS requests is strongly discouraged. Without verification, credentials, session cookies and API responses can be read or altered by anyone positioned between you and the server, and silencing the warning makes the hole invisible in logs and code review.

The safer alternatives above cover every real case: a CA bundle for private and proxy roots, truststore for operating system roots, a complete chain on the server, and pinning for a single device you cannot fix. See [certificate chains explained](https://ssl.sh/learn/certificate-chains/) for why the chain matters.

## Verify the fix

```bash
python -W error::urllib3.exceptions.InsecureRequestWarning -c "import requests; print(requests.get('https://example.com', timeout=10).status_code)"
```

With warnings turned into errors, this command fails if any unverified request remains on that code path. Run your application's test suite the same way, ideally in CI, so a future `verify=False` breaks the build instead of shipping quietly. Finally, search the code once more for `verify=False` and `CERT_NONE` and confirm nothing is left.
