438

I am getting the following error:

Exception in thread Thread-3:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 810, in        __bootstrap_inner
self.run()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 763, in  run
self.__target(*self.__args, **self.__kwargs)
File "/Users/Matthew/Desktop/Skypebot 2.0/bot.py", line 271, in process
info = urllib2.urlopen(req).read()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 431, in open
response = self._open(req, data)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 449, in _open
'_open', req)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 409, in _call_chain
result = func(*args)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1240, in https_open
context=self._context)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1197, in do_open
raise URLError(err)
URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)>

This is the code that is causing this error:

if input.startswith("!web"):
    input = input.replace("!web ", "")      
    url = "https://domainsearch.p.mashape.com/index.php?name=" + input
    req = urllib2.Request(url, headers={ 'X-Mashape-Key': 'XXXXXXXXXXXXXXXXXXXX' })
    info = urllib2.urlopen(req).read()
    Message.Chat.SendMessage ("" + info)

The API I'm using requires me to use HTTPS. How can I make it bypass the verification?

HamZa
  • 14,671
  • 11
  • 54
  • 75
user3724476
  • 4,720
  • 3
  • 15
  • 20
  • 5
    There is nothing wrong with the URL and it can be successfully verified with the common trusted certificates. So you should better not try to bypass certificate validation, but to fix it. Which version of python you are using? – Steffen Ullrich Jan 08 '15 at 08:27
  • This might be related to http://stackoverflow.com/a/27826829/3081018. The server uses the same kind of certificate chain with multiple trust path. See there which cafile you might need to use for verification. – Steffen Ullrich Jan 08 '15 at 08:31
  • I am using Python 2.7 – user3724476 Jan 08 '15 at 08:56
  • Python 2.7.9 or which version exactly? You see the version if you just call 'python' on the command line. – Steffen Ullrich Jan 08 '15 at 09:56
  • Same error for me, which started to annoy me, once I've updated on 2.7.9 – om-nom-nom Jan 28 '15 at 18:32
  • 8
    This error also occurs on Python 3.5 after upgrading to yosemite – pyCthon Mar 03 '15 at 22:43
  • 2
    This explains the situation. https://access.redhat.com/articles/2039753 – Charlie Burns Jan 10 '17 at 00:15
  • 10
    *"How can I make it bypass the verification?"* is the wrong question. You should probably ask how to validate the certificate provided by the domain. – jww Jun 08 '17 at 05:24
  • The OP didn't mention if he's working on a private server. For example, I can't load external datasets to my company Python server, such as the Titanic dataset from the `seaborn` module, due to security concerns. – RobertF Dec 03 '18 at 15:59
  • Changing `https:` to `http:` on 2 lines in `yolk/pypi.py` made [yolk3k](https://github.com/myint/yolk) work, bypass the SSL CERTIFICATE_VERIFY_FAILED, on macos 10.10, python 3.7.6, OpenSSL 19.1.0. (Sure, security leak -- but `yolk -l -f home-page,summary,requires` is soo useful.) – denis Aug 22 '20 at 13:05
  • for me what works: ```import ssl``` then ```ssl._create_default_https_context = ssl._create_unverified_context``` from https://stackoverflow.com/a/49174340/9439097 – charelf Nov 11 '21 at 13:20

47 Answers47

573

This isn't a solution to your specific problem, but I'm putting it here because this thread is the top Google result for "SSL: CERTIFICATE_VERIFY_FAILED", and it lead me on a wild goose chase.

If you have installed Python 3.6 on OSX and are getting the "SSL: CERTIFICATE_VERIFY_FAILED" error when trying to connect to an https:// site, it's probably because Python 3.6 on OSX has no certificates at all, and can't validate any SSL connections. This is a change for 3.6 on OSX, and requires a post-install step, which installs the certifi package of certificates. This is documented in the file ReadMe.rtf, which you can find at /Applications/Python\ 3.6/ReadMe.rtf (see also the file Conclusion.rtf, and the script build-installer.py that generates the macOS installer).

The ReadMe will have you run the post-install script at

/Applications/Python\ 3.10/Install\ Certificates.command (Terminal App, this command alone should, fix the issue. Be sure to update the file path using your current subversion.)

(its source is install_certificates.command), which:

Release notes have some more info: https://www.python.org/downloads/release/python-360/

On newer versions of Python, there is more documentation about this:

JayRizzo
  • 3,234
  • 3
  • 33
  • 49
Craig Glennie
  • 5,913
  • 1
  • 14
  • 6
  • 2
    I'm using OS X El Capitan 10.11.6, Python 3.6.0 and this solution worked perfectly. – y2knoproblem Apr 23 '17 at 00:08
  • 2
    I'm using macOS Sierra 10.12.5, Python 3.6.1 and this solution worked perfectly. – James Jul 20 '17 at 05:04
  • 1
    i had to run this even though i was running a virtualenv with certifi installed.... worked though. – Ian Oct 09 '17 at 21:06
  • 1
    Thank you Craig! I had to install certifi manually via pip3. After that your command worked for me. – zombi_man Feb 06 '18 at 15:24
  • 1
    @CraigGlennie How do I solve the problem, if I don't have admin rights? Thanks! – tommy.carstensen Feb 16 '18 at 00:19
  • @tommy.carstensen you may need to try using a virtualenv, and installing the `certifi` package in there. – Craig Glennie Mar 04 '18 at 18:13
  • @CraigGlennie I did brew install in the end of Python and SSL certificates. – tommy.carstensen Mar 04 '18 at 19:34
  • I'm under the gun to get out some analysis, and your post saved me losing hours chasing down a red herring. Much appreciated. – bmosov01 Mar 05 '18 at 23:30
  • This work PERFECTLY in my Macbook. BUT, I have the same error in AWS. I can't run this command in my ec2. – GIA Jun 01 '18 at 22:27
  • Verified this also works on Python 3.7. Thanks, this is definitely the quickest and simplest solution! – natonomo Oct 18 '18 at 17:15
  • Verified that this does not in fact work on Python 3.6. The direct command, pip install certifi, does not fix the issue either. -1 – hpm Dec 02 '18 at 12:42
  • I didn't use the Python installer when I installed Python (maybe I used homebrew?), so I couldn't find where this command was. Per the suggestion here https://stackoverflow.com/a/49953648/3322074, I reinstalled Python 3 with the installer, and the directions for running this script were in the installation complete window. – user124384 Jan 25 '19 at 22:23
  • 3
    Still doesn't help with Python3.7 and macOS 10.14.4 – Roman Mar 31 '19 at 11:38
  • 2
    Anyone got this to work on Debian or equivalent? Tried installing python-certifi but didn't work. – Dan Walters Apr 03 '19 at 14:41
  • 4
    I can't find /Application/Python 3.6/ directory. I installed Anaconda. Can anyone tell me how to do it with python installed with Anaconda? – Jimmy Li May 08 '19 at 21:44
  • 7
    Python 3.7 on macOS Mojave: it doesn't work here. I've uninstalled / reinstalled / run the install certificate, rebooted, etc.. doesn't work for me – Thomas Jul 19 '19 at 10:12
  • 1
    How does this work if you are using pyenv along with virtualenv? When I go to ~/.pyenv/versions/3.6.0/ I don't see an Install directory. – James Parker Sep 19 '19 at 13:34
  • worked for me with Python3.7 on macOS Mojave, I was using virtualenv so I removed the virtual dir, install the certificate and then recreate the virtualenv. – xergiopd Nov 25 '19 at 09:23
  • thanks ,solved the problem for OS X 10.11.6 and python 3.7 – Amin Hemati Nik Dec 15 '19 at 06:03
  • -bash: /Applications/Python 3.6/Install Certificates.command: No such file or directory – demongolem Jan 03 '20 at 12:42
  • I installed Python via Homebrew so I don't have this `.command` file. What's the solution then? – numbermaniac Feb 21 '20 at 03:50
  • For 3.8 do this, /Applications/Python\ 3.8/Install\ Certificates.command – Joseph Astrahan Apr 26 '20 at 01:00
  • can you just `pip install certifi` instead, or is that insufficient? – ascourtas May 20 '20 at 15:17
  • This is the correct solution.. but.. how do you deal with application "compiled" with py2app and similar? – 0plus1 Sep 29 '20 at 02:27
  • I am using MacOS Catalina and Python 3.7. Directly run /Applications/Python\ 3.7/Install\ Certificates.command solve my problem on OSX. Thanks. – donut Mar 03 '21 at 18:27
  • I had the same problem in Ubuntu I following your instructions I could solve it. Thank you! – Henry Navarro Jul 14 '21 at 15:00
  • For MacOS 12.4 and Python 3.6 I had to run the install certificates command as root. Thanks! – Thorbjørn Ravn Andersen May 26 '22 at 10:21
  • The following fixed it for MacOs Monterey 12.5.1, python 3.8: `pip install certifi && /Applications/Python\ 3.8/Install\ Certificates.command` – Avishag Sahar Aug 28 '22 at 14:58
  • FYI still an issue for 3.10. `/Applications/Python\ 3.10/Install\ Certificates.command` This will fix the error "SSL: CERTIFICATE_VERIFY_FAILED" – JayRizzo Aug 30 '22 at 20:25
  • 1
    This is still required for Python 3.11 and MacOS Monterey 12.6. However, it works like a charm. – Doug Oct 31 '22 at 12:17
390

If you just want to bypass verification, you can create a new SSLContext. By default newly created contexts use CERT_NONE.

Be careful with this as stated in section 17.3.7.2.1

When calling the SSLContext constructor directly, CERT_NONE is the default. Since it does not authenticate the other peer, it can be insecure, especially in client mode where most of time you would like to ensure the authenticity of the server you’re talking to. Therefore, when in client mode, it is highly recommended to use CERT_REQUIRED.

But if you just want it to work now for some other reason you can do the following, you'll have to import ssl as well:

input = input.replace("!web ", "")      
url = "https://domainsearch.p.mashape.com/index.php?name=" + input
req = urllib2.Request(url, headers={ 'X-Mashape-Key': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' })
gcontext = ssl.SSLContext()  # Only for gangstars
info = urllib2.urlopen(req, context=gcontext).read()
Message.Chat.SendMessage ("" + info)

This should get round your problem but you're not really solving any of the issues, but you won't see the [SSL: CERTIFICATE_VERIFY_FAILED] because you now aren't verifying the cert!

To add to the above, if you want to know more about why you are seeing these issues you will want to have a look at PEP 476.

This PEP proposes to enable verification of X509 certificate signatures, as well as hostname verification for Python's HTTP clients by default, subject to opt-out on a per-call basis. This change would be applied to Python 2.7, Python 3.4, and Python 3.5.

There is an advised opt out which isn't dissimilar to my advice above:

import ssl

# This restores the same behavior as before.
context = ssl._create_unverified_context()
urllib.urlopen("https://no-valid-cert", context=context)

It also features a highly discouraged option via monkeypatching which you don't often see in python:

import ssl

ssl._create_default_https_context = ssl._create_unverified_context

Which overrides the default function for context creation with the function to create an unverified context.

Please note with this as stated in the PEP:

This guidance is aimed primarily at system administrators that wish to adopt newer versions of Python that implement this PEP in legacy environments that do not yet support certificate verification on HTTPS connections. For example, an administrator may opt out by adding the monkeypatch above to sitecustomize.py in their Standard Operating Environment for Python. Applications and libraries SHOULD NOT be making this change process wide (except perhaps in response to a system administrator controlled configuration setting).

If you want to read a paper on why not validating certs is bad in software you can find it here!

Asclepius
  • 57,944
  • 17
  • 167
  • 143
Noelkd
  • 7,686
  • 2
  • 29
  • 43
  • 1
    So if this error is keeping me from using `setup.py upload` how can I fix that? – pyCthon Mar 03 '15 at 22:36
  • 10
    ssl._create_default_https_context = ssl._create_unverified_context this worked for me as mentioned by Noelkd near the end. As ours is an intranet site for HP printers... purely used for scraping... we don't have an issue with using this method. – ihightower Mar 26 '15 at 09:59
  • 1
    You first method is the least desirable one - bypass validation. Why is the one that actually validates the certificate not listed first? – jww Jun 08 '17 at 05:23
  • 1
    this can also happen if you have an outdate version of openSSL. So for me what worked was updating to most recent version of `certifi ` and updating openssl on the boxes. – Mahdi Yusuf Jun 27 '17 at 16:26
  • 1
    `context ` is what I needed – prayagupa Nov 15 '17 at 00:40
  • thanks to @Noelkd ,this works for me . /** import ssl context = ssl._create_unverified_context() urllib.urlopen("https://no-valid-cert", context=context) */ – wolfog Nov 06 '18 at 12:13
  • After using ssl._create_default_https_context = ssl._create_unverified_context, how do I set it back to the default behavior? (verified context) – milanDD Dec 19 '19 at 10:25
  • For me I have to use `gcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)` – C-Y Jan 05 '22 at 01:56
  • I just wanted to note that after [this](https://github.com/boto/boto/blob/b2a6f08122b2f1b89888d2848e730893595cd001/boto/connection.py#L74) line in boto package, I had to add `ssl._create_default_https_context = ssl._create_unverified_context `. – tash Feb 20 '22 at 00:26
103

To expand on Craig Glennie's answer:

in Python 3.6.1 on MacOs Sierra

Entering this in the bash terminal solved the problem:

pip install certifi
/Applications/Python\ 3.6/Install\ Certificates.command
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
jnPy
  • 1,179
  • 1
  • 7
  • 5
75

On Windows, Python does not look at the system certificate, it uses its own located at ?\lib\site-packages\certifi\cacert.pem.

The solution to your problem:

  1. download the domain validation certificate as *.crt or *pem file
  2. open the file in editor and copy it's content to clipboard
  3. find your cacert.pem location: from requests.utils import DEFAULT_CA_BUNDLE_PATH; print(DEFAULT_CA_BUNDLE_PATH)
  4. edit the cacert.pem file and paste your domain validation certificate at the end of the file.
  5. Save the file and enjoy requests!
Bruno Gabuzomeu
  • 1,061
  • 8
  • 9
  • 10
    `lib\site-packages\certifi\cacert.pem` does not exist in Python 2.7.10. And the question is about `urllib2` not `requests` – Kevin Smyth Jan 15 '16 at 21:38
  • 2
    Best solution so far, twitter API uses DigiCert certificate which is not in my python's cacert.pem file. I added there and VOILA! – digz6666 Feb 23 '16 at 04:07
  • 2
    Worked on Debian. For the records, the file path on my system was: `/usr/local/lib/python2.7/dist-packages/certifi-2015.09.06.2-py2.7.egg/certifi/cacert.pem`. Thanks! – ofavre Mar 23 '17 at 12:01
  • 1
    Unfortunately python requests does not use any operating system's CA trust store. https://github.com/requests/requests/issues/2966. You have to set REQUESTS_CA_BUNDLE https://github.com/bloomreach/s4cmd/issues/111#issuecomment-406839514. – jamshid Jul 22 '18 at 05:49
  • Works on Windows 10, Python 3.6, with the Google and Twitter APIs and the requests module in general. – tblznbits Nov 20 '18 at 14:18
  • This worked for me on macOS Catalina 10.15.2, brew installed Python 3.7.6, with a self-signed certificate which I exported from Keychain as a .pem. I had already trusted the certificate in Keychain, but apparently Python does not look at that. Thanks! – Josh Mar 06 '20 at 17:33
  • Great! Worked for me!...Actually, for my website, I had to concatenate both cert and chain files to cacert.pem. – Dounchan Jan 03 '21 at 22:18
  • In my case I had 2 corporate certificates, adding these 2 certificates at the end of cacert.pem did the trick for me. – Sujith Sep 14 '22 at 02:43
  • the domain validation certificate as *.crt means you can export it from chrome which is used by your company for proxy usage – shuhui geng Apr 08 '23 at 14:49
65

I was having a similar problem, though I was using urllib.request.urlopen in Python 3.4, 3.5, and 3.6. (This is a portion of the Python 3 equivalent of urllib2, per the note at the head of Python 2's urllib2 documentation page.)

My solution was to pip install certifi to install certifi, which has:

... a carefully curated collection of Root Certificates for validating the trustworthiness of SSL certificates while verifying the identity of TLS hosts.

Then, in my code where I previously just had:

import urllib.request as urlrq

resp = urlrq.urlopen('https://example.com/bar/baz.html')

I revised it to:

import urllib.request as urlrq
import certifi

resp = urlrq.urlopen('https://example.com/bar/baz.html', cafile=certifi.where())

If I read the urllib2.urlopen documentation correctly, it also has a cafile argument. So, urllib2.urlopen([...], certifi.where()) might work for Python 2.7 as well.


UPDATE (2020-01-01): As of Python 3.6, the cafile argument to urlopen has been deprecated, with the context argument supposed to be specified instead. I found the following to work equally well on 3.5 through 3.8:

import urllib.request as urlrq
import certifi
import ssl

resp = urlrq.urlopen('https://example.com/bar/baz.html', context=ssl.create_default_context(cafile=certifi.where()))
Saim Ehsan
  • 21
  • 6
hBy2Py
  • 1,707
  • 19
  • 29
  • 1
    `load_verify_locations` mutates the `SSLContext` instance and returns `None`. You should use `context=ssl.create_default_context(cafile=certifi.where())` instead. See the [`ssl` docs](https://docs.python.org/3/library/ssl.html#ssl.create_default_context) for more info. – ostrokach Jan 20 '20 at 20:13
  • 1
    @ostrokach Huh, I tried something like that, but I must've used the wrong `ssl` function. See edit; ok? – hBy2Py Jan 21 '20 at 14:13
  • 1
    This is *the* answer. Thanks. – Alexey Burdin Sep 26 '20 at 21:31
  • @hBy2Py I'm thinking this may fix my issue https://askubuntu.com/questions/1401379/certificate-verify-failed-error Question: what is baz.html? The template URL of your Django app? And do the imports go into views.py? – BlueDogRanch Apr 07 '22 at 17:12
  • To answer your specific questions here, @BlueDogRanch: 1) `https://.../baz.html` is just a fake website address, to demonstrate the syntax. 2) The imports need to go in whatever module where the `urlopen()` (or whatever resource opener) function is called, and the new SSL context pointing to the `certifi` certificates needs to be passed into the opener as the `context` keyword argument). – hBy2Py Apr 11 '22 at 20:57
51

My solution for Mac OS X:

  1. Upgrade to Python 3.6.5 using the native app Python installer downloaded from the official Python language website https://www.python.org/downloads/

I've found that this installer is taking care of updating the links and symlinks for the new Python a lot better than homebrew.

  1. Install a new certificate using "./Install Certificates.command" which is in the refreshed Python 3.6 directory
cd "/Applications/Python 3.6/"
sudo "./Install Certificates.command"
David Beauchemin
  • 231
  • 1
  • 2
  • 12
Claude COULOMBE
  • 3,434
  • 2
  • 36
  • 39
41

You could try adding this to your environment variables:

PYTHONHTTPSVERIFY=0 

Note that this will disable all HTTPS verification so is a bit of a sledgehammer approach, however if verification isn't required it may be an effective solution.

Chris Halcrow
  • 28,994
  • 18
  • 176
  • 206
  • 33
    I suspect that disabling all HTTP verification for all of python is a bit excessive to deal with one error in verification. There are a lot of cases in which one might want verification by default. – trevorKirkby Dec 22 '16 at 03:27
  • Worked for me on Windows Server 2016 on python 2.7.13. I normally don't have python installed on windows servers but needed it for a vCenter upgrade with Nexus 1000v migration to VDS, and this just fixes the problem with a self-signed vCenter cert for the time being (will use VMCA and valid certs in upgraded environment). I had no luck getting the cert to be accepted by editing the cacert.pem in python request package – Christopher Thorjussen May 29 '17 at 11:40
  • 3
    Also, I set the variable directly in command line window before running the script, so it won't be disabling all checks like @someone-or-other are afraid of, which I too wouldn't recommend. – Christopher Thorjussen May 29 '17 at 11:41
  • That's perfect for my use case: testing. I would never do this on production, but for running tests which have nothing to do with SSL, that's a wonderful option. – sorin Jun 15 '17 at 16:25
  • Thanks, this solution did it for me: import os os.environ["PYTHONHTTPSVERIFY"] = "0" – mbello Sep 11 '18 at 14:27
  • Dangerous, but for sure a quick fix. One can run a script named `script.py` like this: `PYTHONHTTPSVERIFY=0 script.py` – Bernardo do Amaral Teodosio Mar 23 '23 at 17:52
30

I had a similar problem on one of my Linux machines. Generating fresh certificates and exporting an environment variable pointing to the certificates directory fixed it for me:

$ sudo update-ca-certificates --fresh
$ export SSL_CERT_DIR=/etc/ssl/certs
ritiek
  • 2,477
  • 2
  • 18
  • 25
16

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"
Ali ZahediGol
  • 876
  • 2
  • 10
  • 20
15
import requests
requests.packages.urllib3.disable_warnings()

import ssl

try:
    _create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
    # Legacy Python that doesn't verify HTTPS certificates by default
    pass
else:
    # Handle target environment that doesn't support HTTPS verification
    ssl._create_default_https_context = _create_unverified_https_context

Taken from here https://gist.github.com/michaelrice/a6794a017e349fc65d01

Prostak
  • 3,565
  • 7
  • 35
  • 46
  • tested this solution in Jenkins environment, personal environment, this works! – rapport89 Sep 29 '18 at 07:09
  • 6
    This is extremely unsafe as it bypasses ALL certificate verification, use at your own risk and for the love of ANYBODY don't use this in production code. – dragon788 Jan 08 '19 at 22:51
  • 1
    Thanks. Finally it worked. It's not necessary that Python 3.6 is installed under /Applications on Mac OS. This should be the accepted answer. – Biranchi Feb 12 '19 at 03:38
  • 1
    You should never ever do such monkeypatching. It is extremely dangerous and will affect all downstream use of the code. – Asclepius Feb 21 '19 at 17:01
14

Like I've written in a comment, this problem is probably related to this SO answer.

In short: there are multiple ways to verify the certificate. The verification used by OpenSSL is incompatible with the trusted root certificates you have on your system. OpenSSL is used by Python.

You could try to get the missing certificate for Verisign Class 3 Public Primary Certification Authority and then use the cafile option according to the Python documentation:

urllib2.urlopen(req, cafile="verisign.pem")
jwpfox
  • 5,124
  • 11
  • 45
  • 42
Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Can you help me plz solve this relevant problem in python and ssl validation [link](https://stackoverflow.com/questions/50058209/how-to-allow-python-to-trust-my-servers-tls-self-signed-certificate-ssl-sslerr) – None Apr 27 '18 at 08:38
11
$ cd $HOME
$ wget --quiet https://curl.haxx.se/ca/cacert.pem
$ export SSL_CERT_FILE=$HOME/cacert.pem

Source: https://access.redhat.com/articles/2039753

veganaiZe
  • 539
  • 5
  • 13
  • 2
    This seemed too simple and I passed this by on my initial search. I'm kicking myself now. It's pretty confusing on Ubuntu why Python's Certifi uses separate bundled certificate bundles instead of defaulting to the system ones first. Thanks for saving my week. – Dave Davis Nov 08 '20 at 23:11
  • 1
    Tested also work on windows, change the export to set. – Frank Feb 06 '21 at 18:15
  • when you face SSL cert error when running flask run create-app using flask-appbuilder in Mac, this will help you without the need to run sudo – praba230890 Feb 18 '22 at 14:30
  • Hi @veganaiZe Why does the haxx.se cert work? Is this something I should try for https://askubuntu.com/questions/1401379/certificate-verify-failed-error – BlueDogRanch Apr 07 '22 at 17:16
  • Hi @BlueDogRanch, Not sure exactly what you mean; Maybe this link helps? https://curl.se/docs/caextract.html – veganaiZe Apr 08 '22 at 21:03
  • Thanks, that helped with an explanation, but using it didn't fix my issue. – BlueDogRanch Apr 09 '22 at 15:51
  • Well then you might want to create a new post with your issue @BlueDogRanch. – veganaiZe Apr 10 '22 at 17:41
9

Solution for Anaconda

My setup is Anaconda Python 3.7 on MacOS with a proxy. The paths are different.

  • This is how you get the correct certificates path:
import ssl
ssl.get_default_verify_paths()

which on my system produced

Out[35]: DefaultVerifyPaths(cafile='/miniconda3/ssl/cert.pem', capath=None,
 openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/miniconda3/ssl/cert.pem',
 openssl_capath_env='SSL_CERT_DIR', openssl_capath='/miniconda3/ssl/certs')

Once you know where the certificate goes, then you concatenate the certificate used by the proxy to the end of that file.

I had already set up conda to work with my proxy, by running:

conda config --set ssl_verify <pathToYourFile>.crt

If you don't remember where your cert is, you can find it in ~/.condarc:

ssl_verify: <pathToYourFile>.crt

Now concatenate that file to the end of /miniconda3/ssl/cert.pem and requests should work, and in particular sklearn.datasets and similar tools should work.

Further Caveats

The other solutions did not work because the Anaconda setup is slightly different:

  • The path Applications/Python\ 3.X simply doesn't exist.

  • The path provided by the commands below is the WRONG path

from requests.utils import DEFAULT_CA_BUNDLE_PATH
DEFAULT_CA_BUNDLE_PATH
Leo
  • 2,775
  • 27
  • 29
7

I need to add another answer because just like Craig Glennie, I went on a wild goose chase due to the many posts referring to this problem across the Web.

I am using MacPorts, and what I originally thought was a Python problem was in fact a MacPorts problem: it does not install a root certificate with its installation of openssl. The solution is to port install curl-ca-bundle, as mentioned in this blog post.

corwin.amber
  • 393
  • 1
  • 3
  • 10
6

Python 2.7.12 (default, Jul 29 2016, 15:26:22) fixed the mentioned issue. This information might help someone else.

caot
  • 3,066
  • 35
  • 37
  • 3
    I encountered it on 2.7.12 on mac, using urllib2 library, using requets library seems fine though – marcadian Aug 22 '16 at 23:15
  • @marcadian Installing and using `certifi`, which is apparently a scrape of the certificates held by `requests`, [fixed the problem for me on Python 3.4 to 3.6](https://stackoverflow.com/questions/27835619/urllib-and-ssl-certificate-verify-failed-error/38666738#48134650). – hBy2Py Jan 23 '18 at 05:23
  • I was using Python 2.7 after updating Python to 2.7.17 worked like a charm, thank you so much. – happy-integer Apr 16 '21 at 15:51
6

Take a look at

/Applications/Python 3.6/Install Certificates.command

You can also go to the Applications folder in Finder and click on Certificates.command

Kirby
  • 15,127
  • 10
  • 89
  • 104
Danielle Cohen
  • 629
  • 8
  • 5
  • 2
    Thanks a lot for this! I just went to the Applications Folder, found the Python folder, and clicked on the Install Certificates.command file. – TazExprez Jun 03 '22 at 22:36
6

I am surprised all these instruction didn't solved my problem. Nonetheless, the diagnostic is correct (BTW, I am using Mac and Python3.6.1). So, to summarize the correct part :

  • On Mac, Apple is dropping OpenSSL
  • Python now uses it own set of CA Root Certificate
  • Binary Python installation provided a script to install the CA Root certificate Python needs ("/Applications/Python 3.6/Install Certificates.command")
  • Read "/Applications/Python 3.6/ReadMe.rtf" for details

For me, the script doesn't work, and all those certifi and openssl installation failed to fix too. Maybe because I have multiple python 2 and 3 installations, as well as many virtualenv. At the end, I need to fix it by hand.

pip install certifi   # for your virtualenv
mkdir -p /Library/Frameworks/Python.framework/Versions/3.6/etc/openssl
cp -a <your virtualenv>/site-package/certifi/cacert.pem \
  /Library/Frameworks/Python.framework/Versions/3.6/etc/openssl/cert.pem

If that still fails you. Then re/install OpenSSL as well.

port install openssl
jww
  • 97,681
  • 90
  • 411
  • 885
berniey
  • 2,772
  • 1
  • 18
  • 8
6

I have found this over here

I found this solution, insert this code at the beginning of your source file:

import ssl

try:
   _create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
    # Legacy Python that doesn't verify HTTPS certificates by default
    pass
else:
    # Handle target environment that doesn't support HTTPS verification
    ssl._create_default_https_context = _create_unverified_https_context

This code makes the verification undone so that the ssl certification is not verified.

6

The SSL: CERTIFICATE_VERIFY_FAILED error could also occur because an Intermediate Certificate is missing in the ca-certificates package on Linux. For example, in my case the intermediate certificate "DigiCert SHA2 Secure Server CA" was missing in the ca-certificates package even though the Firefox browser includes it. You can find out which certificate is missing by directly running the wget command on the URL causing this error. Then you can search for the corresponding link to the CRT file for this certificate from the official website (e.g. https://www.digicert.com/digicert-root-certificates.htm in my case) of the Certificate Authority. Now, to include the certificate that is missing in your case, you may run the below commands using your CRT file download link instead:

wget https://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt

mv DigiCertSHA2SecureServerCA.crt DigiCertSHA2SecureServerCA.der

openssl x509 -inform DER -outform PEM -in DigiCertSHA2SecureServerCA.der -out DigicertSHA2SecureServerCA.pem.crt

sudo mkdir /usr/share/ca-certificates/extra

sudo cp DigicertSHA2SecureServerCA.pem.crt /usr/share/ca-certificates/extra/

sudo dpkg-reconfigure ca-certificates

After this you may test again with wget for your URL as well as by using the python urllib package. For more details, refer to: https://bugs.launchpad.net/ubuntu/+source/ca-certificates/+bug/1795242

WebDev
  • 1,211
  • 11
  • 17
4

I hang my head in semi-shame, as I had the same issue, except that in my case, the URL I was hitting was valid, the certificate was valid. What wasn't valid was my connection out to the web. I had failed to add proxy details into the browser (IE in this case). This stopped the verification process from happening correctly.
Added in the proxy details and my python was then very happy .

Ads
  • 2,084
  • 2
  • 24
  • 34
  • 3
    Don't hang your head in shame for forgetting something and then figuring it out and sharing, someone might find that useful. Using IE though... shame :p – Davos Mar 08 '18 at 15:58
4

For Python 3.4+ on Centos 6/7,Fedora, just install the trusted CA this way :

  1. Copy the CA.crt to /etc/pki/ca-trust/source/anchors/
  2. update-ca-trust force-enable
  3. update-ca-trust extract
Cherif KAOUA
  • 834
  • 12
  • 21
3

Like you, I am using python 2.7 on my old iMac (OS X 10.6.8), I met the problem too, using urllib2.urlopen :

urlopen error [SSL: CERTIFICATE_VERIFY_FAILED]

My programs were running fine without SSL certificate problems and suddently (after dowloading programs), they crashed with this SSL error.

The problem was the version of python used :

  1. No problem with https://www.python.org/downloads and python-2.7.9-macosx10.6.pkg

  2. problem with the one instaled by Homebrew tool : "brew install python", version located in /usr/local/bin.

A chapter, called Certificate verification and OpenSSL [CHANGED for Python 2.7.9], in /Applications/Python 2.7/ReadMe.rtf explains the problem with many details.

So, check, download and put in your PATH the right version of python.

Noelkd
  • 7,686
  • 2
  • 29
  • 43
3

Python 2.7 on Amazon EC2 with centOS 7

I had to set the env variable SSL_CERT_DIR to point to my ca-bundle which was located at /etc/ssl/certs/ca-bundle.crt

Brian McCall
  • 1,831
  • 1
  • 18
  • 33
  • You're answer led me onto the right track for me. On ubuntu, I had to set `SSL_CERT_DIR` to `/etc/ssl/certs`, and also made sure the `ca-certificates` package was installed and up to date. – Norman Breau Apr 21 '19 at 22:04
  • This worked for me, CentOS Linux release 7.9.2009. I did use `export SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt` instead. As Charlie Burns pointed out, this issue is already discussed in detail in https://access.redhat.com/articles/2039753 – Amin.A May 20 '22 at 01:24
2

Installing PyOpenSSL using pip worked for me (without converting to PEM):

pip install PyOpenSSL
Yannis
  • 1,682
  • 7
  • 27
  • 45
averma93
  • 21
  • 2
2

I had this problem solved by closing Fiddler (an HTTP debugging proxy) check if you have a proxy enabled and try again.

vperezb
  • 373
  • 4
  • 7
2

In my case I was getting this error because requests and urllib3 versions were incompatible, giving the following error during installation:

ERROR: requests 2.21.0 has requirement urllib3<1.25,>=1.21.1, but you'll have urllib3 1.25 which is incompatible.
pip install 'urllib3<1.25' --force-reinstall

did the trick.

fabio.sang
  • 835
  • 8
  • 26
2

Another Anaconda solution. I was getting CERTIFICATE_VERIFY_FAILED in my Python 2.7 environment on macOS. It turns out the conda paths were bad:

base (3.7) environment:

>>> import ssl
>>> ssl.get_default_verify_paths()
DefaultVerifyPaths(cafile='/usr/local/anaconda3/ssl/cert.pem', capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/local/anaconda3/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/local/anaconda3/ssl/certs')

2.7 environment (paths did not exist!):

DefaultVerifyPaths(cafile='', capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/local/anaconda3/envs/py27/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/local/anaconda3/envs/py27/ssl/certs')

The fix:

cd /usr/local/anaconda3/envs/py27/
mkdir ssl
cd ssl
ln -s ../../../ssl/cert.pem
Peter Tseng
  • 13,613
  • 4
  • 67
  • 57
2

There are cases when you can not use insecure connections or pass ssl context into urllib request. Here my solution based on https://stackoverflow.com/a/28052583/6709778

In a case if you want use your own cert file

import ssl

def new_ssl_context_decorator(*args, **kwargs):
    kwargs['cafile'] = '/etc/ssl/certs/ca-certificates.crt'
    return ssl.create_default_context(*args, **kwargs)

ssl._create_default_https_context = ssl._create_unverified_context

or you can use shared file from certifi

def new_ssl_context_decorator(*args, **kwargs):
    import certifi
    kwargs['cafile'] = certifi.where()
    return ssl.create_default_context(*args, **kwargs)
1

In python 2.7 adding Trusted root CA details at the end in file C:\Python27\lib\site-packages\certifi\cacert.pem helped

after that i did run (using admin rights) pip install --trusted-host pypi.python.org --trusted-host pypi.org --trusted-host files.pythonhosted.org packageName

MD5
  • 1,356
  • 15
  • 14
1

Installing certifi on Mac solved my issue:

pip install certifi
Snehal Parmar
  • 5,453
  • 3
  • 35
  • 46
1

I had this problem with Python 2.7.9

Here is what I did:

  • Uninstalled Python 2.7.9
  • Deleted c:\Python27 folder
  • Downloaded Python 2.7.18 which is the latest Python 2.7 release today.
  • Re-run my application
  • And it worked!

There isnt any "[CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)" error anymore.

oyildirim
  • 51
  • 3
1

I was getting the same error, and also went on a wild goose chase for quite a while before I gave up and started trying things on my own. I eventually figured it out, so I thought I'd share. In my case, I am running Python 2.7.10 (due to reasons beyond my control) on Linux, don't have access to the requests module, can't install certificates globally at the OS or Python level, can't set any environment variables, and need to access a specific internal site that uses internally issued certificates.

NOTE: Disabling SSL verification was never an option. I'm downloading a script that immediately runs as root. Without SSL verification, any web server could pretend to be my target host, and I'd just accept whatever they give me and run it as root!

I saved the root and intermediate certificates (there may be more than one) in pem format to a single file, then used the following code:

import ssl,urllib2
data = urllib2.build_opener(urllib2.HTTPSHandler(context=ssl.create_default_context(cafile='/path/to/ca-cert-chain.pem')), urllib2.ProxyHandler({})).open('https://your-site.com/somefile').read()
print(data)

Note that I added urllib2.ProxyHandler({}) there. That's because in our environment proxies are set up by default, but they can only access external sites, not internal ones. Without the proxy bypass, I cannot access internal sites. If you don't have that problem, you can simplify as follows:

data = urllib2.build_opener(urllib2.HTTPSHandler(context=ssl.create_default_context(cafile='/path/to/ca-cert-chain.pem'))).open('https://your-site.com/somefile').read()

Works like a charm, and does not compromise security.

Enjoy!

apresence
  • 310
  • 2
  • 5
1

My solution was to use Beautiful Soup a python package. It magically handles the SSL stuff. Beautiful Soup is a library that makes it easy to scrape information from web pages.

from bs4 import BeautifulSoup as soup
import requests
url = "https://dex.raydium.io/#/market/2xiv8A5xrJ7RnGdxXB42uFEkYHJjszEhaJyKKt4WaLep"
html = requests.get(url, verify=True)
 
page_soup = soup(html.text, 'html.parser')
print(page_soup.prettify())
Bruce Seymour
  • 1,520
  • 16
  • 24
1

You can install the package in python using the below command

In Jupiter notebook

!pip install --trusted-host=pypi.org --trusted-host=files.pythonhosted.org --user [Pacakage name]

!pip install --trusted-host=pypi.org --trusted-host=files.pythonhosted.org --user xgboost

Please note I have tried Install Certificates.command in mac and windows noting helped

RVK
  • 473
  • 1
  • 5
  • 16
1

Solution for M1 MacOS

(Where python was installed with homebrew)

  1. To investigate which paths are used to lookup SSL cerficates. Run this Python code:
import ssl
ssl.get_default_verify_paths()

For me this returned:

DefaultVerifyPaths(cafile=None, capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/opt/local/libexec/openssl3/etc/openssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/opt/local/libexec/openssl3/etc/openssl/certs')

This was incorrect.

  1. Re-install OpenSSL
brew uninstall --ignore-dependencies openssl && brew install openssl

Look at the output of the above command. Here I saw the correct paths for cert.pem and the certs folder (used in step 3).

  1. Make your system aware of the correct paths. Set the following environment variables:
export SSL_CERT_FILE=/opt/homebrew/etc/openssl@3/cert.pem
export SSL_CERT_DIR=/opt/homebrew/etc/openssl@3/certs

(Add these lines to your .profile file to set the variables permanently)

Tom O
  • 2,495
  • 2
  • 19
  • 23
0

If your on vCenter 6, you should instead add your vCenter's vmware certificate authority cert to your OS's list of trusted CA's. To download your cert do the following

  1. Open your Web browser.
  2. Navigate to https://
  3. In the lower right-hand corner, click the Download Trusted Root CA link

On Fedora

  1. unzip and change the extension from .0 to .cer
  2. Copy it to the /etc/pki/ca-trust/source/anchors/
  3. run the update-ca-trust command.

Links:

  1. https://virtualizationreview.com/articles/2015/04/02/install-root-self-signed-certificate-vcenter-6.aspx?m=1
  2. http://forums.fedoraforum.org/showthread.php?t=293856
0

Try

pip install --trusted-host pypi.python.org packagename

It worked for me.

0

installing steps for nltk (I had python3 (3.6.2) installed already in MAC OS X

sudo easy_install pip

use ignore installed option to ignore uninstalling previous version of six, else, it gives an error while uninstalling and does not movie forward

sudo pip3 install -U nltk --ignore-installed six

Check the installation of pip and python, use the '3' versions

which python python2 python3
which pip pip2 pip3

Check if NLTK is installed

python3
import nltk
nltk.__path__
['/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/nltk']

Install SSL certificate prior to installing the examples book, else we will certificate error while installing the examples

/Applications/Python\ 3.6/Install\ Certificates.command
python3 -m nltk.downloader book

That completed the installation successfully of nltk and nltk_ata for book examples

Community
  • 1
  • 1
0

For anyone using mechanize who comes across this question, here's how you can apply the same technique to a mechanize Browser instance:

br = mechanize.Browser()
context = ssl._create_unverified_context()
br.set_ca_data(context=context)
Kirkman14
  • 1,506
  • 4
  • 16
  • 30
0

For Linux Python3.6, this worked for me.

from command line install pyopenssl and certifi

sudo pip3 install -U pyopenssl
sudo pip3 install certifi

and in my python3 script, added verify='/usr/lib/python3.6/site-packages/certifi/cacert.pem' like this:

import requests
from requests.auth import HTTPBasicAuth
import certifi

auth = HTTPBasicAuth('username', 'password')
body = {}

r = requests.post(url='https://your_url.com', data=body, auth=auth, verify='/usr/lib/python3.6/site-packages/certifi/cacert.pem')
Joe Jadamec
  • 156
  • 1
  • 8
0

Already lots of answers here, but we ran into this in a very specific case and blew a lot of time investigating, so adding yet another one. We saw it in the following case:

  • In a debian-stretch-slim docker container
  • Default Python 3.5.3 easy_install3
  • For LetsEncrypt certificates registered using cert-manager in our Kubernetes cluster

pip3 and openssl command line were both able to verify the cert and easy_install3 was able to verify other LetsEncrypt certs successfully.

The workaround was to build the latest Python (3.7.3 at the time) from source. The instructions here are detailed and easy to follow.

aschmied
  • 908
  • 2
  • 10
  • 26
0

If you have private certs to deal with, like your orgs own CA root and intermediates part of the chain, then better to add the certs to the ca file viz. cacert.pem than bypassing the entire security apparatus (verify=False). Below code gets you going in both 2.7+ and 3+

Consider adding the whole cert chain and off course you need to do this only once.

import certifi

cafile=certifi.where() # cacert file
with open ('rootca.pem','rb') as infile:
    customca=infile.read()
    with open(cafile,'ab') as outfile:
        outfile.write(customca)
with open ('interca.pem','rb') as infile:
    customca=infile.read()
    with open(cafile,'ab') as outfile:
        outfile.write(customca)
with open ('issueca.pem','rb') as infile:
    customca=infile.read()
    with open(cafile,'ab') as outfile:
        outfile.write(customca)

Then this should get you going

import requests
response = requests.request("GET", 'https://yoursecuresite.com',  data = {})
print(response.text.encode('utf8'))

Hope this helps

Ajit Surendran
  • 709
  • 7
  • 4
0

import request
response = requests.get("url/api that you want to hit", verify="path to ssl certificate")

For me the problem was that none of the above answers completely helped me but gave me the right direction to look at.

For sure, SSL certificate is needed but when you are behind the company's firewall then publicly available certificates might not help. You might need to reach out to the IT department of your company to obtain the certificate as each company uses special certificate from the security provider they have contracted the services from. And place it in a folder and pass the path to that folder as an argument to verify parameter.

For me even after trying all the above solutions and using the wrong certificate I was not able to make it work. So just remember for those who are behind company's firewall to obtain the right certificate. It can make a difference between success and failure of your request call.

In my case I placed the certificate in the following path and it worked like magic.

C:\Program Files\Common Files\ssl

You could also refer https://2.python-requests.org/en/master/user/advanced/#id3 which talks about ssl verification

Harpreet
  • 165
  • 1
  • 8
0

If the certificate is issued through Let's encrypt make sure to remove the expired DST Root CA X3 issued R3 certificate in your Intermediate cert store on the client.

sevenam
  • 592
  • 1
  • 8
  • 21
0

The problem could be due to expired SSL certificates. On CentOS Linux, I got it resolved by upgrading ca-certificates package:

yum upgrade ca-certificates
S.V
  • 2,149
  • 2
  • 18
  • 41
0

I had that problem while trying to read .pdf files, it was fixed with verify=False in response = requests.get(pdf_url, verify=False) But this is only safe if the server is trusted

Julian
  • 56
  • 5
-7

ln -s /usr/local/share/certs/ca-root-nss.crt /etc/ssl/cert.pem

(FreeBSD 10.1)

  • 10
    I'm writing as a reviewer. Would you please add some words of explanation for your answer. Otherwise, your answer may be subject to deletion. – Bill Bell Mar 13 '17 at 19:29