33

This code

import requests
requests.get("https://hcaidcs.phe.org.uk/WebPages/GeneralHomePage.aspx")

is giving me this error

[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)

I know practically nothing about SSL, but I've tried downloading the site's certificate and pointing to that file using the verify option, but it hasn't worked. Am I missing something?

5
  • Which version of Python and operating system are you using? Commented Oct 6, 2017 at 11:00
  • Yes sorry, Python 3.6.3 and Windows 7 Commented Oct 6, 2017 at 11:02
  • 3
    The site has a bad SSL Implementation: ssllabs.com/ssltest/analyze.html?d=hcaidcs.phe.org.uk Commented Oct 6, 2017 at 11:09
  • Does this answer your question? Python Requests throwing SSLError Commented Jan 12, 2023 at 22:14
  • check your system proxy settings, maybe you have set a unavailable proxy. Commented Dec 12, 2023 at 4:16

4 Answers 4

47

As already pointed out in a comment: the site has a bad SSL implementation as can be seen from the SSLLabs report. The main part of this report regarding your problem is:

This server's certificate chain is incomplete. Grade capped to B.

This means that the server is not sending the full certificate chain as is needed to verify the certificate. This means you need to add the missing certificates yourself when validating. For this you need to include the PEM for the missing chain certificate C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 High Assurance Server CA and also for the root CA C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA info a file my_trust_store.pem and then you can call:

requests.get("https://...", verify='my_trust_store.pem')

... but I've tried downloading the site's certificate and pointing to that file using the verify option

This will not work with normal leaf certificates. Since the SSL stack of Python is based on OpenSSL and OpenSSL expects only trusted certificate authorities in the trust store (i.e. given with verify) and a server certificate is not CA certificate it will not help to add it to the trust store.

Sign up to request clarification or add additional context in comments.

2 Comments

From the SSLLabs report, you can download the complete certificate chain with intermediates and root. Click "Click here to expand" under "Certification Paths", and then click the faint download icon next to the path whose chain you'd like to download. Save this as a .pem file, and its path can be used as the argument to verify=.
The last paragraph helped me solve the error finally. Thank you for mentioning it.
3
cat institution-certificate.pem >> venv/lib/python3.9/site-packages/certifi/cacert.pem

This should solve the problem if your network requires a CA

2 Comments

Since I had my institution's certificate handy, this was the easiest and most robust solution.
I smell a handy integration with something like pypi.org/project/get-certificate-chain
2

using the certifi doesn't seem to be implied, so i'll show you what made my solution:

import urllib, urllib2, ssl
import certifi

request = urllib2.Request(url=url)
kw = dict()
if url.startswith('https://'):
    certifi_context = ssl.create_default_context(cafile=certifi.where())
    kw.update(context=certifi_context)
urllib2.urlopen(request, **kw)

i found this solution and more on RealPython, here

Comments

-2

If you can avoid the certificate verification (not secure), set PYTHONHTTPSVERIFY environment variable to 0:

export PYTHONHTTPSVERIFY=0

This will skip the certificate verification.

2 Comments

Did not work for me. What library uses this variable? requests certainly does not.
@redbeam_ This turn certificate verification off which is turned on by default. You can refer access.redhat.com/articles/2039753

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.