Fading Coder

An Old Coder’s Final Dance

Home > Tech > Content

Troubleshooting requests.exceptions.SSLError from HTTPSConnectionPool after User-Agent–Triggered Redirects

Tech 1

Symptom

Calling requests.get against an HTTP URL appears to work once, but a subsequant call raises an SSL error similar to:

requests.exceptions.SSLError: HTTPSConnectionPool(host='www.baidu.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)')))

Reproducing the issue

Example target: http://www.baidu.com/

  1. No headers supplied (HTTP stays HTTP):
import requests

resp = requests.get('http://www.baidu.com/', timeout=5)
print(resp.status_code, resp.url)          # e.g., 200, 'http://www.baidu.com/'
  1. Spoofing a desktop browser User-Agent (server may switch to HTTPS):
import requests

ua = {
    'User-Agent': (
        'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1'
    )
}

# First request
r1 = requests.get('http://www.baidu.com/', headers=ua, timeout=5)
print('first:', r1.status_code, r1.url)

# A follow-up request may fail if HTTPS validation cannot be performed
try:
    r2 = requests.get('http://www.baidu.com/', headers=ua, timeout=5)
    print('second:', r2.status_code, r2.url)
except requests.exceptions.SSLError as exc:
    print('second raised:', type(exc).__name__, exc)

Why this happens

Some sites decide whether to redirect http → https based on the User-Agent. When redirected to https://www.baidu.com/, requests will validate the TLS certificate by default. If your Python/requests/SSL trust store is outdated or misconfigured, certificate verification fails and triggers SSLError via HTTPSConnectionPool.

Confirming the redirect behavior

Disable certificate checking temporarily to inspect redirect history. This is only for diagnosis.

import requests

ua = {
    'User-Agent': (
        'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1'
    )
}

# Case A: UA set — expect http -> https redirect
with requests.Session() as s:
    resp = s.get('http://www.baidu.com/', headers=ua, verify=False, timeout=5)
    print([h.status_code for h in resp.history])   # e.g., [302]
    print(resp.url)                                 # 'https://www.baidu.com/'

# Case B: No UA — often stays on http
resp2 = requests.get('http://www.baidu.com/', verify=False, timeout=5)
print([h.status_code for h in resp2.history])       # e.g., []
print(resp2.url)                                    # 'http://www.baidu.com/'

Note: You will see InsecureRequestWarning when verify=False; this is expected during diagnosis.

Practical fixes

Prefer fixing trust rather than disabling verification.

  • Use a current CA bundle (certifi) and point requests to it:
import requests, certifi

# Directly use HTTPS and a modern CA bundle
r = requests.get('https://www.baidu.com/', verify=certifi.where(), timeout=5)
print(r.status_code)
  • Update your toolchain:

    • Upgrade requests and urllib3
    • Ensure Python’s OpenSSL is up-to-date
    • On Windows, install/upgrade certifi; on macOS/Linux, ensure system CA store is current
  • Configure CA paths explicitly if needed:

    • Environment variables: REQUESTS_CA_BUNDLE or SSL_CERT_FILE
    • Or supply a PEM bundle path via verify='/path/to/ca-bundle.pem'
  • As a last resort for non-production scenarios, disable verification:

import requests

r = requests.get('https://www.baidu.com/', verify=False, timeout=5)
print(r.status_code)

To examine redirects without triggering verification errors, you can also avoid following redirects automatically and inspect the Location header:

import requests

ua = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1'
}

r = requests.get('http://www.baidu.com/', headers=ua, allow_redirects=False, timeout=5)
print(r.status_code)           # 301/302 when redirecting
print(r.headers.get('Location'))

Useful references

  • Browser User-Agent strings: https://www.useragentstring.com/
  • Requests SSL/TLS verification: https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification
Tags: Python

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.