Solucionar error HTTPSConnectionPool Max retries exceeded Caused by SSLError SSLCertVerificationError CERTIFICATE_VERIFY_FAILED certificate verify failed self signed certificate in certificate chain que se produce al ejecutar una aplicación Python que accede a un recurso web HTTPS.
- Error HTTPSConnectionPool Max retries exceeded Caused by SSLError SSLCertVerificationError CERTIFICATE_VERIFY_FAILED certificate verify failed self signed certificate in certificate chain en Python.
- Solución rápida al error SSLError SSLCertVerificationError CERTIFICATE_VERIFY_FAILED en Python.
- Solución más segura al error SSLError SSLCertVerificationError CERTIFICATE_VERIFY_FAILED en Python.
Error HTTPSConnectionPool Max retries exceeded Caused by SSLError SSLCertVerificationError CERTIFICATE_VERIFY_FAILED certificate verify failed self signed certificate in certificate chain en Python
Cuando desarrollamos un script/app en el lenguaje de programación Python que accede a algún recurso web por HTTPS (puerto 443 o TLS) mediante la librería requests (por ejemplo para el acceso al API de DeepSeek), y recibimos este error:
Error inesperado: Error de conexión: HTTPSConnectionPool(host=’api.deepseek.com’, port=443): Max retries exceeded with url: /v1/chat/completions (Caused by SSLError(SSLCertVerificationError(1, ‘[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:992)’)))

El motivo es que en nuestra organización hay algún tipo de sistema de seguridad perimetral o de endpoint que analiza el tráfico HTTPS. Este tipo de sistemas suele usar un certificado propio para romper el túnel HTTPS, analizar el tráfico y volver a montar el túnel. Si no disponemos de este certificado, podremos recibir el error que indicamos.
Solución rápida al error SSLError SSLCertVerificationError CERTIFICATE_VERIFY_FAILED en Python
A continuación mostramos una solución rápida el error SSLCertVerificationError , aunque no es la mejor ni la más segura, dado que desactivaremos la comprobación de certificado HTTPS. Para ello, en el código Python donde realicemos la conexión al recurso web mediante requests, agregaremos el parémtro «verify», con valor «False». Por ejemplo, si tenemos este código Python de conexión a un recurso web:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
try: response = requests.post(API_URL, headers=encabezado, data=json.dumps(datos)) response.raise_for_status() # Lanza una excepción si la solicitud no fue correcta return response.json() except requests.exceptions.HTTPError as e: if response.status_code == 401: raise Exception("Error de autenticación: API key no válida") elif response.status_code == 429: raise Exception("Límite de tasa excedido: Demasiadas solicitudes") else: raise Exception(f"Error HTTP: {str(e)}") except requests.exceptions.ConnectionError as e: raise Exception(f"Error de conexión: {str(e)}") except requests.exceptions.Timeout as e: raise Exception(f"Tiempo de espera agotado: {str(e)}") except requests.exceptions.RequestException as e: raise Exception(f"Error en la solicitud: {str(e)}") |
Añadiremos al método post (o al get) de requests el parámetro verify=False, quedando:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
try: response = requests.post(API_URL, headers=encabezado, data=json.dumps(datos), verify=False) response.raise_for_status() # Lanza una excepción si la solicitud no fue correcta return response.json() except requests.exceptions.HTTPError as e: if response.status_code == 401: raise Exception("Error de autenticación: API key no válida") elif response.status_code == 429: raise Exception("Límite de tasa excedido: Demasiadas solicitudes") else: raise Exception(f"Error HTTP: {str(e)}") except requests.exceptions.ConnectionError as e: raise Exception(f"Error de conexión: {str(e)}") except requests.exceptions.Timeout as e: raise Exception(f"Tiempo de espera agotado: {str(e)}") except requests.exceptions.RequestException as e: raise Exception(f"Error en la solicitud: {str(e)}") |
Añadiendo este parámetro, no nos dará el error indicado, aunque en la ventana de terminal seguirá mostrando un warning, del tipo:
connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host ‘api.deepseek.com’. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
warnings.warn
Para ocultar este waring, añadiremos la siguiente línea de código al principio de nuestro script Python:
1 |
warnings.filterwarnings("ignore", message="Unverified HTTPS request") |
Que necesitará el import:
1 |
import warning |
Solución más segura al error SSLError SSLCertVerificationError CERTIFICATE_VERIFY_FAILED en Python
Lo ideal, aunque esto no siempre es posible, es agregar un certificado válido para establecer la conexión HTTPS. Como hemos indicando en este punto, este error suele producirse cuando el sistema de seguridad de nuestra organización rompe el túnel HTTPS para analizar el tráfico cifrado y, una vez analizado, vuelve a montar el túnel con su propio certificado. Si disponemos de este certificado (que suele proporcionarlo el fabricante de la solución de seguridad), podremos indicuar su ubicación en el código Python, de forma que para establecer la conexión se usará dicho certificado.
Para establecer el certificado SSL en la conexión requests de Python, modificaremos el código con lo siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
try: ca_cert = "certificado.pem" # Ruta y fichero de certificado en formato PEM response = requests.post(API_URL, headers=encabezado, data=json.dumps(datos), verify=ca_cert) response.raise_for_status() # Lanza una excepción si la solicitud no fue correcta return response.json() except requests.exceptions.HTTPError as e: if response.status_code == 401: raise Exception("Error de autenticación: API key no válida") elif response.status_code == 429: raise Exception("Límite de tasa excedido: Demasiadas solicitudes") else: raise Exception(f"Error HTTP: {str(e)}") except requests.exceptions.ConnectionError as e: raise Exception(f"Error de conexión: {str(e)}") except requests.exceptions.Timeout as e: raise Exception(f"Tiempo de espera agotado: {str(e)}") except requests.exceptions.RequestException as e: raise Exception(f"Error en la solicitud: {str(e)}") |
El fichero de certificado «certificado.pem» debe existir en la misma carpeta que el ejecutable de nuestra app Python. Si no encuentra el fichero de certificado, mostrará el error:
Could not find a suitable TLS CA certificate bundle, invalid path: /ruta_del_certificado/certificado.pem
Si el fichero del certificado indicado no es correcto, mostrará el error:
Error de conexión: HTTPSConnectionPool(host=’api.deepseek.com’, port=443): Max retries exceeded with url: /v1/chat/completions (Caused by SSLError(SSLError(136, ‘[X509: NO_CERTIFICATE_OR_CRL_FOUND] no certificate or crl found (_ssl.c:4123)’)))