In order to make the requests library use a custom ssl context, you need to create a custom HTTPAdapter class and override the init_poolmanager method to pass in extra arguments to the base class's implementation.

See sample code here:

from requests import Session
from requests.adapters import HTTPAdapter
import ssl


class CustomHTTPAdapter(HTTPAdapter):

    def init_poolmanager(self, *args, **kwargs):
        # this creates a default context with secure default settings,
        # which enables server certficiate verification using the
        # system's default CA certificates
        context = ssl.create_default_context()

        # alternatively, you could create your own context manually
        # but this does NOT enable server certificate verification
        # context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)

        super().init_poolmanager(*args, **kwargs, ssl_context=context)


def main():
    client_session = Session()
    client_session.mount("https://", CustomHTTPAdapter())

    # now you can use the client_session to make requests
    # r = client_session.get("https://<web address>/rest/info?f=json")
Answer from Joe Savage on Stack Overflow
Top answer
1 of 2
6

In order to make the requests library use a custom ssl context, you need to create a custom HTTPAdapter class and override the init_poolmanager method to pass in extra arguments to the base class's implementation.

See sample code here:

from requests import Session
from requests.adapters import HTTPAdapter
import ssl


class CustomHTTPAdapter(HTTPAdapter):

    def init_poolmanager(self, *args, **kwargs):
        # this creates a default context with secure default settings,
        # which enables server certficiate verification using the
        # system's default CA certificates
        context = ssl.create_default_context()

        # alternatively, you could create your own context manually
        # but this does NOT enable server certificate verification
        # context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)

        super().init_poolmanager(*args, **kwargs, ssl_context=context)


def main():
    client_session = Session()
    client_session.mount("https://", CustomHTTPAdapter())

    # now you can use the client_session to make requests
    # r = client_session.get("https://<web address>/rest/info?f=json")
2 of 2
1

Creating an ssl.SSLContext() on its own doesn't enable certificate verification or load CA certificates by default. This is why you're not seeing SSL errors. Using ssl.create_ssl_context() does set verification by default.

So the issue here isn't with SSLContext or certifi, it's with the website's certificate and how you're constructing your SSLContext. Next step would be to look into why the certificate the website is presenting isn't valid.

🌐
Python
docs.python.org › 3 › library › ssl.html
ssl — TLS/SSL wrapper for socket objects — Python 3.14.4 ...
Return a new SSLContext object with default settings for the given purpose. The settings are chosen by the ssl module, and usually represent a higher security level than when calling the SSLContext constructor directly.
🌐
Pythontic
pythontic.com › ssl › sslcontext › sslcontext
SSLcontext() method of SSLcontext class in Python | Pythontic.com
The SSLContext() method creates an SSLContext object which is used for storing SSL related settings and artefacts like SSL certificates, private key and CA certificates.
🌐
ProgramCreek
programcreek.com › python › example › 72757 › ssl.SSLContext
Python Examples of ssl.SSLContext
Defaults to ``PROTOCOL_SSLv23``. """ if protocol is None: protocol = ssl.PROTOCOL_SSLv23 ctx = _SSLContext(protocol) ctx.load_cert_chain(cert_file, pkey_file) return ctx ... def __init__( self, url: str, timeout: int = 30, ssl: Optional[SSLContext] = None, proxy: Optional[str] = None, default_headers: Dict[str, str] = {}, ): """API client for Incoming Webhooks and response_url :param url: a complete URL to send data (e.g., https://hooks.slack.com/XXX) :param timeout: request timeout (in seconds) :param ssl: ssl.SSLContext to use for requests :param proxy: proxy URL (e.g., localhost:9000, http://localhost:9000) :param default_headers: request headers to add to all requests """ self.url = url self.timeout = timeout self.ssl = ssl self.proxy = proxy self.default_headers = default_headers
🌐
Stack Overflow
stackoverflow.com › questions › 36026846 › ssl-context-for-older-python-version
sockets - SSL Context for older python version - Stack Overflow
So your wrap_socket should be like ssl.wrap_socket(s_, keyfile=clientKey, certfile=clientCert, ca_certs=cacertfile cert_reqs=ssl.CERT_REQUIRED) 2016-03-25T03:44:12.187Z+00:00 ... I've got the perfect solution using the requests library. The requests library has got to be my favorite library I've ever used, cause it takes something in Python that is inherently difficult to do -- SSL and REST requests -- and makes it unbelievably simple.
🌐
Electricmonk
electricmonk.nl › log › 2018 › 06 › 02 › ssl-tls-client-certificate-verification-with-python-v3-4-sslcontext
SSL/TLS client certificate verification with Python v3.4+ SSLContext | Electricmonk.nl weblog
June 2, 2018 - But SSLContext.load_default_certs() loads the system’s default trusted Certificate Authority chains so that the client can verify the server‘s certificates. You generally don’t want to use these for client certificates. In the Verifying Certificates section, it mentions that you need to specify CERT_REQUIRED: In server mode, if you want to authenticate your clients using the SSL ...
🌐
GitHub
github.com › encode › httpx › issues › 924
How can I use a custom SSLContext / PyOpenSSLContext when creating a Client? · Issue #924 · encode/httpx
May 2, 2020 - My understanding from reading httpx documentation is that a httpx.Client is roughly similar to a requests.Session and the Dispatcher API will be roughly similar to Adapters. @tomchristie mentions configuring an ssl_context in 768 - Dispatcher API but I didn't understand how to use that in practice.
Author   kafonek
Find elsewhere
🌐
Stack Overflow
stackoverflow.com › questions › 38795935 › how-to-send-json-data-using-ssl
python - How to send JSON data using SSL - Stack Overflow
May 23, 2017 - def single_contract(amount, service_key): current_date = datetime.now() fee = 0 if amount > 10000.0: fee = amount * 0.01 if os.path.exists('./Files/Point.txt'): with open('./Files/Point.txt') as opened_file: point_id = opened_file.read() json_data = dict() json_data["single_contract"] = dict() json_data["single_contract"]["point_id"] = point_id.strip() json_data["single_contract"]["datetime"] = datetime.strftime(current_date, '%Y-%m-%d %H:%M:%S') json_data["single_contract"]["external_transaction_id"] = randint(999999999, 9999999999) json_data["single_contract"]["service_id"] = 100135186139257
🌐
MicroPython
docs.micropython.org › en › latest › library › ssl.html
ssl – SSL/TLS module — MicroPython latest documentation
DTLS cookies for “Hello Verify” are associated with the SSLContext object, so the same SSLContext object should be used to wrap a subsequent connection from the same client.
🌐
Beautiful Soup
tedboy.github.io › python_stdlib › generated › generated › ssl.SSLContext.get_ca_certs.html
ssl.SSLContext.get_ca_certs — Python Standard Library
ssl.SSLContext » · ssl.SSLContext.get_ca_certs · View page source · SSLContext.get_ca_certs(binary_form=False) → list of loaded certificate¶ · Returns a list of dicts with information of loaded CA certs. If the optional argument is True, returns a DER-encoded copy of the CA certificate.
🌐
GitHub
github.com › python › cpython › blob › main › Lib › ssl.py
cpython/Lib/ssl.py at main · python/cpython
All Python stdlib modules shall use this function to create SSLContext · objects in order to keep common settings in one place. The configuration · is less restrict than create_default_context()'s to increase backward · compatibility. """ if not isinstance(purpose, _ASN1Object): raise TypeError(purpose) · # SSLContext sets OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_COMPRESSION, # OP_CIPHER_SERVER_PREFERENCE, OP_SINGLE_DH_USE and OP_SINGLE_ECDH_USE ·
Author   python
🌐
Python.org
discuss.python.org › core development
`ssl`: changing the default `SSLContext.verify_flags`? - Core Development - Discussions on Python.org
July 25, 2023 - At the moment (CPython 3.11), the default SSLContext.verify_flags is set to just VERIFY_X509_TRUSTED_FIRST: >>> import ssl >>> ssl.create_default_context().verify_flags <VerifyFlags.VERIFY_X509_TRUSTED_FIRST: 32768> I…
🌐
Pyopenssl
pyopenssl.org › en › latest › api › ssl.html
SSL — An interface to the SSL-specific parts of OpenSSL — pyOpenSSL 26.0.0 documentation
callback – The optional Python verification callback to use. This should take five arguments: A Connection object, an X509 object, and three integer variables, which are in turn potential error number, error depth and return code. callback should return True if verification passes and False otherwise. If omitted, OpenSSL’s default verification is used. ... See SSL_CTX_set_verify(3SSL) for further details.
🌐
Readthedocs
python-security.readthedocs.io › ssl.html
Python SSL and TLS security — Python Security 0.0 documentation
Windows: ssl.enum_certificates(store_name), new in Python 3.4. Use CertOpenStore() and CertEnumCertificatesInStore() functions. ... New in Python 3.2. ... SSLContext.load_verify_locations(): This method can also load certification revocation lists (CRLs) in PEM or DER format.
🌐
Pythontic
pythontic.com › ssl › sslcontext › introduction
The SSLContext class in Python | Pythontic.com
The SSLContext object in Python acts as a place to initialize SSL settings before connecting to a peer using SSL protocol. An SSLcontext object also has methods for validating the certificates and SSLSocket creation.
🌐
Medium
rob-blackbourn.medium.com › secure-communication-with-python-ssl-certificate-and-asyncio-939ae53ccd35
Secure Communication With Python SSL Certificate and Asyncio | by Rob Blackbourn | Medium
July 22, 2023 - import asyncio from os.path import expanduser import socket import ssl async def tcp_echo_client(message): host = socket.gethostname() context = ssl.SSLContext(ssl.PROTOCOL_TLS) # Load the client certificate.
🌐
Runebook.dev
runebook.dev › en › docs › python › library › ssl › ssl.SSLContext
Securing Your Python Apps: A Guide to ssl.SSLContext Best Practices
The ssl.SSLContext object in Python is essentially a container for configuration settings related to SSL/TLS (Secure Sockets Layer/Transport Layer Security) protocols.
🌐
Python
docs.python.domainunion.de › 3 › library › ssl.html
ssl — TLS/SSL wrapper for socket objects — Python 3.14.3 documentation
Wrap an existing Python socket sock and return an instance of SSLContext.sslsocket_class (default SSLSocket). The returned SSL socket is tied to the context, its settings and certificates.