Pip install fails: SSL required

Just an easy_install rsa==3.1.1 will do the job.


Solution: Upgrade to the latest version of your library.

It all starts here, suddenly(on Oct-2017) the Distutils team decided to revoke support for non-https requests without worrying about breaking the backward compatibility of earlier versions of numerous python libraries. Bit unprofessional, but hey it's Python world.

So here is the fix, Simply move on to the latest version of the library (rsa==3.4.2 in my case) on whatever library (nltk==3.2.5 etc)

Alternate Solution: Fork(or locally copy) the version of repo & modify the http url into https

Nonetheless, watch out if you are doing this while maintaining another project since the dependency you are upgrading might not be compatible with the original library the author had intended, for example in my context rsa was used under another library as a dependency. Thus the solution was to upgrade the parent library so that this issue is automatically taken care.


The accepted answer did not work in my case (on an elder Raspbian), but providing the download URL with the command helped me as described in this post:

sudo pip install paho-mqtt -i https://pypi.python.org/simple

Unfortunately none of the previous answers work for me.

IMHO it was very stupid pip / distutils chose to break packages on http repos.

I think a better choice would have been:

  • pip/distutils use https by default

  • in case of error, like 403, pip has to suggest you "the package repo is on http, do you want to download it?"

Still in 2020 many Python 2 packages are on http repos; with their decision, the installation of these packages is broken.


The working solution for me is a very simple patch of one python core modules:

--- /usr/local/lib/python2.7/urllib2.py.original
+++ /usr/local/lib/python2.7/urllib2.py
@@ -427,6 +427,9 @@
             req = meth(req)

         response = self._open(req, data)
+        if protocol == "http" and response.code == 403 :
+            if isinstance(fullurl, basestring) and fullurl.startswith("http://pypi.python.org/packages/source/d/distribute/") :
+                return    self.open(fullurl.replace("http://", "https://"), data = data, timeout = timeout)

         # post-process response
         meth_name = protocol+"_response"

Working: if the failed url is on http, retry on https.

I know it is a little ugly, but it is very clear and also you can revert to the original module in a snap (make a copy of /usr/local/lib/python2.7/urllib2.py before to apply this patch).