Python applications often communicate with external services through HTTPS. They may call REST APIs, download packages, connect to cloud services, or exchange data with internal company systems. These connections rely on SSL/TLS certificates to verify the identity of the server and protect data during transmission.
Sometimes, a Python application fails to connect even when the server is available. Instead of receiving a response, the application reports an SSL certificate verification error.
This problem can occur because Python cannot find a trusted certificate authority, a server has an incomplete certificate chain, a certificate has expired, or a corporate proxy is intercepting HTTPS traffic.
The correct solution depends on the cause. Disabling certificate verification might make a connection work temporarily, but it also removes an important security check.
In this article, you will learn how to identify common Python certificate errors, diagnose the underlying problem, and configure certificate trust correctly.
What Causes Python Certificate Errors?
When a Python application connects to an HTTPS server, the TLS implementation checks the server's certificate against trusted certificate authorities. It also validates details such as the certificate's validity period and the server hostname.
If the certificate cannot be verified, Python may stop the connection before the application receives an HTTP response.
Several issues can cause this failure.
Cause | Typical symptom | Recommended solution |
|---|
Missing CA certificates | Certificate verification fails | Install or configure the appropriate trusted certificates |
Outdated CA bundle | Some HTTPS connections fail | Update the certificate bundle |
Corporate HTTPS inspection | Internal network requests fail | Configure the organization's approved root CA |
Expired server certificate | Certificate validity error | Ask the server administrator to renew the certificate |
Incomplete certificate chain | Issuer or chain verification error | Configure the server to provide the required intermediate certificates |
Hostname mismatch | Certificate does not match the requested host | Correct the hostname or server certificate |
Incorrect system time | Certificate appears expired or not yet valid | Correct the system clock |
Understanding the specific error message is the first step toward finding the right solution.
How to Identify the Certificate Error
Python libraries often include the underlying TLS error in their exception messages.
For example, an application using the requests library might produce an error similar to this:
requests.exceptions.SSLError:
certificate verify failed:
unable to get local issuer certificate
This message indicates that the certificate verification process could not establish trust in the certificate chain.
Another common error is:
certificate verify failed:
certificate has expired
This points toward a certificate validity problem rather than necessarily indicating a missing local certificate.
You can inspect the Python environment before changing any settings.
import ssl
import sys
print("Python version:", sys.version)
print("OpenSSL version:", ssl.OPENSSL_VERSION)
print("Default certificate paths:")
print(ssl.get_default_verify_paths())
This code displays the Python version, the OpenSSL version used by the SSL module, and the default certificate locations known to Python.
The output can help identify an outdated runtime or an unexpected certificate configuration.
Keep in mind that libraries such as requests may use a certificate bundle provided by certifi, so the default paths reported by ssl do not necessarily describe every HTTPS connection made by your application.
Fix Certificate Errors in Python Requests
The requests library is widely used to call REST APIs and other HTTPS endpoints.
Consider the following example:
import requests
response = requests.get(
"https://api.example.com",
timeout=10
)
response.raise_for_status()
print(response.status_code)
The timeout prevents the request from waiting indefinitely for a response. However, it does not solve certificate trust problems.
If the request fails with a certificate verification error, start by checking the certificate bundle used by the environment.
Update the Certificate Bundle
The certifi package provides a collection of trusted root certificates for Python applications and is commonly used by requests.
You can update it using pip:
python -m pip install --upgrade certifi
Using python -m pip helps ensure that pip runs under the Python interpreter you intend to update.
If your application uses a virtual environment, activate that environment before running the command.
You can then inspect the certificate bundle location:
import certifi
print(certifi.where())
If the problem was caused by an outdated CA bundle, updating it may resolve the issue.
However, updating certifi will not fix every certificate error. It cannot correct an expired server certificate, a hostname mismatch, or an internal certificate authority that your organization has not configured.
Specify a Trusted CA Bundle
If your organization uses an approved private certificate authority, you may need to provide its root CA certificate explicitly.
For example:
import requests
response = requests.get(
"https://internal-api.example.com",
verify="/etc/company-certs/company-root-ca.pem",
timeout=10
)
response.raise_for_status()
print(response.json())
Replace the example certificate path with the actual path to your organization's trusted CA bundle.
The verify parameter tells requests to validate the server's certificate using the specified CA file. The file must contain the appropriate trusted certificate or certificates for the server's certificate chain.
Do not download a random certificate from an untrusted source and add it to your trust configuration. Obtain certificates through an approved administrative or security process.
Configure Certificates for Python and pip
Certificate failures can also occur while installing dependencies.
For example, a pip command may fail when connecting to a package index because the environment cannot validate the server's certificate.
python -m pip install requests
If this fails, first identify whether the problem affects all HTTPS connections or only package installation.
Check the following:
Whether the Python environment uses an outdated certificate bundle.
Whether the package index uses a certificate issued by a private CA.
Whether a corporate proxy intercepts HTTPS traffic.
Whether pip is using the expected Python environment and configuration.
Where supported by your pip version, you can configure a certificate bundle through the PIP_CERT environment variable.
On Linux or macOS, for example:
export PIP_CERT=/etc/company-certs/company-ca-bundle.pem
python -m pip install requests
The certificate path is only an example. Use the CA bundle approved for your environment.
For a permanent configuration, follow your organization's package management policies instead of repeatedly passing command-line options.
Recent pip versions can also use system certificate stores in supported configurations. The available behavior depends on the pip version, Python version, and platform, so check your environment before changing the configuration.
Fix Certificate Errors Behind a Corporate Proxy
Some organizations inspect HTTPS traffic through a corporate proxy. The proxy establishes a connection to the external server and presents a certificate signed by the organization's internal certificate authority.
A browser may trust this certificate because the organization's root CA has already been installed in the operating system. A Python application may use a different certificate bundle and reject it.
In this situation, repeatedly upgrading certifi might not help because the organization's private CA is not necessarily included in its public certificate collection.
The appropriate solution is to obtain the approved corporate CA certificate and configure the Python application to trust it.
For a requests application, one option is to set an environment variable:
export REQUESTS_CA_BUNDLE=/etc/company-certs/company-ca-bundle.pem
On Windows PowerShell, the equivalent command is:
$env:REQUESTS_CA_BUNDLE = "C:\Company\Certificates\company-ca-bundle.pem"
These settings apply to the relevant process environment. They are not automatically permanent across every terminal session or deployment.
Also, REQUESTS_CA_BUNDLE is specific to requests and compatible integrations. Other libraries may use different certificate configuration mechanisms.
If the connection still fails, confirm that the CA bundle contains the correct certificate and that the proxy is presenting a valid certificate chain for the requested hostname.
Use Python's SSL Module to Test a Connection
You can investigate a TLS connection without involving a higher-level HTTP library.
The following example opens a connection to a server and validates its certificate using Python's default SSL configuration.
import socket
import ssl
hostname = "example.com"
port = 443
context = ssl.create_default_context()
with socket.create_connection(
(hostname, port),
timeout=10
) as connection:
with context.wrap_socket(
connection,
server_hostname=hostname
) as secure_connection:
print("TLS version:", secure_connection.version())
print("Certificate verified successfully.")
The ssl.create_default_context() function creates a context with appropriate client-side verification defaults.
The server_hostname parameter enables hostname verification and supports Server Name Indication, which helps servers select the correct certificate.
If the connection succeeds here but fails in requests, investigate the certificate bundle and configuration used by requests.
If both connections fail, examine the server certificate, network path, system trust configuration, and any proxy involved.
This test is useful for diagnosis, but it does not replace testing the complete application workflow.
Common Mistakes to Avoid
Disabling Certificate Verification
You may find examples that use the following configuration:
import requests
response = requests.get(
"https://api.example.com",
verify=False
)
This disables certificate verification for the request. The connection might succeed, but Python no longer verifies that the server's certificate chains to a trusted authority or matches the expected hostname.
An attacker positioned between the client and server could potentially impersonate the server.
Do not use this configuration in production. If it is used temporarily in a controlled diagnostic environment, remove it immediately and restore normal verification.
Installing Certificates Without Verifying Their Origin
A certificate should not become trusted simply because it makes an error disappear.
Only add CA certificates obtained through a trusted, verified process. Trusting an incorrect certificate authority can weaken the security of every connection that relies on it.
Updating the Wrong Python Environment
A machine may have multiple Python installations, virtual environments, and package directories.
Running pip against one interpreter does not necessarily update the packages used by another.
Check the interpreter path and use the corresponding python -m pip command.
Ignoring Server-Side Problems
Not every certificate failure originates on the client.
If a server provides an incomplete certificate chain or an expired certificate, the server administrator must correct the configuration. Changing the client's trust settings is not always an appropriate solution.
Best Practices for Production Applications
Keep certificate verification enabled for every production HTTPS connection.
Use a maintained Python runtime and update dependencies according to your team's security process. When an application requires a private CA, distribute the approved certificate through managed configuration rather than embedding it in source code.
Keep certificate files separate from application logic so that development, testing, and production environments can use their appropriate trust configuration.
Also, avoid logging credentials, authorization headers, private keys, or sensitive request data while debugging TLS failures. Certificate diagnostics should provide enough information to identify the problem without exposing secrets.
Finally, test certificate configuration in the same type of environment where the application runs. A developer's laptop may trust a certificate that is missing from a container, CI runner, or production server.
Summary
Python certificate errors usually indicate that the application cannot establish trust in an HTTPS server's certificate. The underlying cause may be an outdated CA bundle, an untrusted corporate certificate authority, an invalid server certificate, or an environment configuration problem.
Start by reading the complete error message and inspecting the Python SSL configuration. Update the relevant certificate bundle when necessary, configure approved private CAs for internal services, and investigate server-side problems when the certificate chain is invalid.
Most importantly, keep certificate verification enabled. Correcting the trust configuration protects the connection while allowing the application to communicate securely with external and internal services.
Join the conversation! Your thoughts help the community grow.