This guide covers Python HTTPS errors on Ubuntu or Debian VPS hosting, virtual environments and Docker services. It includes a small diagnostic script and a rebuild example. Keep certificate verification enabled as you diagnose and retest the connection.
Read the full SSL error before changing anything
The phrase CERTIFICATE_VERIFY_FAILED identifies a verification failure. The text after it usually gives a more specific reason. Save that message together with the Python version and where the process runs.
| Message | Check first | Likely repair location |
|---|---|---|
| Unable to get local issuer certificate | CA bundle and the server's intermediate chain | Client trust store or HTTPS endpoint |
| Certificate has expired | Certificate dates and the machine clock | Certificate deployment or time synchronisation |
| Hostname mismatch | Requested DNS name and certificate names | URL, DNS or TLS virtual host |
| Self-signed certificate in certificate chain | Private CA or HTTPS-inspection proxy | Approved CA configuration |
| Certificate revoked or deliberately distrusted | Issuer advisory and the deployed chain | Replace the affected certificate chain |
Python exposes a verification code and message through SSLCertVerificationError. Those fields make a useful starting point for the investigation. Check the Python exception documentation.
1. Locate the Python process that fails
Use the same executable, virtual environment and service account as the application. A command from your SSH shell can select a different Python installation from a scheduled job or bot process.
python -c "import sys; print(sys.executable); print(sys.version)"
python -m pip --version
python -m pip show requests certifi
For a virtual environment, call its interpreter directly. For example, use .venv/bin/python in place of python. Package information from another environment will give you an incomplete picture of the running service.
For Docker, inspect the application service from its Compose directory. Replace app with your actual service name.
sudo docker compose ps
sudo docker compose exec app python -c \
"import sys, ssl; print(sys.executable); print(sys.version); print(ssl.OPENSSL_VERSION)"
sudo docker compose exec app python -m pip show requests certifi
Review whether the process has certificate or proxy overrides configured. Check their names and intended paths, and keep credentials out of shared logs or support tickets. Common variables include SSL_CERT_FILE, SSL_CERT_DIR, REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE and PIP_CERT.
2. Reproduce the Python HTTPS failure
Save this as tls_check.py in your diagnostic working directory. It uses Python's standard HTTPS client and prints the interpreter, default CA paths and verification error.
import ssl
import sys
import urllib.error
import urllib.parse
import urllib.request
url = sys.argv[1] if len(sys.argv) > 1 else "https://www.python.org/"
if urllib.parse.urlsplit(url).scheme != "https":
raise SystemExit("Supply an https:// URL")
print("Python", sys.version.split()[0])
print("Executable", sys.executable)
print("OpenSSL", ssl.OPENSSL_VERSION)
print("Default CA paths", ssl.get_default_verify_paths())
try:
with urllib.request.urlopen(url, timeout=15) as response:
print("HTTPS status", response.status)
except urllib.error.HTTPError as error:
print("HTTPS reached HTTP status", error.code)
except urllib.error.URLError as error:
reason = error.reason
if isinstance(reason, ssl.SSLCertVerificationError):
print("Verification code", reason.verify_code)
print("Verification message", reason.verify_message)
else:
print("Connection error", type(reason).__name__)
raise SystemExit(1)
Run it with the failing HTTPS endpoint, using a URL that contains no secret token. The default target is the public Python website.
python tls_check.py
python tls_check.py https://api.example.com/
A normal HTTP response, including an application-level 401 or 403, means that request got as far as an HTTP-speaking endpoint. A certificate exception gives you the TLS verification message to investigate. A DNS failure or timeout needs connectivity checks before certificate diagnosis can continue.
The script follows Python's normal URL-handling behaviour, including detected proxy settings. Inspect the application's own client as well if it uses Requests, HTTPX or a custom SSL context. Review urllib HTTPS behaviour.
3. Check the hostname, certificate chain and clock
On an Ubuntu or Debian VPS, inspect time and the endpoint's TLS response. Replace api.example.com with the exact DNS name used by your application.
date -u
timedatectl status
openssl s_client \
-connect api.example.com:443 \
-servername api.example.com \
-verify_hostname api.example.com \
-verify_return_error \
-CAfile /etc/ssl/certs/ca-certificates.crt \
< /dev/null
-servername supplies the TLS server name, while -verify_hostname checks the certificate against it. -verify_return_error makes a failed verification terminate the check. Read the OpenSSL command documentation.
Expired certificate
Renew and deploy the certificate on every relevant TLS terminator, then reload the service that presents it.
Wrong hostname
Check the application's URL, DNS destination and selected virtual host. The certificate must cover the requested name.
Incomplete chain
Configure the HTTPS server to send the required intermediate certificates alongside its leaf certificate.
If you control the endpoint, repair its certificate deployment and retest from another network. If it belongs to an API provider, send that provider the hostname, failure message and time of the check. A browser can behave differently because its trust store or cached intermediate certificates differ from the application environment.
4. Identify the certificate bundle the client uses
Python's standard SSL configuration can report its OpenSSL CA-file and CA-directory defaults.
python -c "import ssl; print(ssl.get_default_verify_paths())"
Use that output to check whether the expected file exists and whether an override points to an old or missing bundle. The result describes the default SSL paths for that interpreter. Read the default-path documentation.
Requests commonly uses the separately installed certifi bundle. Check its location inside the application's environment.
python -c "import certifi; print(certifi.where())"
Requests supports a custom bundle through its verify setting or REQUESTS_CA_BUNDLE, with CURL_CA_BUNDLE as a fallback. If the application constructs prepared requests manually, check that its send workflow merges environment settings when relying on those overrides. Review Requests certificate handling.
Modern pip uses system certificates alongside its own bundled certifi certificates. Its bundled copy is updated through pip itself. Inspect pip in the affected environment and account for any distribution-specific packaging changes. Review pip's HTTPS trust configuration.
5. Refresh Ubuntu or Debian system certificates
For a VPS using the distribution's system trust store, refresh the package metadata and install the current CA package.
sudo apt-get update
sudo apt-get install ca-certificates
sudo update-ca-certificates
Check the resulting bundle at /etc/ssl/certs/ca-certificates.crt and rerun the diagnostic with the application's interpreter. The trust-store documentation explains the distribution's certificate locations and update command. Review Ubuntu's trust-store layout.
Record the change and restart affected long-running services where their SSL contexts retain previously loaded certificates. Applications using a separate bundle need attention to that bundle too.
Recent Python and packaging trust updates
The Python security announcement for the October 2026 eMudhra/emSign incident lists updates for Python, certificate bundles and packaging tools. Its current guidance includes pip 26.2.2, certifi 2026.10.19 and uv 0.13.6 as minimum recommended versions for those components.
It also identifies patched Python releases including 3.15.2, 3.14.10, 3.13.18, 3.12.16 and 3.11.18. Check the appropriate release line for your application and use the announcement's verified bootstrap procedure when updating affected packaging tools. Existing virtual environments require attention individually. These details were checked on 12 November 2026. Follow the maintained incident guidance.
After applying the relevant packaging-tool update, refresh certifi in an application environment that uses it. This example targets a virtual environment named .venv. Review the project's dependency constraints and update its dependency lock through the normal release workflow.
.venv/bin/python -m pip install --upgrade certifi
.venv/bin/python -m pip check
Retest dependencies and application startup when replacing a runtime. Keep an approved, current trust store in the environment used for installation as well as the one used to run the service. An endpoint using a deliberately distrusted chain needs a replacement certificate chain.
6. Rebuild the Docker image that contains the trust store
A container has its own filesystem and certificate packages. Update the relevant image's trust configuration and dependencies, then deploy a newly built container. Docker documents certificate installation within images and the additional requirements some runtimes have. Review Docker CA certificate handling.
The following small diagnostic image uses an official Python tag checked for this article. It installs the Debian CA package and copies the script from above. For a real application, keep a supported Python version compatible with its dependencies.
FROM python:3.15.2-slim-bookworm
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates \
&& update-ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /check
COPY --chmod=0444 tls_check.py .
USER 65534:65534
ENTRYPOINT ["python", "tls_check.py"]
Save that as Dockerfile beside tls_check.py, then build and run the check.
sudo docker build --pull --no-cache -t python-tls-check .
sudo docker run --rm python-tls-check https://www.python.org/
--pull refreshes the base-image lookup and --no-cache reruns the package-installation layer. An exact Python tag still receives image rebuilds, so record the tested image digest when you need reproducible deployment records. Review Docker rebuild guidance.
For an existing Compose application, build its reviewed changes and recreate that service.
sudo docker compose build --pull --no-cache app
sudo docker compose up -d --no-deps app
sudo docker compose logs --tail 100 app
This build workflow applies to a service with a build configuration. For an image-only service, obtain the maintained replacement image and recreate the service using your normal release procedure. Verify the actual Python client's connection after deployment. Our existing guide covers the update and recovery workflow. Update Compose services with a recovery plan.
7. Configure an approved private CA or inspection proxy
For an internal API or an organisation's HTTPS-inspection proxy, obtain the approved root CA certificate from the administrator responsible for that service. Verify its fingerprint through the organisation's trusted channel.
On Ubuntu or Debian, an approved PEM-encoded root certificate with a .crt extension can be installed into the local CA directory.
sudo install -m 0644 company-root.crt \
/usr/local/share/ca-certificates/company-root.crt
sudo update-ca-certificates
When a Requests application should use this combined system bundle, configure its environment accordingly. The file should contain the public roots and approved private root required by that application.
REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt \
.venv/bin/python bot.py
Apply the setting through the actual service configuration for a persistent deployment, then restart and test the application. Containerised clients need the approved CA and corresponding client configuration inside their own image or managed certificate mount.
Python bots and API clients on HYEHOST
A Discord or Telegram bot can fail when one of its HTTPS dependencies changes certificates or when a runtime retains an old trust bundle. Check the selected Python runtime, installed dependencies and the exact error from the affected API call.
On managed bot hosting, use the runtime and dependency information available through the panel and send support the verification message if the container's system certificates need investigation. VPS and VDS users can administer their own runtime, operating-system packages and images.
Verify the repair in the real service
- Run the request from the same interpreter or rebuilt container as the application.
- Confirm the expected hostname, certificate validity and trusted chain.
- Restart the service and test its normal API operation or bot command.
- Check scheduled jobs and background workers that use a separate environment.
- Record the runtime, package or certificate change and retain the relevant deployment configuration.
A successful diagnostic request is a useful checkpoint. Complete a normal application action as well, then review its logs for remaining certificate exceptions.
Python SSL error FAQ
What does Python CERTIFICATE_VERIFY_FAILED mean?
Python could not validate the certificate presented for an HTTPS connection. The detailed error can point to an untrusted issuer, an expired certificate, a hostname mismatch or another verification failure.
Why does curl work while Python Requests fails?
The clients may use different certificate stores, proxy settings or runtime environments. Run the checks from the same host or container and inspect the CA bundle selected by the failing Python client.
Will updating certifi fix every Python SSL error?
Updating certifi can refresh the CA bundle used by an application that relies on it. Expired server certificates, hostname mismatches, incomplete chains and other trust stores require their own corrections.
How do I fix certificate verification inside Docker?
Update the relevant image trust store, runtime or dependencies, rebuild the image and recreate the service. Test the rebuilt container against the failing endpoint with certificate verification enabled.
Does modern pip use the system certificate store?
Modern pip uses system certificates alongside its bundled certifi certificates by default. Its bundled copy is maintained through pip updates, and distribution-packaged versions can include downstream changes.
Can I run Python bots on HYEHOST in New Zealand?
Yes. HYEHOST bot hosting is available in Wolverhampton, Ashburn and Auckland, including the free bot hosting range. Cloud VPS and VDS are also available in these regions for applications needing server administration access.

