Fehlermeldung
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
Auch ausgegeben als
- ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
Python hängt die Position im C-Quellcode an, etwa „(_ssl.c:1082)“; die Zahl ändert sich mit der Python-Version und ist für die Diagnose bedeutungslos. urllib verpackt den Fehler als „<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] …>“, requests und urllib3 als „Max retries exceeded … (Caused by SSLError(…))“.
Python ssl module (OpenSSL) — ssl.SSLCertVerificationError, X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY (20)
Was der Fehler bedeutet
Das Modul ssl von Python hat OpenSSL beauftragt, das Zertifikat des Servers zu prüfen, und OpenSSL konnte den Aussteller des letzten Zertifikats der Kette nicht unter den CA-Zertifikaten finden, die dieser SSLContext geladen hat. Der Server ist nicht unbedingt falsch konfiguriert: Oft verwendet dieses Python einfach ein anderes (oder leeres) CA-Bundle als dein Browser oder dein Betriebssystem.
Warum der Fehler auftritt
Python von python.org unter macOS ohne seine Zertifikate
häufigDer macOS-Installer von python.org bringt ein eigenes OpenSSL mit, das den macOS-Schlüsselbund nicht liest. Solange „Install Certificates.command“ für diese Python-Version nicht ausgeführt wurde, hat sie überhaupt keine CA-Zertifikate, deshalb scheitert jede HTTPS-Anfrage auf diese Weise.
Eine private CA oder ein Proxy mit TLS-Inspektion
häufigFirmendienste und Firmen-Proxys verwenden Zertifikate, deren Root-Zertifikat über den Zertifikatsspeicher des Betriebssystems an verwaltete Rechner verteilt wird. Das OpenSSL von Python fragt den Zertifikatsspeicher von Windows oder macOS nicht ab, und Linux-Container haben das Root-Zertifikat nur, wenn es hinzugefügt wird.
Der Server sendet sein Zwischenzertifikat nicht
häufigOpenSSL lädt fehlende Zwischenzertifikate nicht nach. Sendet der Server nur sein Leaf-Zertifikat, scheitert Python, während Browser, die Zwischenzertifikate zwischenspeichern und herunterladen, scheinbar problemlos funktionieren.
Die CA wurde dem Zertifikatsspeicher des Systems hinzugefügt, aber die Bibliothek verwendet certifi
gelegentlichrequests, httpx, aiohttp, botocore und pip (mit Legacy-Zertifikaten) prüfen gegen das certifi-Bundle, das als Python-Paket ausgeliefert wird. Ein Root-Zertifikat, das mit update-ca-certificates oder im Schlüsselbund des Betriebssystems installiert wurde, ist für sie unsichtbar.
SSL_CERT_FILE oder SSL_CERT_DIR zeigt auf die falsche Stelle
seltenDiese Variablen ersetzen die Standardpfade von OpenSSL. Ein Pfad, der von einem anderen Tool übrig geblieben ist, oder ein Bundle, das nur ein privates Root-Zertifikat enthält, lässt öffentliche Websites scheitern (oder umgekehrt).
So behebst du den Fehler
- 1.
Builds von python.org unter macOS: Install Certificates.command ausführen
Das Skript installiert certifi und verlinkt es als Bundle für das OpenSSL dieses Python. Nach der Installation einer weiteren Python-Version muss es erneut ausgeführt werden.
bash # macOS, python.org installer: run once per installed Python version "/Applications/Python 3.14/Install Certificates.command" - 2.
Mit truststore den Trust Store des Betriebssystems verwenden
truststore lässt ssl.SSLContext über das Betriebssystem prüfen (Schlüsselbund unter macOS, Windows-Zertifikatsspeicher, System-Bundle unter Linux), sodass von deiner IT verteilte Root-Zertifikate auch in Python funktionieren. Es deckt außerdem urllib3, requests und pip ab; pip verwendet es seit pip 24.2 standardmäßig.
python # pip install truststore==0.10.5 — verify with the OS trust store (Keychain, Windows store, Linux bundle) import truststore truststore.inject_into_ssl() # call once at start-up, before creating connections import urllib.request urllib.request.urlopen("https://api.example.com/") - 3.
CA für einen Client explizit laden
Übergib cafile (oder cadata) an ssl.create_default_context(), wenn Code mit einem privaten Dienst kommuniziert. Der Kontext prüft weiterhin Hostnamen und Gültigkeitszeiträume.
python import ssl, urllib.request ctx = ssl.create_default_context(cafile="/etc/ssl/private-ca/corp-root-ca.pem") urllib.request.urlopen("https://api.example.com/", context=ctx) - 4.
Standardpfad des Bundles prüfen und setzen
ssl.get_default_verify_paths() zeigt, welche Datei und welches Verzeichnis OpenSSL verwendet. Mit SSL_CERT_FILE und SSL_CERT_DIR überschreibst du beide für den Prozess; lass die Variablen auf ein Bundle zeigen, das sowohl öffentliche Root-Zertifikate als auch deine CA enthält.
bash # Where does this Python look by default? python3 -c "import ssl; print(ssl.get_default_verify_paths())" # Point OpenSSL-based clients at a bundle that includes your CA export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt - 5.
Auf dem Server: vollständige Kette ausliefern
Enthält der Handshake nur ein Zertifikat und ist dessen Aussteller eine öffentliche Zwischen-CA, konfiguriere den Server mit der Full-Chain-Datei.
bash # Server side: 1 certificate in the handshake = intermediate missing openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \ | grep -c 'BEGIN CERTIFICATE'
Verwandte Fehler
<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unab…Python urllib.requestMax retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1…requests / urllib3 (Python)There was a problem confirming the ssl certificate: [SSL: CERTIFICATE_VERIFY_FA…pip[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certifi…Python ssl module (OpenSSL)curl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)