41

Every time I try to do:

requests.get('https://url') 

I got this message:

import requests
>>> requests.get('https://reviews.gethuman.com/companies') 
Traceback (most recent call last): 
   File "<stdin>", line 1, in <module> 
   File "/usr/lib/python2.7/dist-packages/requests/api.py", line 55, in get 
    return request('get', url, **kwargs) 
   File "/usr/lib/python2.7/dist-packages/requests/api.py", line 44, in request 
    return session.request(method=method, url=url, **kwargs)    
   File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 455, in request 
    resp = self.send(prep, **send_kwargs) 
   File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 558, in send 
    r = adapter.send(request, **kwargs) 
   File "/usr/lib/python2.7/dist-packages/requests/adapters.py", line 385, in send 
    raise SSLError(e) requests.exceptions.SSLError: [Errno 1]
_ssl.c:510: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure

I tried everything:

  • update my requests
  • update my ssl

but nothing changes.

I am using Python 2.7.6, can't change this.

the
  • 21,007
  • 11
  • 68
  • 101
Idan Haim Shalom
  • 1,234
  • 1
  • 11
  • 19
  • Looks like you have to force sslv3 use when call request. See http://stackoverflow.com/questions/22857889/ssl-error-using-python-requests-to-access-shibboleth-authenticated-server for more detail. – Bestasttung Jul 27 '15 at 09:52
  • Do you have the problem for every https url you try or one in particular? I tried ```requests.get('https://reviews.gethuman.com/companies')``` and had no problem – Bestasttung Jul 27 '15 at 09:56
  • is that the actual url you are using? – Emmy R Jul 27 '15 at 20:16
  • yes this is the actual url nothing special .I had the problem in every https i am trying to get its seems that updating my ubuntu fix the problem but I dont know why yet – Idan Haim Shalom Jul 28 '15 at 14:01

9 Answers9

51

On OSX, using python 2.7.10 / requests 2.9.1 I only had to to install requestsusing its security setup:

pip install requests[security]

This installs pyOpenSSL, ndg-httpsclient and pyasn1. https://github.com/kennethreitz/requests/blob/master/setup.py#L70

Tobias Lorenz
  • 1,426
  • 11
  • 17
  • 1
    Installing `requests` using its security setup also seems to work on Windows, thanks! – Steffen Opel Feb 05 '16 at 01:33
  • I had to upgrade pip before I could do this, but it worked on OS X 10.5. – e.barojas Mar 08 '17 at 19:35
  • 1
    This solved the problem for me with Python 3.5.3 and requests 2.18.4 on Debian 9.2 (stretch). Thanks for the tip! – René Pijl Nov 06 '17 at 11:06
  • didn't work for me for a specific site: python Successfully installed asn1crypto-0.24.0 cffi-1.11.5 cryptography-2.3.1 enum34-1.1.6 ipaddress-1.0.22 pyOpenSSL-18.0.0 pycparser-2.19 Python 2.7.15 (default, Jun 17 2018, 12:46:58) [GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.2)] on darwin – Hvisage Oct 25 '18 at 05:19
39

I resolve the problem in the end i updated my ubuntu from 14.04 to 14.10 and the problem was solved

but in the older version of ubuntu and python I install those lib and it seems to fix all my problems

sudo apt-get install python-dev libssl-dev libffi-dev
sudo pip2.7 install -U pyopenssl==0.13.1 pyasn1 ndg-httpsclient

if you don`t have pip2.7 installed you can use pip instead

Idan Haim Shalom
  • 1,234
  • 1
  • 11
  • 19
12

If you are not able to upgrade your Python version to 2.7.9 then downgrade you requests package to 2.5.3. That worked for me.

sudo pip install requests==2.5.3

Edit

You can also install requests with security extension

pip install requests[security]
Hassan Raza
  • 3,025
  • 22
  • 35
  • Unfortunately, downgrading requests is the only solution that worked for me. requests==2.11.1 is the last version with which I don't get this error. 2.12 starts throwing the error. – newlog Jan 08 '18 at 16:09
  • 1
    This seems to work for me as well. I'm using python 2.7.6 on linux mint Rebecca – stingMantis Jun 04 '18 at 01:31
8
import requests

#Add support for all cipher suites
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS='ALL'
#Exclude use of pyopenssl (pyopenssl module may need to be installed first $pip install pyopenssl)
requests.packages.urllib3.contrib.pyopenssl.extract_from_urllib3()
Amr
  • 2,045
  • 14
  • 17
4

I am using python 2.7.6 cant change it.

Sorry for you then. The server you are trying to reach requires (SNI) Server Name Indication and will cause a handshake failure if the client is not using this SNI extension.. Support for SNI was only added with python 2.7.9 so it looks like you are out of luck.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Didn't dv, but isn't this possible by installing the `[security]` extensions of requests, and therefore you can still support SNI in 2.7.6? – jonnybazookatone Jun 15 '16 at 15:01
  • @jonnybazookatone: might be but it is not really documented and maybe it also has some unexpected side effects (again, missing detailed documentation). – Steffen Ullrich Jun 15 '16 at 15:59
  • True. There is conflicting documentation on requests that says there is no support: http://docs.python-requests.org/en/master/community/faq/ for <2.7.9. Yet, in the urllib3 docs it is fine for `python2.6` and `python2.7.0-2.7.8`: http://urllib3.readthedocs.io/en/latest/security.html. However, this PR on requests seems to show SNI is fine: https://github.com/kennethreitz/requests/pull/1347. – jonnybazookatone Jun 15 '16 at 16:10
  • In fact, clicking on the SO question on the requests docs points to the requests PR that includes SNI for 2.6-3. I think it'd be safe to say it works. – jonnybazookatone Jun 15 '16 at 16:17
  • @jonnybazookatone: yes, it will probably work but since the implementation is no longer on top of ssl.py but on top of pyOpenSSL there might be unexpected behavior differences. – Steffen Ullrich Jun 15 '16 at 16:38
  • It'd be great if you could update your answer to include this information, as it lead me to what I wanted -- the down vote is misleading. – jonnybazookatone Jun 15 '16 at 16:44
  • @jonnybazookatone: there is already a highly voted answer on this question which covers this case, so no need to alter my answer after a year. – Steffen Ullrich Jun 15 '16 at 17:15
  • Fair enough. The highly voted answer has no context, and no explanation why it works, just a "fix". Thx anyway. – jonnybazookatone Jun 15 '16 at 17:18
4

after trying all the above solutions and going down quite the rabbit hole, the thing that eventually cracked the case was simply trying to import pyopenssl from the urllib3 package like so:

from urllib3.contrib import pyopenssl

which led me right to the error (missing the cryptography package)

Bobby
  • 6,840
  • 1
  • 22
  • 25
  • simply installing the `cryptography` package solved the problem, but I was only able to see that this was the issue by attempting the `pyopenssl` import – Bobby Jan 02 '17 at 21:00
  • added 'from urllib3.contrib import pyopenssl' to source, then i tried debug code, then i got the error " ImportError: No module named ndg.httpsclient.ssl_peer_verification" , then i installed ndg.httpsclient using 'sudo pip install pyasn1 ndg-httpsclient ' , that solved the problem for me – user3826306 Jan 17 '18 at 15:51
2

I kept getting this error message when connecting to an old website with obsolete HTTPS.

In the end I had to set the Protocol AND the Ciphers manually with an adapter for the request to work.

What worked for me -

  1. go to a diagnostics site like this one https://www.ssllabs.com/ssltest/analyze.html
  2. find out what protocol the website uses (TLS1.0, TLS1.2, SSL3.0 (only?) ....)
  3. find out what obsolete ciphers suite are used
  4. from 3) translate cipher name to the the openssl name from a list like https://www.openssl.org/docs/man1.1.0/apps/ciphers.html or http://testssl.sh/openssl-rfc.mapping.html to use in code

then in requests create an adapter with what you have researched above

import requests, ssl
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
from requests.packages.urllib3.util import ssl_

class OldInsecureWebsiteAdapter(HTTPAdapter):
    def __init__(self, **kwargs):
        super(OldInsecureWebsiteAdapter, self).__init__(**kwargs)
    def init_poolmanager(self, *pool_args, **pool_kwargs):
        """
        my website uses TLS1.0 ONLY (from step 2) 
        and several obsolete ciphers (from step 3/4 I only picked one)
        """
        context = ssl_.create_urllib3_context(ssl.PROTOCOL_TLSv1, ciphers="DES-CBC3-SHA")

        """
        website does not support anything else so exclude all other protocols
        """
        context.options |= ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_3 | ssl.OP_NO_TLSv1_2 
        context.options |= ssl.OP_NO_SSLv3 | ssl.OP_NO_SSLv2

        self.poolmanager = PoolManager(*pool_args,
                                   ssl_context=context,
                                   **pool_kwargs)

now I mount the adapter to the requests object

    url = "https://yourwebsite.gov.whocares"
    session = requests.session()
    session.mount(url, OldInsecureWebsiteAdapter())
    result = session.get(url) 
    #no more ssl3 handshake error...
uosjead
  • 426
  • 6
  • 5
2

Running python 2.7.13. I tried the recommended solutions here, which ended up installing the following:

  • pip install requests[security] (installed asn1crypto-0.24.0 cffi-1.11.5 cryptography-2.4.2 idna-2.7 ipaddress-1.0.22 ndg-httpsclient-0.5.1 pyOpenSSL-18.0.0 pyasn1-0.4.4 pycparser-2.19)

no help, then tried

  • pip install -U requests (installed certifi-2018.10.15 chardet-3.0.4 requests-2.20.1 urllib3-1.24.1)

no help. Finally tried

  • pip install -U httplib2 (httplib2-0.12.0)

which resolved the problem. Previously I was running httplib2==0.9.2

Lou K
  • 1,128
  • 2
  • 12
  • 31
-2

You just need to upgrade your requests.

pip install requests --upgrade

You can still use python 2.7.