Skip to content

Repository files navigation

📹 Multi-Platform Video Downloader

🌟 Plataformas Soportadas

Instagram - Posts, Reels, Stories y Videos Privados (cookies + proxy de embeds)
LinkedIn - Videos de posts y Galerías de imágenes (descarga secuencial)
X (Twitter) - Videos de tweets (alta calidad garantizada)
TikTok - Videos sin marca de agua
Facebook - Videos públicos, Reels y enlaces share/v/ (múltiples fallbacks)
YouTube - Videos y Shorts (Calidad Optimizada hasta 1080p + Audio)
Pinterest - Videos e Imágenes (Pin original)
Twitch - Clips y VODs
Threads - Videos de posts (vía navegador headless en el backend residencial)


🏗️ Arquitectura híbrida (Railway + backend residencial)

Es un solo código (este repo). GitHub lo guarda; corre en dos lugares a la vez:

        Usuarios (celular / web)
                │
                ▼
   Railway (nube, URL pública fija)  ── contenido público → lo baja directo
                │
                │ contenido con login (Instagram/Facebook) o Threads
                ▼
   Tu PC (backend residencial, vía Cloudflare Tunnel)
     IP de casa + cookie de Meta + navegador (Playwright)

Por qué: Meta (Instagram/Facebook/Threads) bloquea las IPs de datacenter como la de Railway (HTTP 400 aunque la cookie sea válida). El pedido tiene que salir de una IP residencial. Entonces:

  • Railway es la única URL pública, siempre online. Sirve todo el contenido público (YouTube, TikTok, X, Pinterest, Twitch, LinkedIn, reels públicos).
  • Cuando un contenido exige login o es de Threads, Railway reenvía el pedido a tu PC (registrada vía Cloudflare Tunnel). Tu PC lo resuelve con IP residencial + cookie y devuelve el resultado. Transparente para el usuario.
  • Si tu PC está apagada: lo público sigue andando; lo de login/Threads no, hasta que la prendas.

Componentes:

  • src/server.py — endpoint /api/admin/set-fallback (tu PC registra su URL, protegido por ADMIN_SECRET) y reenvío automático en handle_extract cuando el resultado trae needs_remote o es login-gated.
  • home_tunnel.py — corre en tu PC: abre el túnel Cloudflare, captura la URL pública y la registra en Railway (re-registra cada 2 min y cuando la URL cambia).
  • tunnel.bat — un clic: levanta la app local + home_tunnel.py.
  • Playwright NO está en requirements.txt (Railway no lo instala); tu venv local sí lo tiene → por eso Threads corre solo en tu PC.

🚀 Características Principales

  • UI/UX Unificada: Misma experiencia para todas las plataformas desde una sola interfaz.
  • Calidad Optimizada:
    • YouTube: Selección inteligente de video (1080p/720p) + audio fusionado.
    • X/Twitter: Enrutamiento especial para evitar errores 403.
    • Instagram: Soporte para historias y cuentas privadas (usando cookies del navegador).
  • Descargas Inteligentes:
    • LinkedIn: Detecta si es video o galería. Si es galería, descarga imágenes secuencialmente (img-1, img-2...).
    • Archivos ZIP: Empaquetado automático para descargas múltiples.
  • Nombres de Archivo Unificados: Todas las descargas siguen el formato plataforma_titulo_fecha.ext (ej. instagram_Mar_del_Plata_Drone_20260702.mp4). Generado por buildFilename() en src/common/card.js.
  • Autenticación con Cookies (Instagram): Soporte para archivo de cookies Netscape en cookies/instagram.txt (o variable de entorno INSTAGRAM_COOKIES_FILE). Necesario porque Instagram exige login para la mayoría de los reels. Exportar con la extensión "Get cookies.txt LOCALLY". El directorio cookies/ está en .gitignore.
  • Interfaz Responsiva: Diseño moderno, adaptable a móviles y escritorio.
  • Logging Detallado: Información completa de resolución, bitrate y errores en consola.
  • API REST Local: Endpoints para validación y extracción, listos para integración.

📁 Estructura del Proyecto

c:\www\video-redes\
├── src/
│   ├── server.py                 # Servidor principal (Entry Point)
│   ├── common/                   # Recursos compartidos
│   │   ├── card.js               # Tarjeta de video + buildFilename()
│   │   ├── ytdlp_cmd.py          # Resolución del ejecutable yt-dlp (venv/PATH/módulo)
│   │   ├── cookies_util.py       # Combina todos los .txt de cookies/ en uno
│   │   └── style.css             # Estilos globales
│   ├── youtube/                  # Módulo YouTube
│   │   ├── youtube_extractor.py  # Extracción de videos/shorts
│   │   └── youtube.js            # Lógica de presentación
│   ├── instagram/                # Módulo Instagram
│   │   ├── insta_extractor.py    # Extracción con soporte cookies
│   │   └── insta.js              # Lógica de presentación
│   ├── tiktok/                   # Módulo TikTok
│   │   ├── tiktok_extractor.py   # Extracción con yt-dlp
│   │   └── tiktok.js             # Lógica de presentación
│   ├── facebook/                 # Módulo Facebook
│   │   ├── facebook_extractor.py # Extracción con fallbacks
│   │   └── facebook.js           # Lógica de presentación
│   ├── linkedin/                 # Módulo LinkedIn
│   │   ├── linkedin_extractor.py # Videos + galerías + PDFs
│   │   └── linkedin.js           # Lógica de presentación
│   ├── x/                        # Módulo X (Twitter)
│   │   ├── x_extractor.py        # Extracción de tweets
│   │   └── x.js                  # Lógica de presentación
│   ├── pinterest/                # Módulo Pinterest
│   │   ├── pinterest_extractor.py
│   │   └── pinterest.js
│   ├── twitch/                   # Módulo Twitch
│   │   ├── twitch_extractor.py
│   │   └── twitch.js
│   └── threads/                  # Módulo Threads (navegador headless)
│       ├── threads_extractor.py  # Playwright + intercepción de GraphQL
│       └── threads.js
├── tests/
│   └── routing_checks.py         # Tests del enrutado + diagnóstico de errores YouTube
├── scripts/
│   └── hooks/pre-commit          # Hook que estampa la versión (copiar a .git/hooks/)
├── mobile/                       # App Android (cáscara Capacitor sobre la URL de Railway)
│   ├── capacitor.config.json     # server.url apunta a Railway → la web no requiere recompilar
│   ├── build-apk.bat             # Genera el APK de debug
│   ├── android/                  # Proyecto Gradle (versionado como respaldo)
│   └── RedesDownloader-debug.apk # APK distribuible (versionado)
├── cookies/                      # (no versionado) *.txt de la extensión; se combinan solos
├── home_tunnel.py                # Backend residencial: túnel Cloudflare + registro en Railway
├── tunnel.bat                    # Un clic: app local + túnel (para usar tu PC de backend)
├── index.html                    # Frontend principal
├── p.ps1                         # Script de inicio rápido (PowerShell)
├── p.bat                         # Script de inicio rápido (CMD, activa .venv)
├── Procfile                      # Configuración para despliegue
├── requirements.txt              # Dependencias (Playwright NO está: queda fuera de Railway)
├── runtime.txt                   # Versión de Python
└── README.md                     # Esta documentación

🏗️ Arquitectura del Sistema

Stack Tecnológico

Capa Componente Propósito
Backend Python 3.11+ Lenguaje principal del servidor
Backend http.server + socketserver Servidor HTTP embebido con multithreading
Backend yt-dlp Biblioteca principal para extracción de videos
Backend imageio-ffmpeg Gestión de FFmpeg para procesamiento de video
Backend requests Cliente HTTP para scraping y proxy
Backend threading Manejo de descargas en segundo plano
Frontend HTML5 + CSS3 Estructura y estilos modernos
Frontend Vanilla JavaScript Lógica de cliente (ES6+)
Frontend SweetAlert2 Modales y notificaciones
Frontend Hls.js Reproducción de videos HLS (m3u8)

Diagrama de Arquitectura

flowchart TB
    subgraph Cliente
        UI[index.html + JavaScript]
        SWEET[SweetAlert2]
        HLS[Hls.js]
    end
    
    subgraph Servidor
        HTTP[ThreadedHTTPServer]
        API[API Endpoints]
        TASK[Task Manager]
    end
    
    subgraph Extractores
        YT[YouTube]
        IG[Instagram]
        TT[TikTok]
        FB[Facebook]
        LI[LinkedIn]
        X[X/Twitter]
        PI[Pinterest]
        TW[Twitch]
    end
    
    subgraph Core
        YTDLP[yt-dlp]
        FFMPEG[FFmpeg]
        REQ[requests]
    end
    
    UI --> HTTP
    HTTP --> API
    API --> TASK
    API --> Extractores
    Extractores --> YTDLP
    TASK --> YTDLP
    YTDLP --> FFMPEG
Loading

Flujo de Descarga

sequenceDiagram
    participant U as Usuario
    participant B as Browser
    participant S as Servidor
    participant Y as yt-dlp
    participant F as FFmpeg

    U->>B: Pegar URL
    B->>S: POST /api/validate
    S-->>B: URL válida ✓
    B->>S: POST /api/extract
    S->>Y: Extraer info
    Y-->>S: Metadatos + formatos
    S-->>B: JSON: preview_url + download_target{url, mode}
    B->>B: Renderizar tarjeta (usa preview_url)
    U->>B: Click en "Descargar"
    B->>S: GET /api/download_start (manda download_target)
    S->>S: Crear thread
    alt mode = source
        S->>Y: Descargar desde URL original
        Y->>F: Fusionar pistas separadas (si las hay)
        F-->>S: MP4 con audio ✓
    else mode = direct
        S->>S: Descarga progresiva del CDN
    else mode = gallery
        S->>S: Empaquetar en ZIP
    end
    loop Progreso
        B->>S: GET /api/download_status
        S-->>B: {progress: 45%}
    end
    S-->>B: Redirigir a archivo
    B->>U: Iniciar descarga
Loading

🔌 API Endpoints

GET Endpoints

Endpoint Descripción
/ Servir index.html
/api/download_start?url=...&filename=... Iniciar tarea de descarga
/api/download_cancel?id=task_id Cancelar descarga
/api/download_status?id=task_id Consultar estado
/api/download_file?id=task_id Descargar archivo completado (&inline=1 lo sirve para reproducir en vez de bajar; soporta Range/206 para adelantar)
/api/download?url=...&filename=... Descarga directa legacy
/admin/cookies Panel para actualizar la cookie compartida (requiere ADMIN_SECRET)

POST Endpoints

Endpoint Descripción
/api/validate Validar formato de URL
/api/extract Extraer información de video
/api/admin/cookies Actualizar la cookie compartida (requiere secret = ADMIN_SECRET)

Ejemplo de Respuesta (extract)

{
  "success": true,
  "title": "Video Title",
  "uploader": "Channel Name",
  "thumbnail": "https://...",
  "preview_url": "https://...mp4",
  "download_target": {
    "url": "https://www.youtube.com/watch?v=...",
    "mode": "source"
  },
  "video_url": "https://...mp4",
  "video_quality": "1080p",
  "duration": 120,
  "filesize": "50.5 MB",
  "platform": "YouTube"
}

preview_url vs download_target (importante): son dos cosas distintas a propósito. preview_url es la rendición del CDN que se usa para previsualizar en la tarjeta; download_target es lo que se descarga. Confundirlos es lo que producía videos mudos: si se descargaba la rendición del CDN tal cual, en las plataformas que sirven video y audio como pistas separadas el archivo salía sin sonido.

mode Qué hace Cuándo
source Pasa la URL original a yt-dlp: si hay pistas separadas las fusiona con FFmpeg; si ya viene muxeado lo deja intacto YouTube, TikTok, Twitch, Facebook (cuando yt-dlp resuelve)
direct Descarga progresiva directa del CDN/servicio externo Fallbacks manuales, fdown, getmyfb, CDN ya muxeado
gallery Lista de URLs empaquetada en ZIP LinkedIn/Pinterest con galerías de imágenes

El frontend normaliza siempre vía normalizeDownloadTarget() / getDownloadTarget() en src/common/card.js, que además acepta el formato viejo (original_url suelto) para no romper respuestas previas.


🛡️ Seguridad

Protección Descripción
SSRF Protection Validación de protocolo (solo http/https)
Path Traversal Validación de rutas con commonpath
Hostname Blocklist Bloqueo de IPs privadas locales
CORS Headers configurables por origen

💾 Instalación y Uso Local

1. Prerrequisitos

  • Python 3.11+: Asegúrate de tener Python instalado y agregado al PATH.
  • FFmpeg: Necesario para unir video y audio en alta calidad.
    • Windows: Descargar de ffmpeg.org y agregar bin al PATH.

2. Configuración Inicial

# Clonar/Descargar el repositorio
cd c:\www\video-redes

# Crear entorno virtual
python -m venv .venv

# Activar entorno (PowerShell)
.venv\Scripts\Activate.ps1

# Instalar dependencias
pip install -r requirements.txt

# Instalar el hook que estampa la versión en cada commit
copy scripts\hooks\pre-commit .git\hooks\pre-commit

El hook hay que instalarlo en cada clon. Git nunca versiona .git/hooks/, así que un clon nuevo arranca sin él y los commits salen con la versión vieja sin avisar. Por eso el fuente vive en scripts/hooks/ y se copia a mano.

Ojo con la zona horaria si lo tocás: el hook usa date a secas porque el reloj de la máquina ya está en hora argentina. No le pongas TZ='America/Argentina/Buenos_Aires': Git Bash en Windows no trae tzdata, cae a UTC en silencio y estampa 3 horas adelantado.

3. Ejecutar el Servidor

Opción A: Solo local (sin backend residencial)

.\p.ps1

Opción B: Como backend residencial de Railway (recomendado)

.\tunnel.bat

Esto levanta la app local y abre el túnel Cloudflare que la registra en Railway. Con esto andando en tu PC, el contenido con login (Instagram/Facebook) y Threads funciona desde la URL pública de Railway (celular incluido). Requiere cloudflared instalado (winget install Cloudflare.cloudflared) y la variable ADMIN_SECRET (la misma clave del panel admin de Railway).

4. Usar la Aplicación

  1. Abre tu navegador en http://localhost:8000 (o la URL de Railway)
  2. Pega el enlace de la red social
  3. El sistema detectará automáticamente la plataforma
  4. Haz clic en "Buscar" para ver la vista previa
  5. Haz clic en la tarjeta para descargar

Cookies (para contenido con login)

  • Exportá tus cookies con la extensión "Get cookies.txt LOCALLY" desde tu Chrome logueado en Instagram/Facebook/Threads.
  • Soltá los archivos tal cual (www.instagram.com_cookies.txt, www.facebook.com_cookies.txt, www.threads.com_cookies.txt) en la carpeta cookies/. La app combina todos los .txt en uno solo automáticamente (src/common/cookies_util.py); ante duplicados gana el archivo más nuevo.
  • La carpeta cookies/ está en .gitignore — nunca se sube a GitHub.

☁️ Despliegue en la Nube (Railway/Heroku)

El proyecto está configurado para desplegarse fácilmente ("Deploy Ready").

Archivos Clave:

  • Procfile: web: python src/server.py
  • runtime.txt: python-3.11
  • requirements.txt: Lista de librerías necesarias
  • Railway usa Railpack como builder. Con solo Procfile + requirements.txt + runtime.txt alcanza; no requiere config de build extra.

Pasos para Railway:

  1. Sube tu código a GitHub
  2. Crea nuevo proyecto en Railway desde GitHub
  3. Railway detectará el Procfile y desplegará automáticamente

Instagram en Railway: el servidor no tiene navegador ni filesystem persistente, así que el contenido que exige login necesita una cookie compartida (una sola sesión de Instagram usada para todos los visitantes — nadie inicia sesión con su propia cuenta).

Configuración inicial (una vez):

  1. Codificar el archivo local en Base64 (PowerShell):
    [Convert]::ToBase64String([IO.File]::ReadAllBytes("cookies\instagram.txt")) | Set-Clipboard
  2. En Railway → tu proyecto → Variables → crear INSTAGRAM_COOKIES_B64 y pegar el valor (queda en el portapapeles).
  3. Al arrancar, server.py decodifica esa variable a un archivo temporal y configura INSTAGRAM_COOKIES_FILE automáticamente.

Panel admin para renovarla sin volver a tocar Railway:

  • Configurar la variable ADMIN_SECRET (una contraseña elegida por vos) en Railway.
  • Entrar a https://tu-app.up.railway.app/admin/cookies, poner la clave, pegar el contenido nuevo de cookies/instagram.txt y guardar. Se actualiza al instante, sin reiniciar el server.
  • Sin ADMIN_SECRET configurada, el panel queda deshabilitado (403) — no expone nada si no lo activás.

Refresco automático: el servidor usa la cookie compartida cada 6 horas en segundo plano para extender su vigencia. Esto no la hace eterna — Instagram igual la vence eventualmente — pero reduce cuánto hay que estar pendiente de renovarla a mano.

Sin cookie configurada, en Railway solo funcionan los reels públicos (vía proxy de embeds); el resto necesita la cookie compartida.

Nota sobre login automático (descartado): se probó un login en vivo con Playwright (navegador automatizado en el server) para refrescar la cookie sin exportar/pegar a mano. No funciona: Instagram/Facebook detectan el navegador automatizado (reCAPTCHA con loop infinito de captchas) y además desconfían de la IP de datacenter de Railway. La única vía confiable es cargar una cookie nacida en un navegador real y logueado (IP residencial) vía la extensión "Get cookies.txt LOCALLY" y pegarla en /admin/cookies.


▶️ Reproductor inline (clic en la tarjeta)

Hacer clic en la preview reproduce el video dentro de la propia tarjeta. Descargar es responsabilidad exclusiva del botón de descarga.

Por qué se descarga al temporal antes de reproducir (y no se apunta el <video> directo al preview_url, que sería instantáneo):

El preview_url es la rendición del CDN, y en las plataformas que sirven video y audio como pistas separadas puede venir sin audio — el mismo motivo por el que las descargas salían mudas. Reproducirlo directo mostraría el video en silencio sin que nadie se entere. El archivo temporal ya pasó por yt-dlp+FFmpeg, así que tiene audio garantizado.

A diferencia de la descarga, la reproducción no abre modal de progreso: solo un spinner discreto sobre la miniatura mientras se prepara el archivo.

Detalles que hacen que funcione de verdad:

  • /api/download_file acepta &inline=1 → responde Content-Disposition: inline en vez de attachment, para que el navegador reproduzca en lugar de bajar.
  • El endpoint soporta Range requests (206 Partial Content + Accept-Ranges). Sin esto no se puede arrastrar la barra de tiempo, y Safari/iOS directamente se niega a reproducir. Rango simple únicamente; fuera de rango responde 416.
  • El <video> usa object-fit: contain (no cover como la miniatura): la tarjeta es 9:16 y un video horizontal quedaría recortado a los costados.
  • Las galerías no son reproducibles → el clic cae a la descarga ZIP de siempre.

Limitación conocida: yt-dlp puede devolver el video en AV1. Chrome y Edge lo reproducen sin problema; Safari viejo y algunos iOS no. En esos casos el archivo se descarga bien igual, pero el reproductor inline puede quedar en negro.


📱 App Android (APK)

La app de Android no es una copia de la web: es una cáscara delgada (Capacitor) que carga el sitio vivo de Railway. En mobile/capacitor.config.json:

"server": { "url": "https://redes-download.up.railway.app" }

El mobile/www/index.html es solo un placeholder que dice "Cargando…" mientras levanta la URL real.

La consecuencia práctica (y la que más confunde):

Qué cambiaste ¿Hay que recompilar el APK?
HTML / CSS / JS del frontend ❌ No — la app lo toma de Railway al abrirse
Extractores, server.py, backend ❌ No — corre en Railway, no en el teléfono
Plugins de Capacitor, permisos, capacitor.config.json ✅ Sí
Ícono, nombre, versión nativa, AndroidManifest ✅ Sí

O sea: pusheás a Railway y el APK ya instalado se actualiza solo. No hay que redistribuir el APK por cada arreglo de la web.

Construir el APK:

cd mobile
.\build-apk.bat

Deja el resultado en mobile/RedesDownloader-debug.apk (versionado en el repo como respaldo distribuible).

Gotcha del JDK: mobile/android/gradle.properties fija org.gradle.java.home porque el JAVA_HOME de la máquina apunta a JDK 17 y este proyecto necesita 21. Apunta a C:/Program Files/Java/latest/jdk-21, que es un enlace que mantiene el instalador de Oracle — no a una ruta con patch fijo tipo jdk-21.0.11. Java se auto-actualiza de patch y una ruta fija deja el build roto con Java home supplied is invalid.


🔧 Detalles Técnicos de los Extractores

YouTube Extractor

  • Detecta YouTube Shorts automáticamente
  • Prioriza formatos progresivos (video+audio)
  • Detecta calidad máxima DASH
  • Calcula tamaño estimado

Instagram Extractor

Cadena de extracción (de más rápido a más lento):

  1. URLs directas de CDN (cdninstagram.com) — sin extracción
  2. yt-dlp anónimo
  3. Archivo de cookies cookies/instagram.txt (recomendado — Instagram exige login para la mayoría de los reels desde 2026)
  4. Proxy de embeds (kkinstagram, estilo InstaFix) — resuelve reels públicos sin login, redirige al mp4 del CDN oficial
  5. Cookies del navegador Chrome/Edge/Firefox (último recurso; falla si el navegador está abierto, y Chrome moderno usa App-Bound Encryption que yt-dlp no puede desencriptar)

Detecta los errores de autenticación modernos ("empty media response", "login required", "rate-limit").

LinkedIn Extractor

  • Videos (yt-dlp)
  • Galerías de imágenes (JSON-LD parsing)
  • Documentos PDFs (native document config)

Facebook Extractor

Cadena de extracción:

  1. yt-dlp (web, luego reintenta con ID de reel y modo móvil si falla)
  2. yt-dlp con la cookie compartida (cookies/instagram.txt) — resuelve reels/videos que exigen login, incluidos facebook.com/reel/...
  3. Scraping manual: og:video + playable_url (web y móvil)
  4. Servicio externo fdown.net
  5. Servicio externo getmyfb.com (endpoint /process) — resuelve enlaces share/v/ que exigen login y devuelve el título real del video

TikTok Extractor

  • yt-dlp con formato bestvideo+bestaudio

X/Twitter Extractor

  • yt-dlp con merge_output_format=mp4
  • Selección de mejor calidad por resolución

Pinterest Extractor

  • Soporte para pins de video e imagen

Twitch Extractor

  • Clips y VODs via yt-dlp

Threads Extractor

  • yt-dlp NO soporta Threads y el video no está en el HTML (lo carga por GraphQL autenticado).
  • Se abre el post en un Chromium headless (Playwright) con la cookie de Meta y se intercepta la respuesta de red buscando browser_native_hd_url / browser_native_sd_url / video_versions (la URL .mp4 del CDN).
  • Playwright se importa perezosamente: en Railway (sin Playwright) devuelve needs_remote=True y el servidor reenvía al backend residencial (tu PC), que sí lo tiene. Por eso Threads siempre corre en tu PC.
  • Es la red más lenta (~10-15 s por video: abrir navegador + cargar + capturar).

🆘 Solución de Problemas Comunes

Error: "Instagram exige iniciar sesión" / "empty media response"

  • Causa: Instagram exige login para la mayoría de los reels (comportamiento desde 2026). No es un bug de la app.
  • Solución recomendada (permanente): Exportar cookies con la extensión "Get cookies.txt LOCALLY" en Chrome (logueado en Instagram) y guardarlas como cookies/instagram.txt. Funciona local y en Railway.
  • Alternativa: Cerrar completamente Chrome/Edge para que yt-dlp lea las cookies del navegador. Nota: Chrome moderno (v127+) cifra las cookies con App-Bound Encryption y yt-dlp puede fallar con "Failed to decrypt with DPAPI" — en ese caso la extensión es la única vía.
  • Las cookies caducan: si el error reaparece tras semanas, re-exportar el archivo.

Error: Facebook "No se pudo extraer la URL del video"

  • Causa: Los enlaces facebook.com/share/v/... suelen exigir login.
  • Solución: Ya está cubierto — el extractor cae automáticamente en getmyfb.com como último recurso. Si aun así falla, el video puede ser privado o de un grupo cerrado.

Error: "403 Forbidden" en X/Twitter

  • Solución: Ya está parchado internamente. El sistema usa twimg.com para evitar el bloqueo.

Error: "FFmpeg not found"

  • Solución: Instala FFmpeg y agrégalo a tus variables de entorno.

La descarga es lenta en local

  • Causa: El video se descarga primero a tu carpeta temporal y luego se te envía.
  • Normalidad: Es el comportamiento esperado para garantizar que el archivo final esté limpio.

⚠️ Aviso Legal

Esta herramienta ha sido creada con fines educativos y de uso personal.

  • Respeta los derechos de autor y la propiedad intelectual.
  • No descargues ni redistribuyas contenido privado sin consentimiento.
  • El usuario es responsable del uso que le dé a esta herramienta.

📋 Novedades v.33 (Julio 2026)

  • yt-dlp actualizado a 2026.6.9 (corrige el aviso "version older than 90 days") junto con todas las dependencias. pydub eliminada (sin uso e incompatible con Python 3.13+).
  • Instagram: nueva cadena de fallbacks — archivo de cookies (cookies/instagram.txt) + proxy de embeds (kkinstagram) para reels públicos sin login. Detección de los errores de autenticación modernos.
  • Facebook: nuevo fallback getmyfb.com para enlaces share/v/ que exigen login.
  • Nombres de archivo unificados: plataforma_titulo_fecha.ext en las 8 plataformas (helper buildFilename() compartido).
  • Resolución robusta de yt-dlp: src/common/ytdlp_cmd.py localiza el ejecutable (venv → PATH → módulo Python); los extractores ya no dependen del PATH.
  • server.py: lógica de reintentos de Instagram unificada en download_with_instagram_auth() (archivo de cookies → Chrome → Edge → Firefox).
  • p.bat ahora activa el entorno virtual antes de arrancar (igual que p.ps1).
  • server.log fuera del control de versiones (queda solo local).

📋 Novedades v.38 (Julio 2026)

  • Panel admin (/admin/cookies, protegido por ADMIN_SECRET) para actualizar la cookie compartida sin tocar Railway/terminal.
  • Refresco automático de sesión: la cookie compartida se usa cada 6 horas en segundo plano para extender su vigencia.
  • Cookies compartidas vía INSTAGRAM_COOKIES_B64: soporte para pasar el archivo de cookies como variable de entorno Base64 en despliegues sin filesystem persistente (Railway).
  • Facebook: nuevo reintento con la cookie compartida antes de rendirse, arregla facebook.com/reel/... que exigen login.

📋 Novedades v.58 (Julio 2026)

  • Arquitectura híbrida (Railway + backend residencial): Railway reenvía el contenido con login (Instagram/Facebook) y Threads a tu PC vía Cloudflare Tunnel, porque Meta bloquea las IPs de datacenter (HTTP 400 aun con cookie válida). Tu PC lo resuelve con IP residencial. Una sola URL pública para todos. Ver sección "Arquitectura híbrida".
  • Threads: soporte nuevo vía navegador headless (Playwright) que intercepta el GraphQL de Meta. Corre solo en tu PC (Playwright no está en Railway). Logo agregado.
  • Cookies multi-archivo: la app combina TODOS los .txt de cookies/ (soporta los per-dominio de la extensión: www.instagram.com_cookies.txt, etc.). Ante duplicados gana el más nuevo.
  • Reparación de cookies pegadas: /admin/cookies arregla tabs→espacios (causa de "empty media response" falsos).
  • home_tunnel.py + tunnel.bat: un clic levanta la app + túnel y la registra en Railway (re-registra cuando la URL del quick tunnel cambia).
  • Playwright eliminado de Railway: el login-en-vivo automatizado se descartó (Instagram/Facebook lo bloquean con reCAPTCHA); la carga de cookies es por pegado/archivo.

📋 Novedades v.26.0807 (Agosto 2026)

  • Audio arreglado en todas las plataformas: se separó preview_url (lo que se previsualiza) de download_target {url, mode} (lo que se descarga). Antes, las plataformas que sirven video y audio como pistas separadas se descargaban copiando la rendición del CDN tal cual → el archivo salía mudo. Ahora el modo source pasa la URL original a yt-dlp, que fusiona las pistas con FFmpeg y deja intacto lo que ya viene muxeado. Los fallbacks directos (fdown, getmyfb, CDN) y el ZIP de galerías siguen igual.
  • Facebook: reintento de descarga con la cookie combinada.
  • Tests: tests/routing_checks.py cubre el enrutado de los tres modos.
  • Nuevo esquema de versión: el header pasó de un contador (v.4, v.58) a un timestamp v.YY.MMDD build(HH.MM) en hora argentina, en dos líneas (nombre grande arriba, versión abajo). Así se ve de un vistazo cuándo se cortó el build que está vivo en Railway, no solo que cambió.
  • Hook pre-commit: estampa la versión y re-stagea index.html en cada commit, para que el sello viaje dentro de ese mismo commit. El fuente versionado está en scripts/hooks/pre-commit; se instala copiándolo a .git/hooks/ (ver "Instalación").
  • .codegraph/ ignorado: índice local por máquina, nunca se comparte entre checkouts.
  • YouTube: se dejó de ocultar el motivo del fallo. El fallback de formato básico capturaba el stderr de yt-dlp, lo imprimía y lo descartaba, devolviendo el mismo texto genérico para todo: bloqueo por IP de datacenter, video privado, rate-limit o timeout se veían idénticos. Peor: _looks_login_gated() decide si reenviar al backend residencial leyendo ese error, así que nunca reconocía los fallos de YouTube y el reenvío —que ya existía y funcionaba— jamás se activaba. Ahora el stderr crudo viaja en detail y la causa reconocida se anexa al error.
  • Build de Android arreglado: gradle.properties apuntaba a jdk-21.0.11, que dejó de existir cuando Java se auto-actualizó a 21.0.12. Ver "App Android (APK)".
  • Reproductor en la tarjeta: el clic sobre la preview ahora reproduce el video ahí mismo en vez de descargarlo; descargar quedó como responsabilidad exclusiva del botón. Ver "Reproductor inline".

Sobre el timestamp: no se puede meter la fecha/hash de un commit dentro de ese commit — el hash se calcula sobre el contenido, así que escribirlo adentro lo cambia. El hook estampa justo antes de crear el commit; la diferencia es de segundos y alcanza de sobra para confirmar qué build está desplegado.


Documentación actualizada: Agosto 2026
📧 Contacto: julio.corbaz@gmail.com 🌐 Página Web Oficial: https://redes-download.up.railway.app/ Versión del proyecto: v.YY.MMDD build(HH.MM) — ver el header de la app

About

Download de Videos de Redes Sociales

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages