While trying to make a GET request from inside python3 on my Macbook I ran into this:

error: ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:600)

After doing a lot of reading of incomplete or incorrect blogs, this is how I fixed it.


I was writing some python code that made a GET request using the popular requests framework.  When I tried to run it I was given a strange error:

error: ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:600)

I’ve used requests with success before so this seemed odd.  I wrote the following quick python script to see if I could reproduce the error:

import requests

def main():
    r = requests.get("https://jsonplaceholder.typicode.com/posts/1")
    print("Response: {c} Text: {t}".format(c=r.status_code, t=r.text))

if __name__ == '__main__':

To run this I brought up a virtual environment (running python 3.5) and did a:

(testvenv)$ pip install requests
(testvenv)$ python test.py
... stack trace ...
error: ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:600)

The problem was confirmed and repeatable. After doing some reading I discovered that Mac OSX comes preloaded with a fairly old version of open ssl.  I confirmed this by:

$ openssl version
OpenSSL 0.9.8zg 14 July 2015

According to the openssl website they recommend LTS version 1.0.2.  0.9.8 is, indeed, out of date.


Reading more about this lead me to a blog post on comeroutewithme.com which had a possible solution. So I followed along:

$ brew update
$ brew install openssl
$ openssl version
OpenSSL 0.9.8zg 14 July 2015

$ brew link --force openssl
Warning: Refusing to link: openssl
Linking key-only openssl means you may end up linking against the insecure,
deprecated system OpenSSL while using the headers from Homebrew's openssl.
Instead, pass the full include/library paths to your compiler e.g.:

So much for that! Some more reading lead me to @zlwaterfield’s  medium post  which claimed I needed to manually link the new version of ssl. However @zlwaterfield tells us to symlink to: /usr/local/Cellar/{version}/include/openssl which is incorrect, the correct location is: /usr/local/Cellar/{version}/bin/openssl. So I tried to update my openssl symlink via:

 $ sudo ln -s -f /usr/local/Cellar/{version}/bin/openssl /usr/bin/openssl 

the -f flag should overwrite the current symlink but it did’t for me so:

$ unlink /usr/bin/openssl
$ sudo ln -s /usr/local/Cellar/{version}/bin/openssl /usr/bin/openssl 
$ openssl version
OpenSSL 1.0.2e 3 Dec 2015

Great! openssl is now the correct version, but when check the python version of ssl I get:

$ python3
Python 3.5.1 (v3.5.1:37a07cee5969, Dec 5 2015, 21:12:44)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>import ssl
'OpenSSL 0.9.8zg 14 July 2015'

Not cool! But now I can continue on from the first blog:

$ brew install python --with-brewed-openssl

but that updates it for python 2.7 not python 3… testing this confirmed that my python ssl version was still old. So:

$ brew install python3 --with-brewed-openssl

This produced a warning that brew did not want to overwrite my symlinks, so:

$ brew link --overwrite python3

This updated my python version from 3.5 to 3.6 so I had to update my path if I want the python3 command to point to 3.6:

export PATH

Now the python3 command points to python 3.6:

$ python3
Python 3.6.3 (default, Oct 27 2017, 10:40:32) 
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
'OpenSSL 1.0.2l 25 May 2017'

Nice!! Now all I needed to do was rebuild my virtual environment around my test file and:

(newtestvenv)$ pip install requests
(newtestvenv)$ python test.py
Response: 200 Text: {
 "userId": 1,
 "id": 1,
 "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
 "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"

Success!  This took far too long and I got no proper work done this morning, but I shouldn’t run into this problem ever again.  Hopefully, this blog will help someone else get through this faster.