Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ceca

La casa de moneda: acuña el PO Token que YouTube empezó a exigir para entregar audio y video. Un binario, sin instalar nada, sin tocar las cuentas de nadie.

License: MIT

Por qué existe

Desde 2026 YouTube exige un PO Token (proof-of-origin) en todos sus clientes de reproducción. Sin él, la extracción funciona —título, duración y calidades salen bien— pero bajar el medio devuelve HTTP Error 403: Forbidden. Medido acá contra yt-dlp 2026.7.4: falla con todos los clientes (android_vr, web, web_safari, ios, mweb, tv_simply), con y sin runtime JS, y con y sin el solver de challenges. No es un problema de versión: 2026.7.4 era la última publicada.

La alternativa habitual es pasarle a yt-dlp las cookies del navegador. Esto existe para no hacer eso: en un equipo donde la app la usan varias personas, leerles el navegador no es una opción.

Qué hace, exactamente

sesión anónima nueva  ->  visitor_data
desafío de BotGuard   ->  intérprete JS  ->  integrity token  ->  PO Token

Sale una línea de JSON por stdout:

{"visitorData":"CgtLNVMz…","poToken":"MtYEKUO4B0oQ…"}

Los dos viajan juntos y eso no es comodidad: el token que destraba las URLs del servidor de video (gvs) se ata al visitor_data de la sesión. Usarlo con otro da un 403 idéntico al de no tener token.

Uso con yt-dlp

eval "$(ceca | python -c 'import sys,json; d=json.load(sys.stdin); print(f"VD={d[\"visitorData\"]}; PT={d[\"poToken\"]}")')"

yt-dlp --extractor-args "youtube:player_client=tv_simply;po_token=tv_simply.gvs+$PT;visitor_data=$VD" \
       -f bestaudio "https://www.youtube.com/watch?v=…"

tv_simply no es decorativo. Con el mismo token, web devuelve solo miniaturas, y mweb e ios siguen dando 403. Es el único cliente que se verificó bajando de punta a punta.

Lo que se aprendió construyéndolo

Cuatro cosas que costaron tiempo y cuyo error no nombra su causa:

Síntoma Causa
400 … JSPB Fava message don't accept top-level braces getHeaders() de bgutils-js manda content-type en minúscula. Pisarlo con Content-Type no reemplaza: viajan las dos y YouTube lee application/json+protobuf, application/json
Token válido que igual da 403 Se ató al id del video (que es lo intuitivo) en vez de al visitor_data. El de id sirve para otro contexto
Only images are available for download El cliente web necesita más que el token gvs. Usar tv_simply
Not implemented: HTMLCanvasElement's getContext() Es un aviso, no un error: canvas no hace falta. Se verificó bajando video sin él, y evita un módulo nativo que hay que compilar por plataforma

Construir

deno task test                     # sin red
deno task mint                     # acuña uno de verdad
deno task compile                  # dist/ceca, un ejecutable autocontenido

El binario compilado pesa ~110 MB (Deno mete su runtime adentro) y no necesita Node, npm ni Deno instalados en la máquina donde corre.

Detrás de un proxy corporativo

Funciona sin tocar nada: Deno respeta HTTP_PROXY y HTTPS_PROXY del entorno, y un proceso lanzado por otra aplicación hereda esas variables.

Verificado con un control, que es la única forma de saberlo: apuntando HTTPS_PROXY a un puerto muerto la corrida falla con fetch failed, y sin esa variable la misma corrida acuña normalmente. Si diera lo mismo en los dos casos, el proxy se estaría ignorando.

Seguridad

Este programa ejecuta JavaScript ofuscado que baja de YouTube. Es inevitable: el desafío de BotGuard es ese programa, y resolverlo es todo el punto. Por eso vive en un proceso aparte en vez de adentro de la app que lo usa, y por eso se compila con los permisos de Deno acotados: red sí, disco no. Aunque ese código quisiera hacer algo más, no puede.

No usa cuentas, cookies ni credenciales de nadie. La sesión es anónima y nueva en cada corrida.

Créditos y licencias

El trabajo pesado —la reimplementación del cliente de BotGuard— es de bgutils-js (MIT), y el visitor_data sale de youtubei.js (MIT). Acá solo está el pegamento.

Existe bgutil-ytdlp-pot-provider, que hace esto y bastante más (sesiones múltiples, proxies, plugin de yt-dlp). Este repo no existe porque aquel esté mal: existe porque es GPL-3.0, y para poder distribuirlo dentro de una aplicación propia hacía falta algo MIT.

About

Acuña el PO Token que YouTube exige para entregar audio y video. Un binario, sin cuentas ni cookies de nadie.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages