Requests is the undisputed king of Python libraries for HTTP requests. Its simple API has made it a staple of Python web scraping and API testing.
But the crown is not without its thorns. One common "gotcha" is Requests' built-in verification of SSL certificates.
Trying to make a request to a site with an invalid SSL cert will throw this familiar error:
SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
Suddenly your scripts grind to a halt. ๐ซ
Now you could just ignore those useless certs and disabling SSL verification altogether. But don't do that just yet!
That may fix your immediate issue, but it opens up risks down the road. Instead, let's dig into Requests properly and see how to disable verification selectively and securely.
After all, you are a Python professional - no shoddy coding!
In this comprehensive guide, you'll learn:
So grab your hard hat and let's dig in!
Why Verify Certificates? A Quick SSL Primer
First, why does Requests even bother verifying SSL certificates?
To understand that, we need a quick SSL primer. Feel free to skip ahead if you're already familiar.
SSL (Secure Sockets Layer) is a security protocol for establishing encrypted links between web servers and clients. That familiar padlock in your browser indicates an SSL connection.
Part of SSL involves certificates that verify site identities and encrypt traffic. Certs are issued by certificate authorities (CAs) like Digicert or LetsEncrypt.
They provide validation that you are talking to who you think. This prevents man-in-the-middle attacks.
Now Requests verifies these certificates by default to protect you. But in some cases, you'll want to disable this. Let's look at the main techniques...
Method 1: Per-Request Verification Disabling
The most straightforward way to disable SSL certificate verification is per request via the
import requests
response = requests.get('<https://invalid-ssl.com>', verify=False)
This disables verification only for this request, keeping all others verified.
Pros:
Cons:
So this method works in a pinch, but we can do better...
Method 2: Global Verification Disabling
For more permanent disabling, we can set
import requests
session = requests.Session()
session.verify = False
response = session.get('<https://invalid-ssl.com>')
Now all requests from this session will skip verification.
Pros:
Cons:
This is handy for APIs and sites you permanently don't want to validate. But it's a bit sledgehammer-y.
Method 3: Disabling Those Pesky Warnings
One downside to disabling verification is the screen full of warnings Requests will spew at you:
InsecureRequestWarning: Unverified HTTPS request is being made...
We can suppress them with:
from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
But note warnings exist for a reason - to alert you to potential security issues. I'd recommend only disabling them once you're done testing.
Method 4: Using a Custom Certificate
Another option is to provide your own custom PEM certificate:
custom_cert = '/path/to/mycert.pem'
response = requests.get('<https://self-signed.com>', verify=custom_cert)
This can be useful for internal servers using self-signed certs.
Pros: More secure than disabling verify altogether.
Cons: Need to have cert access and management.
Method 5: Set Environment Variable
Finally, we can specify a custom cert via the
import os
os.environ['REQUESTS_CA_BUNDLE'] = '/path/to/cacert.pem'
response = requests.get('<https://example.com>')
This keeps the custom cert out of your code.
Pros: Avoid hardcoded custom cert paths.
Cons: More convoluted setup.
So in summary, we have many options - per request, global, warnings, custom certs, and environment. Choose wisely based on your use case!
Should You Disable Verification? Dangers & Best Practices
Before you go disabling that vital SSL verification, let's recap the security implications.
Disabling SSL cert verification weakens security by removing a key validation step. Doing so on production systems can be dangerous and open you to MITM attacks.
So in general, only disable verification in development/testing on trusted networks. Make sure you re-enable it before going live. The goal should be to fix the root certificate issue rather than simply bypassing it indefinitely.
Other best practices include:
Following these tips will keep you secure even as you temporarily work around SSL issues.
Other Concerns When Disabling Verification
Let's round out this guide by looking at a few other things to keep in mind:
The main takeaway is test in your specific environment. What works for one setup may fail in another. Always validate you are getting the expected behavior.
Conclusion and Key Takeaways
And there you have it - my insider's guide to proficiently disabling SSL certificate verification in Python's Requests library!
We looked at:
The key takeaways are:
Employing these lessons will make you a verification expert in no time!
Now go forth and request securely. ๐ And let me know if you have any other tips!
Frequently Asked Questions
Here are answers to some common questions about disabling SSL certificate verification in Python Requests:
How can I disable verification for just one request?
Pass
What's the quickest way to disable verification globally?
Set
Why am I still seeing SSL warnings after disabling verification?
You need to explicitly disable
What if I want to use my own certificate?
You can pass the PEM cert path to
How do I avoid hardcoded certificate paths in my code?
Set the
Is disabling verification risky?
Yes, it removes a security validation step so only do it temporarily in development.
What if I'm making requests between my own machines?
Self-signed certs on internal servers can cause issues. Use a custom cert.
How can I validate that my cert is properly disabled?
Always test your requests to confirm no errors occur from verification failures.
Hopefully these answers provide a quick reference on key points around disabling SSL certificate verification in Python Requests.