When making a request over HTTPS, HTTPX needs to verify the identity of the requested host. To do this, it uses a bundle of SSL certificates (a.k.a. CA bundle) delivered by a trusted certificate authority (CA).
By default httpx will verify HTTPS connections, and raise an error for invalid SSL cases...
>>> httpx.get("https://expired.badssl.com/")
httpx.ConnectError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:997)
You can disable SSL verification completely and allow insecure requests...
>>> httpx.get("https://expired.badssl.com/", verify=False)
<Response [200 OK]>
If you're using a Client()
instance you should pass any verify=<...>
configuration when instantiating the client.
By default the certifi CA bundle is used for SSL verification.
For more complex configurations you can pass an SSL Context instance...
import certifi
import httpx
import ssl
# This SSL context is equivelent to the default `verify=True`.
ctx = ssl.create_default_context(cafile=certifi.where())
client = httpx.Client(verify=ctx)
Using the truststore
package to support system certificate stores...
import ssl
import truststore
import httpx
# Use system certificate stores.
ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
client = httpx.Client(verify=ctx)
Loding an alternative certificate verification store using the standard SSL context API...
import httpx
import ssl
# Use an explicitly configured certificate store.
ctx = ssl.create_default_context(cafile="path/to/certs.pem") # Either cafile or capath.
client = httpx.Client(verify=ctx)
Client side certificates allow a remote server to verify the client. They tend to be used within private organizations to authenticate requests to remote servers.
You can specify client-side certificates, using the .load_cert_chain()
API...
ctx = ssl.create_default_context()
ctx.load_cert_chain(certfile="path/to/client.pem") # Optionally also keyfile or password.
client = httpx.Client(verify=ctx)
Unlike requests
, the httpx
package does not automatically pull in the environment variables SSL_CERT_FILE
or SSL_CERT_DIR
. If you want to use these they need to be enabled explicitly.
For example...
# Use `SSL_CERT_FILE` or `SSL_CERT_DIR` if configured.
# Otherwise default to certifi.
ctx = ssl.create_default_context(
cafile=os.environ.get("SSL_CERT_FILE", certifi.where()),
capath=os.environ.get("SSL_CERT_DIR"),
)
client = httpx.Client(verify=ctx)
When making requests to local servers, such as a development server running on localhost
, you will typically be using unencrypted HTTP connections.
If you do need to make HTTPS connections to a local server, for example to test an HTTPS-only service, you will need to create and use your own certificates. Here's one way to do it...
- Use trustme to generate a pair of server key/cert files, and a client cert file.
- Pass the server key/cert files when starting your local server. (This depends on the particular web server you're using. For example, Uvicorn provides the
--ssl-keyfile
and--ssl-certfile
options.) - Configure
httpx
to use the certificates stored inclient.pem
.
ctx = ssl.create_default_context(cafile="client.pem")
client = httpx.Client(verify=ctx)