Сообщение об ошибке
<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
Также выводится как
- urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
Текст внутри угловых скобок — исходная ошибка ssl, и он бывает разным («self-signed certificate in certificate chain», «certificate has expired», …). Python завершает его местом в исходном коде и «>», например «(_ssl.c:1082)>».
Python urllib.request — urllib.error.URLError wrapping ssl.SSLCertVerificationError
Что это означает
urllib.request.urlopen() оборачивает любую проблему с соединением в URLError, поэтому ошибка TLS оказывается внутри «<urlopen error …>». Если так происходит со всеми публичными сайтами, включая www.python.org, у процесса Python вообще нет пригодных сертификатов CA. Классический случай — установщик python.org для macOS: встроенный в него OpenSSL не читает связку ключей, пока не запущен «Install Certificates.command».
Почему это происходит
Python с python.org в macOS без установленных сертификатов
частоУстановщик поставляет OpenSSL с пустым хранилищем доверенных сертификатов и вспомогательный скрипт «Install Certificates.command», который устанавливает certifi и создаёт на него ссылку. Если пропустить этот шаг (или позже установить новую минорную версию), urlopen ничего не сможет проверить.
Минимальный образ или собственная сборка Python без пакета сертификатов CA
иногдаPython, собранный из исходного кода или скопированный в образ scratch или distroless, ищет пакет сертификатов по пути OpenSSL по умолчанию, которого там нет.
Прокси с инспекцией TLS
иногдаЕсли ошибка возникает только на некоторых сайтах или сбои начались в корпоративной сети, вероятная причина — корневой сертификат прокси, которому этот Python не доверяет.
SSL_CERT_FILE или SSL_CERT_DIR указывает не туда
редкоЭти переменные заменяют пути по умолчанию для всего процесса; пустой или посторонний файл ломает любую проверку.
Как исправить
- 1.
macOS: запустите Install Certificates.command
Запустите его из Finder или терминала для каждой версии Python с python.org, затем убедитесь, что файл CA по пути по умолчанию существует.
bash # macOS, python.org installer (one script per installed version) "/Applications/Python 3.14/Install Certificates.command" python3 -c "import ssl; print(ssl.get_default_verify_paths().openssl_cafile)" - 2.
Передайте контекст, созданный на основе certifi
Для скриптов, которые должны работать везде, явно создавайте SSL-контекст из certifi.where(); обновляйте certifi, чтобы его корневые сертификаты оставались актуальными.
python # Explicit, portable: use certifi's Mozilla bundle for this request # pip install certifi import certifi, ssl, urllib.request ctx = ssl.create_default_context(cafile=certifi.where()) urllib.request.urlopen("https://www.python.org/", context=ctx) - 3.
Или используйте хранилище доверенных сертификатов операционной системы
После вызова truststore.inject_into_ssl() urllib, http.client и библиотеки на основе ssl проверяют сертификаты средствами ОС, в том числе с учётом корневых сертификатов компании, развёрнутых ИТ-отделом.
python # Or verify with the operating system's store (macOS Keychain, Windows, Linux bundle) # pip install truststore==0.10.5 import truststore truststore.inject_into_ssl() - 4.
Проверьте переопределения в переменных окружения
Сбросьте SSL_CERT_FILE и SSL_CERT_DIR, если они указывают на файлы без нужных корневых сертификатов.
bash env | grep -E '^SSL_CERT_(FILE|DIR)=' python3 -c "import ssl; print(ssl.get_default_verify_paths())"