pythoncurlhttpspython-requestsbearer-token

HTTPS GET with API Bearer Token: working with cURL but not with Python requests.get


When I launch the following cURL command on a https URL with an API token, I get the expected response (a list of files in my storage): curl -H "Authorization: Bearer <TOKEN>" "https://my_website.com:443/api/storage".

However, when I try with requests.get in Python:

url = "https://my_website.com:443/api/storage"
token = "..."
headers = {'Authorization': f"Bearer {token}"}

resp = requests.get(url, headers=headers)
resp.json()

I have an authentication error as follows:

---------------------------------------------------------------------------
SSLCertVerificationError                  Traceback (most recent call last)
File c:\AnsysDev\Python311\Lib\site-packages\urllib3\connectionpool.py:467, in HTTPConnectionPool._make_request(self, conn, method, url, body, headers, retries, timeout, chunked, response_conn, preload_content, decode_content, enforce_content_length)
    466 try:
--> 467     self._validate_conn(conn)
    468 except (SocketTimeout, BaseSSLError) as e:

...

File c:\AnsysDev\Python311\Lib\site-packages\requests\adapters.py:517, in HTTPAdapter.send(self, request, stream, timeout, verify, cert, proxies)
    513         raise ProxyError(e, request=request)
    515     if isinstance(e.reason, _SSLError):
    516         # This branch is for urllib3 v1.22 and later.
--> 517         raise SSLError(e, request=request)
    519     raise ConnectionError(e, request=request)
    521 except ClosedPoolError as e:

SSLError: HTTPSConnectionPool(host='my_website.com', port=443): Max retries exceeded with url: /api/storage (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1006)')))

Why is the behavior different?

I tried to add parameter allow_redirects=False, allow_redirects=True (also it is the default), and I tried setting the token with a requests.Session (see below) but they all lead to the same error:

session = requests.Session()
session.headers.update(headers)
response = session.get(url)
response.json()

Solution

  • Based on the traceback of your call to requests.get, it appears that it is an error of verification of certification (SSLCertVerificationError) probably because of the certification in your website uses a self-signed SSL certificate ([SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain).

    To solve the issue, you can call with argument verify=False:

    resp = requests.get(url, headers=headers, verify=False)
    resp.json()
    

    You will then probably see the warning: InsecureRequestWarning: Unverified HTTPS request is being made to host 'my_website.com'. Adding certificate verification is strongly advised..

    To disable it, you can use the following command from urllib3:

    import urllib3
    
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    

    If you want to disable this warning just at the level of your call, you can do instead:

    url = "https://my_website.com:443/api/storage"
    token = "..."
    headers = {'Authorization': f"Bearer {token}"}
    
    with urllib3.warnings.catch_warnings():
        urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
        resp = requests.get(url, headers=headers, verify=False)
    
    json_data = resp.json()
    

    Related issues: