When making a request over HTTPS we need to verify the identity of the requested host. We rely on the truststore
package to load the system certificates, ensuring that httpx
has the same behaviour on SSL sites as your browser.
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)
If you're confident that you want to visit a site with an invalid certificate you can disable SSL verification completely...
>>> httpx.get("https://expired.badssl.com/", verify=False)
<Response [200 OK]>
If you're using a Client()
instance you can pass the verify=<...>
configuration when instantiating the client.
>>> client = httpx.Client(verify=True)
For more complex configurations you can pass an SSL Context instance...
import certifi
import httpx
import ssl
import certifi
# Use certifi for certificate validation, rather than the system truststore.
ctx = ssl.create_default_context(cafile=certifi.where())
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
.
These environment variables shouldn't be necessary since they're obsoleted by truststore
. They can be enabled if required like so...
# 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)