Verify vs Cert: The Python Requests Handbook
Understanding SSL/TLS in Python Requests: The 'verify' and 'cert' arguments explained with interactive animations.
You’ve seen the error. You’ve felt the panic.
SSLError(CertificateError("hostname 'bankofamerica.com' doesn't match..."))
And you’ve probably done the “lazy fix”: adding verify=False just to make the red text go away.
Stop.
Before you disable security on your production app, let’s actually understand what verify and cert do. And because SSL handshakes are boring, we’re going to visualize them as a high-stakes money transfer.
The Analogy: The Armored Courier
Imagine requests is an Armored Courier (Client).
The server (e.g., google.com) is the Bank (Server).
The payload is a Bag of Cash (Data).
There are two critical questions that must be answered before any money changes hands:
- “Is this the Real Bank?” (Handled by
verify) - “Is this a Real Courier?” (Handled by
cert)
1. verify: Checking the Bank
Who checks who? The Courier checks the Bank.
Default in Requests: True (Secure).
When you send a request, your code wants to know if it’s talking to the real server or an imposter.
The Mechanism
- Bank presents its ID Card (SSL Certificate).
- Courier checks its Book of Trusted IDs (CA Bundle).
- If the Bank’s ID is signed by someone in the Book? Trust.
Interactive Simulation: The Trust Check
Scenario A: verify=True (The Good)
By default, requests acts like a strict bouncer. It grabs the digital ID bundle from certifi (a Python package containing trusted CAs like DigiCert, Let’s Encrypt).
import requests
# This is the default. You don't even need to type verify=True.
requests.get('https://github.com', verify=True)
Scenario B: verify=False (The Ugly)
You turn off the ID check. The courier walks up to anyone wearing a “Bank” t-shirt and hands them the money.
This is fine for localhost testing.
This is suicide on public WiFi or the open internet.
# Disables the safety check.
# Creates a massive security hole ("Man in the Middle" attack).
requests.get('https://internal-tool.local', verify=False)
Pro Tip: If you have a custom internal CA (common in corporate VPNs), don’t set False! Instead, point to your company’s certificate file:
requests.get(url, verify='/path/to/company-ca.pem')
2. cert: The Badge Check
Who checks who? The Bank checks the Courier.
Also known as: mTLS (Mutual TLS) or Two-Way SSL.
Sometimes, the Bank is exclusive. It doesn’t talk to just anyone. It demands proof that you are an authorized courier.
The Mechanism
- Courier initiates connection.
- Bank says “Show me your badge.”
- Courier sends its Client Certificate (
.crt) and Private Key (.key). - Bank validates the badge. If valid? Access Granted.
Interactive Simulation: The Double Check
How to use it
You need two files from your security team: a Certificate (public ID) and a Key (secret password).
# Tuple format: (cert_path, key_path)
client_cert = ('/path/to/client.crt', '/path/to/client.key')
requests.get(
'https://secure-bank.com/api/vault',
cert=client_cert
)
Sometimes these are combined into a single .pem file. In that case, just pass the string path:
cert='/path/to/combined.pem'.
TL;DR Summary
| Parameter | Analogy | Who is being checked? | Why use it? |
|---|---|---|---|
verify | The ID Check | The Server | To ensure you aren’t sending data to a hacker. |
cert | The Badge | The Client (You) | To prove you have permission to access the server. |
Next time requests throws an SSL error, don’t just blindly set verify=False. Ask yourself: Do I trust this bank?
Related posts
-
API Certificates: The Mastery Guide to Debugging & The Chain of Trust
Stop guessing with SSLErrors. A mastery-level guide to the Chain of Trust, openssl debugging, and proving exactly whose fault it is.
-
Authentication vs. Authorization vs. OAuth: The 'ID Card' Mental Model
Stop mixing up 401 and 403. A mastery guide to AuthN (Who you are), AuthZ (What you can do), and the OAuth Valet Key.
-
SP7 - Proxy - Learn Design Pattern From Simple Things
The boss wants the employees to focus on work and not get distracted by social media. So he decides to block some websites on the corporate network during working hours.
-
SP6 - Object Pool - Learn Design Pattern From Simple Things
Producing planes on a large scale is expensive, but fortunately the manufactured raw parts are always stored in the pool, thereby reducing duplication in the production process.