Saltar al contenido
ecdsa.com
Python urllib.requestcryptography de Python

Mensaje de error

<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate

También se muestra como

  • urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate

El texto que va entre los corchetes angulares es el error de ssl subyacente y varía («self-signed certificate in certificate chain», «certificate has expired», …). Python lo cierra con una ubicación en el código fuente y «>», por ejemplo, «(_ssl.c:1082)>».

Python urllib.request — urllib.error.URLError wrapping ssl.SSLCertVerificationError

Qué significa

urllib.request.urlopen() envuelve cualquier problema de conexión en URLError, así que el fallo de TLS aparece dentro de «<urlopen error …>». Cuando esto ocurre con todos los sitios públicos, incluido www.python.org, el proceso de Python no tiene ningún certificado de CA utilizable: el caso clásico es el instalador de python.org en macOS, cuyo OpenSSL incluido no lee el llavero hasta que se ejecuta «Install Certificates.command».

Por qué ocurre

Cómo solucionarlo

  1. 1.

    macOS: ejecutar Install Certificates.command

    Ejecútalo desde Finder o desde una terminal para cada versión de Python de python.org y, después, confirma que existe la ruta del archivo de CA predeterminado.

    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. 2.

    Pasar un contexto creado a partir de certifi

    En los scripts que deben funcionar en cualquier sitio, crea el contexto SSL explícitamente a partir de certifi.where(); mantén certifi actualizado para que sus raíces estén al día.

    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. 3.

    O usar el almacén de confianza del sistema operativo

    truststore.inject_into_ssl() hace que urllib, http.client y las bibliotecas construidas sobre ssl verifiquen a través del sistema operativo, incluidas las raíces corporativas que despliega el departamento de TI.

    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. 4.

    Comprobar si el entorno sustituye las rutas predeterminadas

    Elimina las variables SSL_CERT_FILE y SSL_CERT_DIR si apuntan a archivos que no contienen las raíces necesarias.

    bash
    env | grep -E '^SSL_CERT_(FILE|DIR)='
    python3 -c "import ssl; print(ssl.get_default_verify_paths())"

Errores relacionados

Explorar toda la base de datos de errores de firma