HomeBlogTranscribePlansAPI Keys

¿youtube-transcript-api bloqueada? Cómo arreglar los baneos de IP en AWS/GCP

Traceback de Python mostrando un error IpBlocked de youtube-transcript-api ejecutándose en un servidor en la nube

El script funcionó perfectamente en tu portátil durante semanas. Luego lo desplegaste — Lambda, una máquina EC2, Cloud Run, un dyno de Heroku, da igual — y ahora absolutamente todas las llamadas a youtube-transcript-api mueren con algo como:

youtube_transcript_api._errors.IpBlocked:
Could not retrieve a transcript for the video ...
YouTube is blocking requests from your IP.

O la versión con sabor a navegador del mismo muro: "Sign in to confirm you're not a bot". Nada en tu código cambió. La biblioteca no está rota. El problema es tu dirección IP.

Por qué solo se rompe en producción

youtube-transcript-api funciona obteniendo los datos de subtítulos igual que lo hace el reproductor de YouTube — sin clave de API, solo peticiones HTTP a YouTube. YouTube tolera esto desde conexiones residenciales, y por eso el desarrollo local va bien. Pero los rangos de IP de AWS, GCP, Azure y Heroku son de conocimiento público, y YouTube desafía en bloque el tráfico de esos ASN. No importa que hagas tres peticiones al día; el bloqueo es sobre el vecindario de red, no sobre tu comportamiento. Reinicia la instancia, consigue una nueva IP elástica, redespliega la función — aterrizarás en otra dirección del mismo pool bloqueado.

Vale la pena interiorizar esto porque el primer instinto (añadir reintentos, añadir retardos, rotar user agents) no ayuda. La señal en la que se fija YouTube es de dónde vienen los paquetes.

Solución 1: operar tus propios proxies residenciales

La biblioteca lo soporta directamente — trae WebshareProxyConfig y un GenericProxyConfig para cualquier proveedor. Enruta las peticiones a través de IPs residenciales y los bloqueos en su mayoría cesan. Funciona de verdad; así es como sobrevive todo el que hace scraping de YouTube a escala.

La contabilidad honesta de costos, eso sí:

Si ya operas infraestructura de proxies para otro scraping, añadir esto encima es razonable. Si las transcripciones son lo único que necesitas, te estás apuntando a operar una flota de proxies para sostener una sola llamada de función.

Solución 2: llamar a un endpoint que ya libra esta batalla

youtube2text.org hace la rotación de proxies residenciales del lado del servidor, así que tu función en la nube hace una aburrida petición HTTPS a una API normal. La migración es casi un buscar y reemplazar.

Antes:

from youtube_transcript_api import YouTubeTranscriptApi

transcript = YouTubeTranscriptApi().fetch(video_id)
text = " ".join(snippet.text for snippet in transcript)

Después:

import requests

r = requests.get(
    "https://youtube2text.org/api/transcribe",
    params={"url": video_id},          # full URLs work too
    headers={"x-api-key": "yt_YOUR_KEY"},
)
text = r.json()["result"]["content"]

Para probarlo antes de crear una cuenta, toma la clave de demostración compartida — curl -s https://youtube2text.org/api/demo-key — que permite 5 videos al mes por IP. Los errores vuelven como JSON estructurado con códigos que vale la pena manejar: TRANSCRIPT_UNAVAILABLE (404) significa que el video de verdad no tiene subtítulos — no es un bloqueo, y ningún proxy lo arreglará; RATE_LIMIT_EXCEEDED (429) incluye una pista de reintento. Hay un recorrido más completo en Python en la guía de integración con Python.

Qué solución te conviene

Tu propia clave (separada de la cuota de demostración compartida) requiere un inicio de sesión de Google en youtube2text.org/app/keys — el nivel gratuito son 5 videos al mes, los planes de pago van desde $5.99/mes por 50 videos hasta $19.99 ilimitado. Sin número de teléfono, sin tarjeta para el nivel gratuito.