UrbKr
UrbKr

Reputation: 663

Python HTTPS request SSLError CERTIFICATE_VERIFY_FAILED

PYTHON

import requests

url = "https://REDACTED/pb/s/api/auth/login"

r = requests.post(
    url,
    data = {
        'username': 'username',
        'password': 'password'
    }
)

NIM

import httpclient, json

let client = newHttpClient()

client.headers = newHttpHeaders({ "Content-Type": "application/json" })
let body = %*{
    "username": "username",
    "password": "password"
}

let resp = client.request("https://REDACTED.com/pb/s/api/auth/login", httpMethod = httpPOST, body = $body)

echo resp.body

I'm calling an API to get some data. Running the python code I get the traceback below. However, the nim code works perfectly so there must be something wrong with the python code or setup.

I'm running Python version 2.7.15. requests lib version 2.19.1

Traceback (most recent call last):
  File "C:/Python27/testht.py", line 21, in <module>
    "Referer": "https://REDACTED.com/pb/a/"
  File "C:\Python27\lib\site-packages\requests\api.py", line 112, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "C:\Python27\lib\site-packages\requests\api.py", line 58, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Python27\lib\site-packages\requests\sessions.py", line 512, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Python27\lib\site-packages\requests\sessions.py", line 622, in send
    r = adapter.send(request, **kwargs)
  File "C:\Python27\lib\site-packages\requests\adapters.py", line 511, in send
    raise SSLError(e, request=request)
SSLError: HTTPSConnectionPool(host='REDACTED.com', port=443): Max retries exceeded with url: /pb/s/api/auth/login (Caused by SSLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:726)'),))

Upvotes: 0

Views: 1042

Answers (2)

Steffen Ullrich
Steffen Ullrich

Reputation: 123340

However, the nim code works perfectly so there must be something wrong with the python code or setup.

Actually, your Python code or setup is less to blame but instead the nim code or better the defaults on the httpclient library. In the documentation for nim can be seen that httpclient.request uses a SSL context returned by getDefaultSSL by default which according to this code creates a context which does not verify the certificate:

proc getDefaultSSL(): SSLContext =
  result = defaultSslContext
  when defined(ssl):
    if result == nil:
      defaultSSLContext = newContext(verifyMode = CVerifyNone)

Your Python code instead attempts to properly verify the certificate since the requests library does this by default. And it fails to verify the certificate because something is wrong - either with your setup or the server.

It is unclear who has issued the certificate for your site but if it is not in your default CA store you can use the verify argument of requests to specify the issuer CA. See this documentation for details.

If the site you are trying to access works with the browser but fails with your program it might be that it uses a special CA which was added as trusted to the browser (like a company certificate). Browsers and Python use different trust stores so this added certificate needs to be added to Python or at least to your program as trusted too. It might also be that the setup of the server has problems. Browsers can sometimes work around problems like a missing intermediate certificate but Python doesn't. In case of a public accessible site you could use SSLLabs to check what's wrong.

Upvotes: 1

wholevinski
wholevinski

Reputation: 3828

The requests module will verify the cert it gets from the server, much like a browser would. Rather than being able to click through and say "add exception" like you would in your browser, requests will raise that exception.

There's a way around it though: try adding verify=False to your post call.

Upvotes: 1

Related Questions