Python Requests throwing SSLError
Asked Answered
T

29

528

I'm working on a simple script that involves CAS, jspring security check, redirection, etc. I would like to use Kenneth Reitz's python requests because it's a great piece of work! However, CAS requires getting validated via SSL so I have to get past that step first. I don't know what Python requests is wanting? Where is this SSL certificate supposed to reside?

Traceback (most recent call last):
  File "./test.py", line 24, in <module>
  response = requests.get(url1, headers=headers)
  File "build/bdist.linux-x86_64/egg/requests/api.py", line 52, in get
  File "build/bdist.linux-x86_64/egg/requests/api.py", line 40, in request
  File "build/bdist.linux-x86_64/egg/requests/sessions.py", line 209, in request 
  File "build/bdist.linux-x86_64/egg/requests/models.py", line 624, in send
  File "build/bdist.linux-x86_64/egg/requests/models.py", line 300, in _build_response
  File "build/bdist.linux-x86_64/egg/requests/models.py", line 611, in send
requests.exceptions.SSLError: [Errno 1] _ssl.c:503: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
Teratogenic answered 19/5, 2012 at 18:45 Comment(4)
Can you share more of the code info? Seems like there is a missing step.Glazier
You should always mention versions of software you need help with.Geoffreygeoffry
I got this problem where i use python 3.5 tornado 4.4. HTTPRequest set the validate_cert=True, so you can set it False to deal itFreemasonry
Try this: requests.get('example.com', verify=certifi.where())Sororicide
K
699

The problem you are having is caused by an untrusted SSL certificate.

Like @dirk mentioned in a previous comment, the quickest fix is setting verify=False:

requests.get('https://example.com', verify=False)

Please note that this will cause the certificate not to be verified. This will expose your application to security risks, such as man-in-the-middle attacks.

Of course, apply judgment. As mentioned in the comments, this may be acceptable for quick/throwaway applications/scripts, but really should not go to production software.

If just skipping the certificate check is not acceptable in your particular context, consider the following options, your best option is to set the verify parameter to a string that is the path of the .pem file of the certificate (which you should obtain by some sort of secure means).

So, as of version 2.0, the verify parameter accepts the following values, with their respective semantics:

  • True: causes the certificate to validated against the library's own trusted certificate authorities (Note: you can see which Root Certificates Requests uses via the Certifi library, a trust database of RCs extracted from Requests: Certifi - Trust Database for Humans).
  • False: bypasses certificate validation completely.
  • Path to a CA_BUNDLE file for Requests to use to validate the certificates.

Source: Requests - SSL Cert Verification

Also take a look at the cert parameter on the same link.

Kabuki answered 12/10, 2012 at 18:19 Comment(15)
Yes, when i used dotCloud in ubuntu, the same "certificate verify failed" came out. After modified "requests.session(headers=headers, hooks=hooks, verify=False)" in "/usr/local/lib/python2.6/dist-packages/dotcloud/client/client.py", it worked.Bronchitis
This isn't marked as correct, but I can verify that it works (as opposed to the answers below).Chanachance
@khalid13: An axe "works" as a headache medicine (no head - no headache). It doesn't mean that it is a good idea to use it that way. verify=False disables host's SSL certificate checking.Blowhard
@J.F.Sebastian Honestly, it depends on what you're doing. For my quick/throwaway application, it was more than sufficient.Chanachance
@Bronchitis making such a change sounds very unsafe…Disconsider
@Bronchitis I agree completely with binki. What was the parameter before? True or a path?Kabuki
Oddly enough, I needed this on Python 2.7.6 but not 2.7.12.Shamrao
Where do you set the verify flag = false? All these comments saying to set it to false, none saying how....Swann
It’s a keyword argument to the get() function: requests.get('https://example.com', verify=False)Kabuki
Getting into the habit of accepting untrusted certificates completely negates the whole purpose of SSL. You'd be better off using a non-SSL endpoint. If your network repudiates SSL certificates wholesale it will be a hayday for attackers intercepting your network's traffic.Unexpressed
That's a fair warning, and certainly the best course of action is to fix the reason the certificate is not being accepted. There are, however, quick/throwaway scenarios where this is not needed or even possible: you're crawling a website with a broken certificate, you're running automated tests in localhost with a self-signed certificate, etc.Kabuki
So does setting the verify parameter to a string that is the path of the .pem file of the certificate count as something that could legitimately be used in production? What is a fix for this one could use in production?Aphorism
If you trust that the .pem file is legit, and it’s stored in a place you trust not to be tampered, I would call using the .pem file a production-grade solution.Kabuki
For anyone wondering how to get multiple .pem certificates into your CA_BUNDLE file, they can just be appended to each other in the same file. Run python -c "import requests; print(requests.certs.where())", and open the printed filepath to see an example.Papaw
Hi there, I have a request that gives me the response of post request in the Postman by disabling the 'SSL certificate verification' in the setting option. But, if I get the python request code that provided by the Postman, I will receive the "SSL routines', 'tls_process_server_certificate', 'certificate verify failed" error and adding the 'verify=False' does not help in this case, Is there any solution to get the response of the Postman in the python request script?Cultism
T
141

From requests documentation on SSL verification:

Requests can verify SSL certificates for HTTPS requests, just like a web browser. To check a host’s SSL certificate, you can use the verify argument:

>>> requests.get('https://kennethreitz.com', verify=True)

If you don't want to verify your SSL certificate, make verify=False

Tyranny answered 19/5, 2012 at 19:20 Comment(8)
Well, I added the verify=True, but still received the exact same error. No change. Something else must be required, but don't know what it could be.Teratogenic
I suppose I have now descended into SSL madness. I added this to my initial get...get(url1, headers=headers, cert='/etc/pki/tls/cert.pem', verify=True, config=my_config) So, now I am getting this error. requests.exceptions.SSLError: [Errno 336265225] _ssl.c:351: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib I have not a clue what this means.Teratogenic
Reading thru tons of documents I have learned I don't need the verify=True. That is for validating the certificate from the server. I don't need to do that because the server and the CAS server do that together. So basically, when you do a 'get' to the primary server, you get redirected to the CAS using https (which is ssl). So basically, the verify=True doesn't apply in this case. Still doesn't help me but maybe will help someone else who reads this.Teratogenic
Just set verify=False if you don't want to validate the certificate, iow if you have a self signed certificateSnakemouth
If you have a self-signed certificate, then download it and set verify to its filename. There is no excuse whatsoever for setting verify=False. verify='/path/to/cert.pem'Stealing
Sorry Boud, I needed to down vote this answer as requests does not handle HTTPS requests "like a web browser". If the full SSL chain of trust (including intermediate certificates) is not declared on a server and requires an extra certificate download, you will receive the above SSL verification error. Web browsers will do the extra download and not flag any certificate errors. This is one way that a web browser and Requests differ. There are others. Requests does some verification, but it is not as good as a browser.Heavierthanair
Hi there, I have a request that gives me the response of post request in the Postman by disabling the 'SSL certificate verification' in the setting option. But, if I get the python request code that provided by the Postman, I will receive the "SSL routines', 'tls_process_server_certificate', 'certificate verify failed" error and adding the 'verify=False' does not help in this case, Is there any solution to get the response of the Postman in the python request script?Cultism
@LouisCremen Awesome comment. How to fix the issue via request. I mean download complete chain of certificates ?Edger
T
71

I encountered the same issue and ssl certificate verify failed issue when using aws boto3, by review boto3 code, I found the REQUESTS_CA_BUNDLE is not set, so I fixed the both issue by setting it manually:

from boto3.session import Session
import os

# debian
os.environ['REQUESTS_CA_BUNDLE'] = os.path.join(
    '/etc/ssl/certs/',
    'ca-certificates.crt')
# centos
#   'ca-bundle.crt')

For aws-cli, I guess setting REQUESTS_CA_BUNDLE in ~/.bashrc will fix this issue (not tested because my aws-cli works without it).

REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt # ca-bundle.crt
export REQUESTS_CA_BUNDLE
Transect answered 15/11, 2015 at 7:47 Comment(4)
This fixed my problem! I was using Charles Proxy on Mac to debug a library that made JSON calls to HTTPS APIs. I installed the Charless certificate as specified, added it to the keychain, but Python kept failing with: SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",) To fix this, I ended up following your advice about adding REQUESTS_CA_BUNDLE and exporting the Charles certificate from my keychain as a .pem file. Now, it works!Koo
Thanks, the same issue was with opened FiddlerShandeigh
@Shandeigh I'm trying to get this working with Fiddler right now. Should setting REQUESTS_CA_BUNDLE to Fiddler's cert work?Lupitalupo
I'm CentOS7 OS, use REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt.Williams
B
66

The name of CA file to use you could pass via verify:

cafile = 'cacert.pem' # http://curl.haxx.se/ca/cacert.pem
r = requests.get(url, verify=cafile)

If you use verify=True then requests uses its own CA set that might not have CA that signed your server certificate.

Blowhard answered 12/10, 2012 at 18:38 Comment(9)
@9emE0iL18gxCqLT: why do you think that all systems use the path you provided? requests can be packaged for your distribution. Run python -mrequests.certs to find out where it points to.Blowhard
If the Python request's cacert bundle is out of date, how do I update it?Dollarfish
You shouldn't use that cacert.pem from curl. It contains many revoked certs. Check out Certifi (which Requests uses): certifi.ioAubree
@KennethReitz: 1- what Requests uses fails for OP (otherwise there weren't be the question) 2- cacert.pem is CA certificates extracted from Mozilla (by cURL) -- it is just an example (if the CA list used by a popular web-browser can't be used as an example then I don't know what can be) -- the point of the answer that you can pass your own CA file if the default list fails.Blowhard
Can you do this and use client certificates at the same time? I'm getting problems with this.Tying
@Tying client certificates seem unrelated to the answer (though I might be wrong, I didn't use client certificates in awhile)Blowhard
Yes, it is a different question. Just wanted to know if your answer could be applied in that situationTying
requests uses the cert parameter to specify the certificate file, not verify: requests.get('https://example.com, verify=True, cert='./cert.pem')Jonquil
@never verify is correct here (CA path). Don't confuse with client certificate. See docs.python-requests.org/en/latest/user/advanced/…Blowhard
E
50

$ pip install -U requests[security]

  • Tested on Python 2.7.6 @ Ubuntu 14.04.4 LTS
  • Tested on Python 2.7.5 @ MacOSX 10.9.5 (Mavericks)

When this question was opened (2012-05) the Requests version was 0.13.1. On version 2.4.1 (2014-09) the "security" extras were introduced, using certifi package if available.

Right now (2016-09) the main version is 2.11.1, that works good without verify=False. No need to use requests.get(url, verify=False), if installed with requests[security] extras.

Esplanade answered 19/9, 2016 at 18:57 Comment(6)
fixed by pip install -U requests[security] --no-cache two times and pip install certifi==2015.04.28Loriannlorianna
@Esplanade What if I want to either configure python to trust some ssl cert or to disable certificate verification but globally in the environment, without editing the source code? For example if I download existing Python utilities (eg the AWS CLI) and I want to trust certs or ignore certificate validation for those tools?Lupitalupo
@Lupitalupo then you can go via j-f-sebastian answer, I guess: https://mcmap.net/q/49587/-python-requests-throwing-sslerrorEsplanade
@Esplanade But doesn't his answer assume I'm writing the code and/or have access to the code? I'm looking to implement this at the environment level.Lupitalupo
do pip install --upgrade pip before installing the requests security package to avoid other errorsPohl
thanks a lot , pip install -U requests[security] helped meHawsepiece
J
40

In case you have a library that relies on requests and you cannot modify the verify path (like with pyvmomi) then you'll have to find the cacert.pem bundled with requests and append your CA there. Here's a generic approach to find the cacert.pem location:

windows

C:\>python -c "import requests; print requests.certs.where()"
c:\Python27\lib\site-packages\requests-2.8.1-py2.7.egg\requests\cacert.pem

linux

#  (py2.7.5,requests 2.7.0, verify not enforced)
root@host:~/# python -c "import requests; print requests.certs.where()"
/usr/lib/python2.7/dist-packages/certifi/cacert.pem

#  (py2.7.10, verify enforced)
root@host:~/# python -c "import requests; print requests.certs.where()"
/usr/local/lib/python2.7/dist-packages/requests/cacert.pem

btw. @requests-devs, bundling your own cacerts with request is really, really annoying... especially the fact that you do not seem to use the system ca store first and this is not documented anywhere.

update

in situations, where you're using a library and have no control over the ca-bundle location you could also explicitly set the ca-bundle location to be your host-wide ca-bundle:

REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt python -c "import requests; requests.get('https://somesite.com')";
Johnsonjohnsonese answered 4/3, 2016 at 8:38 Comment(3)
A hundred times this: key being inability to modify verify path.Mollusc
What if you're using a self signed cert? What would the CA be in that case?Invitatory
Tiny update - for python 3.6, there should be parentheses for the print command - python -c "import requests; print(requests.certs.where())"Invitatory
K
28

As pointed out by others, this problem "is caused by an untrusted SSL certificate". My answer is based on the top-rated answer and this answer.

You can test the certificate using curl:

curl -vvI https://example.com

If an error returns, you have 3 options:

  1. For a quick fix, you could just not verify the certificate:
requests.get('https://example.com', verify=False)
  1. Pass the path to the CA_BUNDLE file or directory with certificates of trusted CAs:
requests.get('https://example.com', verify='/path/to/certfile')
  1. If you have access to, fix the web server certificate.

My problem was because I was using only my site's certificate, not the intermediate (a.k.a. chain) certificate.

If you are using Let's Encrypt, you should use the fullchain.pem file, not cert.pem.

Kirkham answered 20/11, 2020 at 15:9 Comment(1)
Thanks for the answer! The quick fix to use verify=False was the only possible solution in my scenario.Metric
S
25

If you want to remove the warnings, use the code below.

import urllib3

urllib3.disable_warnings()

and verify=False with request.get() or post() method

import requests

requests.get(url, verify=False)
Saddlebag answered 3/11, 2015 at 7:42 Comment(0)
G
17

I face the same problem using gspread and these commands works for me:

sudo pip uninstall -y certifi
sudo pip install certifi==2015.04.28
Gametogenesis answered 16/2, 2016 at 4:53 Comment(3)
This did it for me. Thanks :)Predestinate
This has the downside of reinstalling potentially revoked/untrusted certificates from the older version of certifi, NOT recommended.Holograph
if for some reason you're forced to stick with an early version of python 2.7, downgrading certifi is the only approach that worked for meAgrapha
M
15

I have found an specific approach for solving a similar issue. The idea is pointing the cacert file stored at the system and used by another ssl based applications.

In Debian (I'm not sure if same in other distributions) the certificate files (.pem) are stored at /etc/ssl/certs/ So, this is the code that work for me:

import requests
verify='/etc/ssl/certs/cacert.org.pem'
response = requests.get('https://lists.cacert.org', verify=verify)

For guessing what pem file choose, I have browse to the url and check which Certificate Authority (CA) has generated the certificate.

EDIT: if you cannot edit the code (because you are running a third app) you can try to add the pem certificate directly into /usr/local/lib/python2.7/dist-packages/requests/cacert.pem (e.g. copying it to the end of the file).

Mahone answered 18/4, 2013 at 14:29 Comment(2)
Related post for debugging CA_BUNDLE used by python.Mahone
What about replacing /usr/local/lib/python2.7/dist-packages/requests/cacert.pem with a symlink to the OS store?Dollarfish
A
10

If you don't bother about certificate just use verify=False.

import requests

url = "Write your url here"

returnResponse = requests.get(url, verify=False)
Atcliffe answered 21/5, 2015 at 12:1 Comment(0)
M
9

After hours of debugging I could only get this to work using the following packages:

requests[security]==2.7.0  # not 2.18.1
cryptography==1.9  # not 2.0

using OpenSSL 1.0.2g 1 Mar 2016

Without these packages verify=False was not working.

I hope this helps someone.

Muncey answered 20/7, 2017 at 20:10 Comment(0)
F
6

I ran into the same issue. Turns out I hadn't installed the intermediate certificate on my server (just append it to the bottom of your certificate as seen below).

https://www.digicert.com/ssl-support/pem-ssl-creation.htm

Make sure you have the ca-certificates package installed:

sudo apt-get install ca-certificates

Updating the time may also resolve this:

sudo apt-get install ntpdate
sudo ntpdate -u ntp.ubuntu.com

If you're using a self-signed certificate, you'll probably have to add it to your system manually.

Freebooter answered 13/6, 2014 at 19:19 Comment(2)
Note, this only applies to Requests installations via apt-get, which is modified by Debian/Ubuntu to use system certs. Requests proper ships with its own, carefully curated, CA bundle: certifi.ioAubree
Shouldn't the root CA be enough? Why do you need the intermediates?Moorefield
I
6

If the request calls are buried somewhere deep in the code and you do not want to install the server certificate, then, just for debug purposes only, it's possible to monkeypatch requests:

import requests.api
import warnings


def requestspatch(method, url, **kwargs):
    kwargs['verify'] = False
    return _origcall(method, url, **kwargs)

_origcall = requests.api.request
requests.api.request = requestspatch
warnings.warn('Patched requests: SSL verification disabled!')

Never use in production!

Inbred answered 29/8, 2017 at 6:6 Comment(0)
S
6

Too late to the party I guess but I wanted to paste the fix for fellow wanderers like myself! So the following worked out for me on Python 3.7.x

Type the following in your terminal

pip install --upgrade certifi      # hold your breath..

Try running your script/requests again and see if it works (I'm sure it won't be fixed yet!). If it didn't work then try running the following command in the terminal directly

open /Applications/Python\ 3.6/Install\ Certificates.command  # please replace 3.6 here with your suitable python version
Stgermain answered 29/11, 2018 at 11:32 Comment(0)
P
4

This is similar to @rafael-almeida 's answer, but I want to point out that as of requests 2.11+, there are not 3 values that verify can take, there are actually 4:

  • True: validates against requests's internal trusted CAs.
  • False: bypasses certificate validation completely. (Not recommended)
  • Path to a CA_BUNDLE file. requests will use this to validate the server's certificates.
  • Path to a directory containing public certificate files. requests will use this to validate the server's certificates.

The rest of my answer is about #4, how to use a directory containing certificates to validate:

Obtain the public certificates needed and place them in a directory.

Strictly speaking, you probably "should" use an out-of-band method of obtaining the certificates, but you could also just download them using any browser.

If the server uses a certificate chain, be sure to obtain every single certificate in the chain.

According to the requests documentation, the directory containing the certificates must first be processed with the "rehash" utility (openssl rehash).

(This requires openssl 1.1.1+, and not all Windows openssl implementations support rehash. If openssl rehash won't work for you, you could try running the rehash ruby script at https://github.com/ruby/openssl/blob/master/sample/c_rehash.rb , though I haven't tried this. )

I had some trouble with getting requests to recognize my certificates, but after I used the openssl x509 -outform PEM command to convert the certs to Base64 .pem format, everything worked perfectly.

You can also just do lazy rehashing:

try:
    # As long as the certificates in the certs directory are in the OS's certificate store, `verify=True` is fine.
    return requests.get(url, auth=auth, verify=True)
except requests.exceptions.SSLError:
    subprocess.run(f"openssl rehash -compat -v my_certs_dir", shell=True, check=True)
    return requests.get(url, auth=auth, verify="my_certs_dir")
Papaw answered 10/10, 2019 at 20:44 Comment(0)
J
3

I fought this problem for HOURS.

I tried to update requests. Then I updated certifi. I pointed verify to certifi.where() (The code does this by default anyways). Nothing worked.

Finally I updated my version of python to python 2.7.11. I was on Python 2.7.5 which had some incompatibilities with the way that the certificates are verified. Once I updated Python (and a handful of other dependencies) it started working.

Jacobs answered 6/5, 2016 at 21:13 Comment(2)
If you updated OpenSSL to a version > 1.0.1, than that was probably the issue. See my answer bellow. https://mcmap.net/q/49587/-python-requests-throwing-sslerrorMatriculation
Going from Python 2.7.9 to 2.7.10 fixed this for me.Plaice
A
3

Some servers do not have the trusted root cert for Letsencrypt.

For example, assume the server pointed by the url below is protected by a Letsencrypt SSL.

requests.post(url, json=data)

This request can fail with [SSL: CERTIFICATE_VERIFY_FAILED] because the requesting server does not have the root cert for Letsencrypt.

When this happens download the active self-signed 'pem' cert from the link below.

https://letsencrypt.org/certificates/. (Active ISRG Root X1 as of this writing)

Now, use that in the verify parameter as follows.

requests.post(url, json=data, verify='path-to/isrgrootx1.pem')
Amandy answered 20/10, 2021 at 20:9 Comment(0)
B
2

There is currently an issue in the requests module causing this error, present in v2.6.2 to v2.12.4 (ATOW): https://github.com/kennethreitz/requests/issues/2573

Workaround for this issue is adding the following line: requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'

Brightness answered 15/1, 2017 at 20:10 Comment(1)
FWIW, it's still present with requests==2.13.0. The above workaround fixes it still.Malpighi
D
2

I think you have several ways for fix this issue. I mentioned 5 ways below:

  1. You can define context for each request and pass the context on each request for use it like below:
import certifi
import ssl
import urllib
context = ssl.create_default_context(cafile=certifi.where())
result = urllib.request.urlopen('https://www.example.com', context=context)
  1. OR Set certificate file in environment.
import os
import certifi
import urllib
os.environ["REQUESTS_CA_BUNDLE"] = certifi.where()
os.environ["SSL_CERT_FILE"] = certifi.where()
result = urllib.request.urlopen('https://www.example.com')

  1. OR Replace create default https context method:
import certifi
import ssl
ssl._create_default_https_context = lambda: ssl.create_default_context(cafile=certifi.where())
result = urllib.request.urlopen('https://www.example.com')
  1. OR If you use Linux machine, generating fresh certificates and exporting an environment variable pointing to the certificates directory fixed it.
$ sudo update-ca-certificates --fresh
$ export SSL_CERT_DIR=/etc/ssl/certs
  1. OR If you use Mac machine, generating fresh certificates
$ cd "/Applications/$(python3 --version | awk '{print $2}'| awk  -F. '{print "Python " $1"."$2}')"
$ sudo "./Install Certificates.command"
Digitigrade answered 7/8, 2022 at 19:7 Comment(1)
#4 crossed with #2 works with my Docker image based on Debian Buster running Python 3.10 and making the requests to the server with aiohttp. I know that's not the question but there is significant overlap and google seems to think there are similarities. I found that rebuilding certs file and setting SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt does work with aiohttp.Scheers
T
2

Everything here failed for me. My company uses Z-Scaler and recently activated some extra protection that resulted in python packages such as plantweb failing with this error:

SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate

The problem was that Z-Scaler is using its own certificate, so I needed to get that file from IT and tell python to use it.

export REQUESTS_CA_BUNDLE="/path/to/zscaler.crt"
plantweb --format png some_file.puml

However, this introduced another problem: Some other code I had started failing with the same SSL error because it needed to use the standard certificates from python's certifi package.

The final solution that worked for me was to combine the normal certificates and the Z-Scaler one into a single certificate and tell python to use that:

pip3 install certifi
normal_python_cert="$(python3 -m certifi)"
cat $normal_python_cert /path/to/zscaler.crt > combined.crt
export REQUESTS_CA_BUNDLE=/path/to/combined.crt
plantweb --format png some_file.puml

Super useful reference: https://help.zscaler.com/zia/adding-custom-certificate-application-specific-trust-store#python

Trilbee answered 1/3, 2023 at 23:9 Comment(0)
O
1

As mentioned by @Rafael Almeida, the problem you are having is caused by an untrusted SSL certificate. In my case, the SSL certificate was untrusted by my server. To get around this without compromising security, I downloaded the certificate, and installed it on the server (by simply double clicking on the .crt file and then Install Certificate...).

Oshaughnessy answered 14/6, 2017 at 11:7 Comment(0)
M
1

In my case the reason was fairly trivial.

I had known that the SSL verification had worked until a few days earlier, and was infact working on a different machine.

My next step was to compare the certificate contents and size between the machine on which verification was working, and the one on which it was not.

This quickly led to me determining that the Certificate on the 'incorrectly' working machine was not good, and once I replaced it with the 'good' cert, everything was fine.

Meet answered 30/4, 2019 at 11:59 Comment(1)
Yes, sometimes the problem is not with the code, the CERT really just doesn't match ... ( certs sometimes belong to a certain env etc .. )Cariole
A
0

It is not feasible to add options if requests is being called from another package. In that case adding certificates to the cacert bundle is the straight path, e.g. I had to add "StartCom Class 1 Primary Intermediate Server CA", for which I downloaded the root cert into StartComClass1.pem. given my virtualenv is named caldav, I added the certificate with:

cat StartComClass1.pem >> .virtualenvs/caldav/lib/python2.7/site-packages/pip/_vendor/requests/cacert.pem
cat temp/StartComClass1.pem >> .virtualenvs/caldav/lib/python2.7/site-packages/requests/cacert.pem

one of those might be enough, I did not check

Assess answered 3/8, 2015 at 17:29 Comment(0)
M
0

I was having a similar or the same certification validation problem. I read that OpenSSL versions less than 1.0.2, which requests depends upon sometimes have trouble validating strong certificates (see here). CentOS 7 seems to use 1.0.1e which seems to have the problem.

I wasn't sure how to get around this problem on CentOS, so I decided to allow weaker 1024bit CA certificates.

import certifi # This should be already installed as a dependency of 'requests'
requests.get("https://example.com", verify=certifi.old_where())
Matriculation answered 11/7, 2017 at 13:26 Comment(1)
I use a Python 2.7.10 installed by ArcGIS and there is no certifi module installed. The requests module installed is in version 2.11.1.Camilacamile
R
0

I had to upgrade from Python 3.4.0 to 3.4.6

pyenv virtualenv 3.4.6 myvenv
pyenv activate myvenv
pip install -r requirements.txt
Rumpf answered 7/3, 2018 at 23:22 Comment(0)
G
0

I found this answer which fixed it:

import ssl
import certifi
import urllib.request

url = "https://www.google.com/"
html = urllib.request.urlopen(url, context=ssl.create_default_context(cafile=certifi.where()))

I have no idea what it does, though.

Gentlefolk answered 2/10, 2021 at 6:41 Comment(0)
N
0

When it says verify takes 'path to certificate', I pointed it to the issuer certificate so that it can use that to verify the url's certificate. curl and wget were fine with that certificate. But not python requests.

I had to create a certificate chain with all the certificates from end (leaf?) to root for python requests to process it fine. And the chain works fine with cURL and Wget too naturally.

Hope it helps someone and saves few hours.

Negligent answered 27/10, 2022 at 11:54 Comment(0)
C
-2

This is just another way you can try to solve the issue.

If you put "www.example.com", requests shouts at you. If you put "https://www.example.com", you get this error. So if you DO NOT NEED https, you can avoid the error by changing "https" to "http". eg. "http://www.example.com"

WARNING: Not using HTTPS is generally not a good idea. See Why HTTPS for Everything? Why HTTPS matters

Cal answered 2/9, 2020 at 8:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.