Configuring and Using System CA Certificates in Python Requests

Nov 23, 2025 · Programming · 10 views · 7.8

Keywords: Python | Requests | SSL Certificates | Debian | System CA Certificates

Abstract: This article explores why Python Requests module does not trust system CA certificates by default in Debian/Ubuntu systems and provides multiple solutions. By setting environment variables, configuring the certifi package, and manually specifying certificate paths, it ensures Requests can correctly validate self-signed certificates. The analysis covers SSL certificate verification mechanisms to help developers deeply understand and resolve common certificate validation failures.

In Debian or Ubuntu systems, users often encounter issues where the Python Requests module fails to validate self-signed certificates, even when these certificates are correctly installed and trusted by the system. This article delves into the reasons behind this behavior and offers several effective solutions.

Problem Background and Cause Analysis

When users install self-signed root CA certificates in the system and update the certificate store via sudo dpkg-reconfigure ca-certificates, system tools like gnutls-cli and openssl s_client can validate the certificates successfully. However, Python 2 and Python 3 Requests modules throw an SSLError: certificate verify failed error. This occurs because the Requests module uses its embedded certificate bundle by default, rather than the system's CA certificate store. Requests is designed for cross-platform consistency, so it includes its own certificate bundle, typically located at /usr/local/lib/python2.7/site-packages/requests/cacert.pem or /usr/lib/python3/dist-packages/requests/cacert.pem. This mechanism avoids issues due to variations in system certificate stores but requires manual configuration to trust system certificates when using self-signed ones.

Solution 1: Setting Environment Variables

The most straightforward approach is to set the REQUESTS_CA_BUNDLE environment variable to point to the system's CA certificate file. In Debian/Ubuntu systems, this file is usually at /etc/ssl/certs/ca-certificates.crt. Use the following command to set the environment variable:

export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt

After setting this, Requests will use the system certificate store for SSL verification, resolving the certificate validation failure. This method is simple and effective for temporary testing or development environments.

Solution 2: Using the certifi Package

For newer versions of Python and Requests, it is recommended to use the certifi package for certificate management. certifi provides a cross-platform CA certificate bundle and allows users to customize certificate paths. First, install certifi:

pip install certifi

Then, specify the certificate path in your code:

import requests
import certifi

response = requests.get('https://mysite.local', verify=certifi.where())

Here, certifi.where() returns the default certificate path, which in Debian/Ubuntu systems typically points to /etc/ssl/certs/ca-certificates.crt. This approach is more flexible and facilitates dynamic certificate management in code.

Solution 3: Manually Specifying Certificate Path

If you prefer not to rely on environment variables or external packages, you can directly specify the certificate path in Requests calls:

import requests

response = requests.get('https://mysite.local', verify='/etc/ssl/certs/ca-certificates.crt')

This method is suitable for scenarios requiring precise control over certificate verification but may increase code maintenance overhead.

Verifying Certificate Loading Path

To confirm the certificate path used by Requests, you can use the following code for verification:

import certifi
print(certifi.where())

The output will show the current certificate file path, aiding in debugging certificate issues.

In-Depth Understanding of SSL Certificate Verification Mechanism

The SSL/TLS protocol requires clients to validate the legitimacy of server certificates during secure connection establishment. The verification process includes checking the certificate's signature chain, validity period, and subject name, among other factors. The Requests module relies on underlying SSL libraries like OpenSSL, and its verification behavior is influenced by the certificate bundle. System tools such as openssl s_client default to the system certificate store, whereas Requests uses its embedded bundle for consistency. Understanding this mechanism helps in configuring certificates in more complex network environments.

Summary and Best Practices

This article presented three methods to address the Python Requests module's lack of trust in system CA certificates: setting environment variables, using the certifi package, and manually specifying certificate paths. It is recommended to use the certifi package in production environments for better maintainability and cross-platform support. For development environments, temporarily setting environment variables is a quick and effective solution. Regardless of the method, ensure the certificate path is correct and regularly update certificates to maintain security.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.