To open an https URL in Python with validation using system certificates (i.e on Windows or macOS), use:
import ssl
from urllib.request import urlopen
ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
response = urlopen("http://www.example.com", context=ctx)
If there are no system certificates or they aren't in a reliable location, you can use certificates bundled with the certifi package:
import certifi # 👈
import ssl
from urllib.request import urlopen
ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
ctx.load_verify_locations(cafile=certifi.where()) # 👈
response = urlopen("http://www.example.com", context=ctx)
If you additionally want to allow users to specify their own certificates - in the case that certifi-bundled certificates become out of date - you can allow users to specify the $SSL_CERT_FILE
environment variable to a certificate bundle (which is a convention originating from the OpenSSL library):
import certifi
import os # 👈
import ssl
from urllib.request import urlopen
ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
ctx.load_verify_locations(cafile=certifi.where())
if (cafile := os.environ.get('SSL_CERT_FILE')) is not None: # 👈
ctx.load_verify_locations(cafile=cafile) # 👈
response = urlopen("http://www.example.com", context=ctx)
All of the above should work on Python 3.8+. Or Python 3.4+ if you rewrite use of the walrus operator (:=
).