נתקלתם בשגיאה SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
בעת ניסיון לבצע בקשת HTTPS בפייתון באמצעות requests
או urllib3
? במאמר זה אציג כיצד לאבחן ולתקן בעיה זו.
השגיאה מציינת שפייתון לא הצליח לאמת את תעודת ה-SSL/TLS של אתר האינטרנט אליו אתם מתחברים, מכיוון שלא מצא תעודת שורש (root certificate) מהימנה במאגר שלו.
שלב 1: אבחון הבעיה באמצעות OpenSSL (מומלץ)
לפני שינוי קוד הפייתון, בדקו את חיבור ה-SSL באמצעות כלי השירות openssl
. זה יעזור להבין אם הבעיה ספציפית לפייתון או קשורה להגדרות מערכת או לשרת עצמו.
- התקינו OpenSSL, אם אינו מותקן אצלכם (לרוב מותקן מראש ב-Linux/macOS; עבור Windows הורידו מה-אתר הרשמי או השתמשו במנהלי חבילות כמו Chocolatey/Scoop).
- בצעו את הפקודה במסוף שלכם (שורת הפקודה), החליפו את
<hostname>
בכתובת האתר (ללאhttps://
) ואת<port>
בפורט (בדרך כלל 443 עבור HTTPS):openssl s_client -connect <hostname>:<port> -showcerts # דוגמה עבור rosstat.gov.ru: openssl s_client -connect rosstat.gov.ru:443 -showcerts
- נתחו את הפלט: שימו לב לשורה
Verify return code
. אם היא מכילה שגיאה כמוunable to get local issuer certificate
(קוד 20) אוcertificate verify failed
(קוד 21), זה מאשר בעיה באמון בתעודה ברמת המערכת או במאגר ש-OpenSSL משתמש בו.
שלב 2: בחרו את שיטת הפתרון
קיימות מספר דרכים לתקן את השגיאה SSLCertVerificationError
. בחרו את זו המתאימה ביותר למצבכם.
שיטה 1: כיבוי אימות SSL (מהיר, אך אינו בטוח)
שיטה זו מכבה לחלוטין את אימות התעודה. השתמשו בה רק לבדיקה זמנית, סקריפטים חד-פעמיים ורק עבור אתרים שאתם בוטחים בהם לחלוטין.
⚠️ אזהרה: כיבוי האימות הופך את החיבור שלכם לפגיע להתקפות "אדם באמצע" (MITM). לעולם אל תשתמשו ב-verify=False
בקוד פרודקשן או בעבודה עם נתונים רגישים!
import requests
import urllib3
url = "https://rosstat.gov.ru/storage/mediabank/tab5_v01.xlsx" # דוגמה ל-URL
# מכבים את אימות ה-SSL
try:
# מדכאים אזהרות על בקשות לא בטוחות (אופציונלי)
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
response = requests.get(url, verify=False)
response.raise_for_status() # בודקים שגיאות HTTP (4xx, 5xx)
# הקוד שלכם לעיבוד התגובה, למשל, שמירת קובץ
with open("downloaded_file.xlsx", "wb") as f:
f.write(response.content)
print("הקובץ הורד בהצלחה (עם אימות SSL כבוי).")
except requests.exceptions.RequestException as e:
print(f"שגיאה בהורדת הקובץ: {e}")
finally:
# חשוב: אם כיביתם אזהרות גלובלית,
# ייתכן שתרצו להפעיל אותן מחדש לאחר ביצוע הבקשה,
# אף על פי שבדרך כלל זה לא נדרש אם הסקריפט מסתיים.
# import warnings
# warnings.simplefilter('default', urllib3.exceptions.InsecureRequestWarning)
pass
שיטה 2: התקנה/עדכון תעודות עבור פייתון (תלוי פלטפורמה)
פייתון עשוי להגיע עם סקריפטים להתקנה או עדכון של אוסף תעודות שורש מחבילת certifi
.
- ב-macOS:
- עברו לתיקיית ההתקנה של פייתון (בדרך כלל
/Applications/Python <version>/
). - מצאו ולחצו פעמיים על הקובץ
Install Certificates.command
. הוא יתקין/יעדכן אתcertifi
ויקשר את מודול הסטנדרטיssl
לתעודות אלו.
- עברו לתיקיית ההתקנה של פייתון (בדרך כלל
- ב-Windows:
- לעיתים בעת התקנת פייתון נוצר סקריפט
install_certificates.bat
. חפשו אותו בספרייתScripts
בתוך תיקיית ההתקנה של פייתון (לדוגמה,C:\Users\<username>\AppData\Local\Programs\Python\Python<version>\Scripts\
). - אם מצאתם אותו, הפעילו אותו.
- אם הסקריפט אינו קיים, שיטה זו ככל הנראה לא תעבוד. השתמשו בשיטה 3.
- לעיתים בעת התקנת פייתון נוצר סקריפט
שיטה 3: שימוש ישיר בחבילת certifi
(מומלץ, מרובה פלטפורמות)
זוהי הדרך האמינה ביותר לציין במפורש לפייתון באיזה אוסף של תעודות שורש להשתמש.
- התקינו את
certifi
:bash pip install --upgrade certifi
- השתמשו ב-
certifi
בקוד שלכם: העבירו את הנתיב לקובץ התעודות שלcertifi
לפרמטרverify
של הפונקציהrequests.get()
.import requests import certifi url = "https://rosstat.gov.ru/storage/mediabank/tab5_v01.xlsx" # דוגמה ל-URL try: # מציינים במפורש להשתמש בתעודות מ-certifi response = requests.get(url, verify=certifi.where()) response.raise_for_status()# הקוד שלכם לעיבוד התגובה with open("downloaded_file_certifi.xlsx", "wb") as f: f.write(response.content) print("הקובץ הורד בהצלחה באמצעות תעודות certifi.")except requests.exceptions.RequestException as e: print(f"שגיאה בהורדת הקובץ: {e}")
אפילו אםrequests
עשויה להשתמש ב-certifi
כברירת מחדל, ציון מפורש שלverify=certifi.where()
מבטיח התנהגות זו.
שיטה 4: שימוש במאגרי מערכת או משתני סביבה (מתקדם)
מודול ה-ssl
של פייתון יכול גם לחפש תעודות במאגרי המערכת או בנתיבים המצוינים במשתני סביבה. זה שימושי, לדוגמה, בסביבות ארגוניות עם מרכזי תעודות (CA) משלהן.
- מאגרי מערכת:
- Linux/macOS: פייתון משתמש לעיתים קרובות אוטומטית בתעודות מערכת (לדוגמה, מ-
/etc/ssl/certs/
). ודאו שלמערכת שלכם יש תעודות שורש עדכניות (sudo apt update && sudo apt install ca-certificates
עבור Debian/Ubuntu,sudo yum update ca-certificates
עבור CentOS/RHEL). - Windows: פייתון עשוי לנסות להשתמש במאגר המערכת של Windows, אך זה לא תמיד עובד באמינות ללא חבילות נוספות (לדוגמה,
python-certifi-win32
). מומלץ להשתמש ב-certifi
(שיטה 3).
- Linux/macOS: פייתון משתמש לעיתים קרובות אוטומטית בתעודות מערכת (לדוגמה, מ-
- משתני סביבה: ניתן לציין במפורש נתיב לקובץ או לספרייה עם תעודות:
SSL_CERT_FILE
: ציינו נתיב ל-קובץ (בפורמט PEM) המכיל את כל תעודות השורש המהימנות.SSL_CERT_DIR
: ציינו נתיב ל-ספרייה, בה כל תעודה נמצאת בקובץ PEM נפרד עם שם בפורמט Hash (השתמשו ב-c_rehash
מ-OpenSSL להכנת הספרייה).
- Linux/macOS (באופן זמני, עבור הסשן הנוכחי):
bash export SSL_CERT_FILE=/path/to/your/ca-bundle.pem python your_script.py
- Windows (cmd, באופן זמני):
cmd set SSL_CERT_FILE=C:\path\to\your\ca-bundle.pem python your_script.py
- Windows (PowerShell, באופן זמני):
powershell $env:SSL_CERT_FILE = "C:\path\to\your\ca-bundle.pem" python your_script.py
כדי להוסיף CA משלכם (לדוגמה, ארגוני), עליכם להוסיף את התעודה שלו לקובץSSL_CERT_FILE
או לספרייהSSL_CERT_DIR
.
שלב 3 (בונוס): כיצד ליצור תעודה בחתימה עצמית (self-signed certificate) לפיתוח מקומי
אם אתם מפתחים שרת אינטרנט מקומי (API, אתר) ורוצים לבדוק אותו ב-HTTPS, תצטרכו תעודת SSL. מכיוון שאין לכם דומיין ציבורי לקבלת תעודה מ-CA רגיל, אתם יכולים ליצור תעודה בחתימה עצמית.
שימוש ב-OpenSSL (מרובה פלטפורמות):
- בצעו את הפקודה: פקודה זו תיצור מפתח פרטי (
key.pem
) ואת התעודה עצמה (cert.pem
), שתהיה תקפה ל-10 שנים, עבורlocalhost
.openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -sha256 -days 3650 -nodes -subj "/CN=localhost" -addext "subjectAltName = DNS:localhost,IP:127.0.0.1"
-nodes
: יוצר מפתח ללא הגנה באמצעות סיסמה (נוח לפיתוח).-subj "/CN=localhost"
: מגדיר את ה-Common Name.-addext "subjectAltName = ..."
: מוסיף Subject Alternative Names (חשוב עבור דפדפנים ולקוחות מודרניים).
- השתמשו ב-
key.pem
וב-cert.pem
בהגדרות שרת האינטרנט המקומי שלכם (Flask, Django, Node.js וכו') להפעלת HTTPS.
שימוש ב-PowerShell (Windows 10/11):
- בצעו את הפקודה ב-PowerShell (עם הרשאות מנהל): פקודה זו תיצור תעודה ותמקם אותה במאגר התעודות של המחשב.
New-SelfSignedCertificate -DnsName "localhost", "127.0.0.1" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(5) -FriendlyName "My Localhost Dev Cert"
ייתכן שתידרשו לייצא תעודה זו מהמאגר (certlm.msc
) לקבצי.pfx
או.pem
לצורך שימוש בשרת האינטרנט שלכם.
הערה: דפדפנים ולקוחות HTTP (כולל requests
של פייתון כברירת מחדל) לא יבטחו בתעודות בחתימה עצמית. בעת גישה לשרת כזה תקבלו אזהרה או שגיאת SSL. לצורך בדיקות, תצטרכו או להוסיף תעודה זו לתעודות השורש המהימנות של המערכת/הדפדפן שלכם, או להשתמש ב-verify=False
(עבור requests
), או לציין את הנתיב לקובץ ה-cert.pem
שלכם באמצעות verify='/path/to/cert.pem'
.