Search code examples
pythonhttpspython-requests

How do I disable the security certificate check in Python requests


I am using

import requests
requests.post(url='https://foo.example', data={'bar':'baz'})

but I get a request.exceptions.SSLError. The website has an expired certficate, but I am not sending sensitive data, so it doesn't matter to me. I would imagine there is an argument like 'verifiy=False' that I could use, but I can't seem to find it.


Solution

  • From the documentation:

    requests can also ignore verifying the SSL certificate if you set verify to False.

    >>> requests.get('https://kennethreitz.com', verify=False)
    <Response [200]>
    

    If you're using a third-party module and want to disable the checks, here's a context manager that monkey patches requests and changes it so that verify=False is the default and suppresses the warning.

    import warnings
    import contextlib
    
    import requests
    from urllib3.exceptions import InsecureRequestWarning
    
    old_merge_environment_settings = requests.Session.merge_environment_settings
    
    @contextlib.contextmanager
    def no_ssl_verification():
        opened_adapters = set()
    
        def merge_environment_settings(self, url, proxies, stream, verify, cert):
            # Verification happens only once per connection so we need to close
            # all the opened adapters once we're done. Otherwise, the effects of
            # verify=False persist beyond the end of this context manager.
            opened_adapters.add(self.get_adapter(url))
    
            settings = old_merge_environment_settings(self, url, proxies, stream, verify, cert)
            settings['verify'] = False
    
            return settings
    
        requests.Session.merge_environment_settings = merge_environment_settings
    
        try:
            with warnings.catch_warnings():
                warnings.simplefilter('ignore', InsecureRequestWarning)
                yield
        finally:
            requests.Session.merge_environment_settings = old_merge_environment_settings
    
            for adapter in opened_adapters:
                try:
                    adapter.close()
                except:
                    pass
    

    Here's how you use it:

    with no_ssl_verification():
        requests.get('https://wrong.host.badssl.example/')
        print('It works')
    
        requests.get('https://wrong.host.badssl.example/', verify=True)
        print('Even if you try to force it to')
    
    requests.get('https://wrong.host.badssl.example/', verify=False)
    print('It resets back')
    
    session = requests.Session()
    session.verify = True
    
    with no_ssl_verification():
        session.get('https://wrong.host.badssl.example/', verify=True)
        print('Works even here')
    
    try:
        requests.get('https://wrong.host.badssl.example/')
    except requests.exceptions.SSLError:
        print('It breaks')
    
    try:
        session.get('https://wrong.host.badssl.example/')
    except requests.exceptions.SSLError:
        print('It breaks here again')
    

    Note that this code closes all open adapters that handled a patched request once you leave the context manager. This is because requests maintains a per-session connection pool and certificate validation happens only once per connection so unexpected things like this will happen:

    >>> import requests
    >>> session = requests.Session()
    >>> session.get('https://wrong.host.badssl.example/', verify=False)
    /usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
      InsecureRequestWarning)
    <Response [200]>
    >>> session.get('https://wrong.host.badssl.example/', verify=True)
    /usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
      InsecureRequestWarning)
    <Response [200]>