25

I am using Python 3.7.3 to run a GET request to a PHP file hosted on my website. However, when I run it I receive the error below. I have installed requests through pip3 on Homebrew. I am using macOS Mojave.

Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", line 600, in urlopen chunked=chunked)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", line 343, in _make_request self._validate_conn(conn)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", line 839, in _validate_conn conn.connect()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connection.py", line 344, in connect ssl_context=context)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/util/ssl_.py", line 344, in ssl_wrap_socket
return context.wrap_socket(sock, server_hostname=server_hostname)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 412, in wrap_socket session=session
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 853, in _create self.do_handshake()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 1117, in do_handshake self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/adapters.py", line 449, in send timeout=timeout
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", line 638, in urlopen _stacktrace=sys.exc_info()[2])
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/util/retry.py", line 398, in increment raise MaxRetryError(_pool, url, error or ResponseError(cause)) urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='ijetlab.com', port=443): Max retries exceeded with url: /api/api.php?one=1&two=2 (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Users/maxwellnewberry/Documents/test.py", line 12, in r = requests.get(url = URL, params = PARAMS)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/api.py", line 75, in get return request('get', url, params=params, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/api.py", line 60, in request return session.request(method=method, url=url, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/sessions.py", line 533, in request resp = self.send(prep, **send_kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/sessions.py", line 646, in send r = adapter.send(request, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/adapters.py", line 514, in send raise SSLError(e, request=request) requests.exceptions.SSLError: HTTPSConnectionPool(host='ijetlab.com', port=443): Max retries exceeded with url: /api/api.php?one=1&two=2 (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)')))

Here is the code:

# importing the requests library 
import requests 

# api-endpoint 
URL = "https://ijetlab.com/api/api.php"


# defining a params dict for the parameters to be sent to the API 
PARAMS = {'one':1, 'two':2} 

# sending get request and saving the response as response object 
r = requests.get(url = URL, params = PARAMS) 

# extracting data in json format 
data = r.json()

print(data['response'])

All searches have told me to run 'Install Certificates.command', and I have – about 100 times. I have also made the customer install certificates as well.

1
  • 5
    ijetlab.com is not sending the chain cert(s) (at least 1, maybe 2) as required. The best solution is to fix the server. If you can't, it is possible to (manually) get the chain and either put it in the truststore/cafile python uses by default, which you shouldn't if that is managed (e.g. by certifi), or build your own custom truststore and use it for your requests. Commented Apr 17, 2019 at 7:13

4 Answers 4

26

TL;DR

The remote website seems to be the problem, not Python. There is likely no fix for this other than to fix the website.

Longer Explanation

The website/server your are dealing with is apparently configured incorrectly. This has nothing directly to do with Python. That said, you can ignore any certificate errors with e.g.:

r = requests.get(url=URL, params=PARAMS, verify=False)

or you can otherwise try to point Python at the missing certificates (as pointed out by @dave_thompson_085 in the comments).

However, this is unlikely to do any good as the server then apparently responds with a 500: Internal Server Error (verified with curl) and a Content-Length: 0, which would seem to indicate an error in the processing of api.php itself (i.e. there is no JSON to process anyway).

2
  • Awesome! It worked for me
    – XpressGeek
    Commented Jan 31, 2021 at 7:02
  • Glad to hear it. =) Commented Jan 31, 2021 at 13:27
4

If you are working within a corporate environment that decrypts your traffic, or possibly proxy servers as part of a VPN, then I have found that the certifi library fails to include the certificate for the decryption server in the certificate package. This leaves you with only 1 good solution, 1 mediocre solution, and 1 bad solution. The bad solution is to not verify the certificates. The mediocre solution is to ask your IT department to whitelist the website you are trying to contact, but you will have to ask them over and over again for every new website you try to contact.

There is a pretty good article on this issue by David Tippet at the following link. https://levelup.gitconnected.com/fixing-your-ssl-verify-errors-in-python-71c2201db4b2

So, what is the good solution? You will have to start by finding someone in your IT department who can give you the URL or IP address for your SSL decryption server, or you can ask them to give you the .pem file in a base64 format for the server. This is a clear text human readable file, and looks something like this:

Certificate example

It will have a 7 lines starting with a comment #, a line that says -----BEGIN CERTIFICATE-----, and a line that ends as -----END CERTIFICATE-----.

Open up your python environment and check to see if you have certifi with the command:

import certifi

Then find out where the chain of certificates is on your computer that Python is using with

certifi.where()

Navigate to the file path returned by certifi.where() and make a copy of that file in case you break something. Mine was located here:

'C:\Users\user_name\Anaconda3\envs\gispy\lib\site-packages\certifi\cacert.pem'

Open up that .txt file and copy and paste the entire certificate for your proxy/decryption server to the end of the cacert.pem file. Now your requests call should work.

1

I don't think the server is necessarily the problem. I'm doing something similar, but my first two lines are the following.

import pandas as pd

BCD = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer/breast-cancer.data')

I'm doing this simultaneously on MacBook Pro with Mojave 10.14.6 and a Microsoft Surface with Windows 10 Enterprise, 10.0.17134, both using Jupyter. My Python installation is 3.7.3 on both.

Both are accessing the Internet through the same home Wi-Fi.

The Surface grabbed it on the first try. The MacBook gives me the same error as the OP.

So, it's really not likely that the UCI database's server is the problem.

2
  • Apologies. Perhaps I was a bit unclear in my original answer. _ssl.c:1056 is a generic error. I never meant to imply that a server problem is the only reason that this issue appears. It could be caused by something as simple as having the wrong date on a system. That said, at the time that the original answer was written, there was clearly an issue with the remote server (which is in Illinois, not California) which had nothing to do with Python. Commented Sep 29, 2019 at 23:06
  • And just as an FYI, since you are having issues on Mac and Windows works fine, it is probably more likely that Python is having trouble with your local certificates/Trust Store. But again, that isn't definitive. Commented Sep 29, 2019 at 23:20
1

In our case the issue was related to SSL certificates signed by own CA Root & Intermediate certificates. The solution was - after finding out the location of the certifi's cacert.pem file (import certifi; certifi.where()) - was to append the own CA Root & Intermediates to the cacert.pem file. Of course, those own certificates were in PEM format.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .