HomeBlogTranscribePlansAPI Keys

Transcripciones con la YouTube Data API: por qué falla captions.download

Terminal mostrando una respuesta 403 Forbidden del endpoint captions.download de la YouTube Data API

Si intentas obtener transcripciones a través de la YouTube Data API, probablemente ya te topaste con el muro: captions.list devuelve alegremente los IDs de las pistas de subtítulos de cualquier video, pero en el momento en que llamas a captions.download sobre una de ellas, recibes un 403. Verificas tu clave de API, añades el scope youtube.force-ssl, pruebas con OAuth — sigue siendo 403. Esto no es un bug ni un problema de cuota. Es así por diseño, y la documentación entierra lo esencial.

La restricción, con precisión

captions.download requiere un token OAuth de una cuenta que sea propietaria del video. No cualquier cuenta autenticada: el dueño del canal (o un gestor de contenido con derechos sobre él). Los endpoints de subtítulos existen para que los creadores gestionen las pistas de subtítulos de sus propias subidas: subir un .srt, corregir una errata, borrar una mala traducción automática. Descargar subtítulos de videos arbitrarios de terceros nunca formó parte del contrato.

El mensaje de error lo deja claro cuando lo lees con atención:

The permissions associated with the request are not sufficient
to download the caption track.

Así que la ruta de escalada habitual — clave de API → OAuth con tu cuenta → scopes más amplios → cuenta de servicio — no lleva a ninguna parte. Cada peldaño falla la misma comprobación de propiedad. Yo quemé una tarde con esto antes de aceptarlo, y a juzgar por el tráfico de Stack Overflow, medio internet también.

Para qué sigue sirviendo captions.list

Para ser justos con la Data API: captions.list funciona con una simple clave de API y cuesta unas 50 unidades de cuota. Te dice qué pistas existen, sus idiomas y si son generadas automáticamente (trackKind: "asr") o subidas por humanos. Eso es genuinamente útil como comprobación previa — si un video no tiene ninguna pista, sabes de antemano que necesitarás speech-to-text en lugar de extracción de subtítulos. La Data API también sigue siendo la herramienta correcta para búsqueda, enumeración de playlists y metadatos. Simplemente no te va a entregar el texto de la transcripción.

Opción 1: obtener los subtítulos como lo hace el reproductor

El reproductor de video obviamente recibe los datos de subtítulos sin el token OAuth del propietario, y bibliotecas como youtube-transcript-api (Python) los obtienen de la misma manera. En tu portátil esto funciona bien y son tres líneas.

La pega aparece en producción: YouTube desafía agresivamente las peticiones desde rangos de IP de centros de datos. Despliega esas mismas tres líneas en AWS, GCP o Heroku y empezarás a ver errores de "Sign in to confirm you're not a bot" e IpBlocked. He documentado ese modo de fallo y sus soluciones por separado en por qué youtube-transcript-api acaba bloqueada en la nube — versión corta: se arregla con proxies residenciales, pero eso es un proyecto en sí mismo.

Opción 2: una API de transcripciones alojada

Si solo quieres texto a partir de una URL, un endpoint alojado se salta ambos problemas — sin requisito de propiedad, sin cuidar proxies. youtube2text.org ejecuta la obtención de subtítulos detrás de proxies residenciales rotatorios del lado del servidor, así que tu petición viene de donde venga:

# grab a free demo key (shared, 5 videos/month per IP)
curl -s https://youtube2text.org/api/demo-key

# fetch a transcript
curl -s "https://youtube2text.org/api/transcribe?url=https://www.youtube.com/watch?v=VIDEO_ID" \
  -H "x-api-key: yt_YOUR_KEY"

La respuesta es JSON simple:

{"result": {"videoId": "...", "title": "...", "pubDate": "...",
            "content": "full transcript text ...", "contentSize": 12345, "truncated": false}}

Si el video simplemente no tiene subtítulos, obtienes TRANSCRIPT_UNAVAILABLE con un 404 — la misma situación que captions.list habría mostrado como una lista de pistas vacía, solo que detectada en una llamada en lugar de dos.

Hay un recorrido más largo con manejo de errores en extraer transcripciones de YouTube con curl, y una versión en Python en la guía de migración de youtube-transcript-api si el código basado en requests es más lo tuyo.

Una configuración combinada sensata

Lo que yo construiría hoy, después de haber peleado con esto desde ambos lados:

Intentar forzar a captions.download a hacer el trabajo del medio es el único camino que categóricamente no puede funcionar para videos que no te pertenecen — ningún scope, clave ni ajuste de consola cambia eso.

Si quieres tu propia clave en lugar de la de demostración compartida, el inicio de sesión es solo con Google en youtube2text.org/app/keys — sin número de teléfono, sin tarjeta. El nivel gratuito son 5 videos al mes; los planes de pago empiezan en $5.99 por 50.