HomeBlogTranscribePlansAPI Keys

API de transcripciones de YouTube en Python: 10 líneas con requests

Script de Python obteniendo una transcripción de YouTube como JSON con la biblioteca requests

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

Si ese traceback te trajo aquí, bienvenido. Es el modo de fallo estándar del popular paquete de pip en cuanto tu código sale de tu portátil y aterriza en AWS, GCP o cualquier otra IP de centro de datos. Este artículo muestra la otra ruta: una API de transcripciones de YouTube alojada a la que llamas desde Python solo con requests. Al final tendrás un script de diez líneas que convierte cualquier URL de YouTube en texto de transcripción, más las ramas adecuadas para límites de tasa y videos sin subtítulos.

Por qué la biblioteca de pip muere en producción

youtube-transcript-api hace scraping de YouTube directamente desde la máquina que la ejecuta. En local eso está bien. Despliégala, y la detección de bots de YouTube marca el rango de IP de tu proveedor de nube en días, a veces en minutos. Documenté los detalles escabrosos en por qué la API de transcripciones de YouTube acaba bloqueada — versión corta: terminas alquilando proxies residenciales para leer subtítulos públicos, lo cual es absurdo.

youtube2text.org hace la parte que mira a YouTube del lado del servidor. Tu código hace una llamada HTTPS y recibe JSON de vuelta.

Las diez líneas

No hace falta cuenta para probarlo — hay un endpoint de clave de demostración:

import requests

API = "https://youtube2text.org/api/transcribe"
KEY = requests.get("https://youtube2text.org/api/demo-key").json()["apiKey"]

resp = requests.get(API, params={"url": "https://youtu.be/dQw4w9WgXcQ"},
                    headers={"x-api-key": KEY}, timeout=60)
resp.raise_for_status()
result = resp.json()["result"]
print(result["title"])
print(result["content"][:300])

El parámetro url acepta cualquier forma de URL de YouTube — watch?v=, youtu.be, shorts, embeds — o un id de video de 11 caracteres a secas. La respuesta te da videoId, title, pubDate, content, contentSize y una bandera truncated.

Una advertencia sobre esa clave de demostración: es compartida entre todos y está limitada a 5 videos al mes por IP. Bien para curiosear, inútil para algo real.

Manejar 429 y 404 como adultos

raise_for_status() está bien para una demo, pero los errores vuelven como JSON estructurado con un code sobre el que puedes ramificar:

import time

resp = requests.get(API, params={"url": video_url},
                    headers={"x-api-key": KEY}, timeout=60)
body = resp.json()

if resp.status_code == 200:
    transcript = body["result"]["content"]
elif resp.status_code == 429:
    time.sleep(body["error"]["retryAfterSeconds"])  # then retry
elif resp.status_code == 404:
    if body["error"]["code"] == "TRANSCRIPT_UNAVAILABLE":
        transcript = None  # video exists, but has no captions — skip it
    else:
        raise ValueError(f"No such video: {video_url}")  # VIDEO_NOT_FOUND
else:
    raise RuntimeError(body["error"]["message"])

TRANSCRIPT_UNAVAILABLE merece un momento de honestidad: las transcripciones salen de las pistas de subtítulos de YouTube (manuales o generadas automáticamente), y algunos videos simplemente no tienen ninguna. Ninguna API puede conjurar texto que no existe — para esos necesitarías speech-to-text de verdad, que comparé en Whisper vs subtítulos de YouTube. Reintentar no ayudará, así que no lo hagas.

maxChars y presupuestos de tokens para LLM

Si la transcripción va camino de un prompt, el tamaño te importa. La transcripción de un pódcast de tres horas se comerá alegremente 100k tokens. El parámetro maxChars limita la salida — el valor por defecto y el máximo son ambos 150000:

resp = requests.get(API,
    params={"url": video_url, "maxChars": 20000},
    headers={"x-api-key": KEY}, timeout=60)

Con la regla aproximada de 4 caracteres por token, maxChars=20000 queda en torno a 5k tokens. Comprueba result["truncated"] para saber si recibiste el texto completo. Si vas a conectar esto a un pipeline de recuperación en lugar de a un solo prompt, el artículo de integración con LangChain cubre el troceado como es debido.

Dejar atrás la clave de demostración

Cuando 5 videos compartidos al mes dejen de ser suficientes, inicia sesión con Google en youtube2text.org/app/keys y acuña tu propia clave — sin número de teléfono, sin tarjeta de crédito. El nivel gratuito son 5 videos al mes por clave; los niveles de pago empiezan en $5.99 por 50. Las diez líneas de arriba no cambian, solo cambia la cadena de la cabecera.