API de videos de Twitter: obtén la URL MP4 de cualquier video de X
La URL MP4 de un video de Twitter está en los datos de medios del post: X codifica cada subida en hasta cinco versiones MP4, de 270p a 1080p o más, y lista la URL de cada archivo con su bitrate.
Respuesta corta: Toma el MP4 con el bitrate más alto; un GIF es un MP4 silencioso. La API oficial de X lista las versiones solo con media.fields=variants, a $10.00 por cada 1,000 posts con video desde el 22 de noviembre de 2026. Sorsa API devuelve el enlace de video de cada post con POST /tweet-info-bulk, 100 posts por solicitud desde $0.014 por cada 1,000, y 100 solicitudes gratis cubren los primeros 10K.
- Endpoint
POST /tweet-info-bulk- Tamaño de página
- 100 posts por solicitud
- Precio
- desde $0.014 por cada 1,000
#Cómo guarda X un video: versiones y bitrates
X nunca sirve el archivo que subió el autor. Recodifica cada video en una escalera de archivos MP4, uno por tamaño, y en una lista de reproducción HLS (un índice .m3u8 que los reproductores de video usan para cambiar de tamaño durante la reproducción). Cada MP4 es un archivo completo con sonido, así que cualquiera de ellos se descarga y se reproduce por sí solo. Para un solo post, el Descargador de videos de Twitter, gratuito, guarda el archivo a partir de un enlace pegado; esta guía es para obtener los archivos en código.
El 2 de noviembre de 2026 leímos las listas de versiones de 23 posts públicos de 2017 a 2026 y medimos los 72 archivos MP4 que X sirvió para ellos. El bitrate que X lista para cada archivo es un techo, y los archivos reales son de tres a cinco veces más livianos:
| Versión | Tamaño de cuadro, píxeles | Bitrate que lista X | Bitrate promedio real |
|---|---|---|---|
| 270p | 480 × 270 | 256 kbps | unos 91 kbps |
| 360p | 640 × 360 | 832 kbps | unos 233 kbps |
| 720p | 1280 × 720 | 2,176 kbps | unos 626 kbps |
| 1080p | 1920 × 1080 | 10.4 Mbps | unos 2,172 kbps |
270p
- Tamaño de cuadro, píxeles
- 480 × 270
- Bitrate que lista X
- 256 kbps
- Bitrate promedio real
- unos 91 kbps
360p
- Tamaño de cuadro, píxeles
- 640 × 360
- Bitrate que lista X
- 832 kbps
- Bitrate promedio real
- unos 233 kbps
720p
- Tamaño de cuadro, píxeles
- 1280 × 720
- Bitrate que lista X
- 2,176 kbps
- Bitrate promedio real
- unos 626 kbps
1080p
- Tamaño de cuadro, píxeles
- 1920 × 1080
- Bitrate que lista X
- 10.4 Mbps
- Bitrate promedio real
- unos 2,172 kbps
Lo que muestran las mediciones:
- El bitrate más alto es el mejor archivo. Ordena las entradas MP4 por bitrate y toma la primera. La entrada de la lista de reproducción, de tipo
application/x-mpegURL, no trae bitrate y es un índice, no un archivo. - El tamaño depende de la forma del cuadro. Los videos verticales reciben de 320 × 568 hasta 1080 × 1920, los cuadrados de 320 × 320 hasta 1080 × 1080, y una subida de 1936 × 1548 recibió un quinto archivo a 25.1 Mbps.
- No toda subida en 1080p recibe un archivo 1080p. De siete subidas de 1920 × 1080 de 2025 y 2026, dos se quedaron en 720p, y la mayoría de los posts anteriores a 2022 llegan como máximo a 720p.
- La lista de reproducción separa el sonido de la imagen. Sus flujos de video son silenciosos; el audio llega como pistas separadas a 32, 64 y 128 kbps, con subtítulos en algunos videos.
Un GIF es más simple: X guarda un MP4 silencioso y en bucle al tamaño propio del GIF, sin otras versiones y sin lista de reproducción.
#Obtén la URL MP4 de un video con Sorsa API
Sorsa API, una API y scraper de Twitter (X), devuelve cada post con sus medios adjuntos: cada video, GIF y foto es una entrada en la lista entities del post con un type, un link directo y una imagen preview. Una API key en un encabezado reemplaza la cuenta de desarrollador y el OAuth que pide la API oficial de X.
-
Obtén una clave. Regístrate y copia la API key desde tu panel. Las primeras 100 solicitudes son gratis, sin tarjeta.
-
Envía el enlace del post.
POST /tweet-info(se abre en una pestaña nueva) admite una URL de post o un ID a secas entweet_link.Terminal curl -X POST "https://api.sorsa.io/v3/tweet-info" \ -H "ApiKey: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"tweet_link": "https://x.com/northfield_video_lab/status/1984519203377641472"}'Response200 OK { "id": "1984519203377641472", "created_at": "2026-10-31T16:04:11Z", "full_text": "First ride on the new gravel loop.", "entities": [ { "type": "video", "link": "https://video.twimg.com/amplify_video/1984519110025023488/vid/avc1/480x270/Qm3vTb8xLwK2pRfA.mp4?tag=21", "preview": "https://pbs.twimg.com/amplify_video_thumb/1984519110025023488/img/Hx2LkP9aQwErT0bn.jpg" } ], "user": { "username": "northfield_video_lab", "display_name": "Northfield Video Lab", "media_count": 214 } } -
Lee las entradas de video. Conserva las entidades cuyo
typeseavideoy cuyolinkesté en video.twimg.com. Una ruta/tweet_video/en el enlace marca un GIF. -
Descarga el archivo. El MP4 es un archivo HTTPS simple en los servidores de X: sin clave, sin cookie y sin que se cuente ninguna solicitud.
import requests API = "https://api.sorsa.io/v3/tweet-info" HEADERS = {"ApiKey": "YOUR_API_KEY"} def video_links(post): r = requests.post(API, headers=HEADERS, json={"tweet_link": post}, timeout=60) r.raise_for_status() # 403: no key, or no requests left tweet = r.json() for e in tweet.get("entities") or []: if e.get("type") == "video" and "video.twimg.com" in e["link"]: yield tweet["id"], e["link"] links = video_links("1984519203377641472") for n, (post_id, link) in enumerate(links, 1): with open(f"{post_id}_{n}.mp4", "wb") as f: f.write(requests.get(link, timeout=120).content)
El link es un MP4 con sonido que se reproduce en cualquier parte. El 2 de noviembre de 2026 pasamos dos videos por nuestro descargador gratuito, que funciona sobre Sorsa API, y ambos enlaces eran la versión 270p de X. Para el de 82 segundos eso significó 1.1 MB: lo bastante liviano para vistas previas, transcripciones, muestreo de cuadros y archivos grandes. El enlace de un GIF es su único archivo, así que llega completo.
El preview sirve también como cuadro a tamaño completo: agrégale ?format=jpg&name=orig (quitando antes el .jpg) y X devuelve el cuadro al tamaño propio de la subida, 1936 × 1548 píxeles en uno de nuestros posts de prueba. Las fotos vienen en la misma lista con type photo; obtener cada una a su tamaño original, de un post o de una cuenta entera, se cubre en la guía del scraper de imágenes de Twitter.
Para una lista de posts, envía hasta 100 enlaces o IDs en tweet_links a POST /tweet-info-bulk (se abre en una pestaña nueva). La respuesta es {"tweets": [...]} con las mismas entities en cada post, y todo el lote es una solicitud: desde $0.014 por cada 1,000 posts.
#Descarga todos los videos de una cuenta o de una búsqueda
La búsqueda encuentra los posts con video por ti. El operador de búsqueda de X filter:native_video conserva los posts con un video subido a X, y card_name:animated_gif conserva los GIF. POST /search-tweets (se abre en una pestaña nueva) devuelve unos 20 posts coincidentes por solicitud, con una búsqueda que llega hasta 2006.
| Tarea | Consulta |
|---|---|
| Todos los videos de una cuenta | from:northfield_video_lab filter:native_video |
| Todos los GIF de una cuenta | from:northfield_video_lab card_name:animated_gif |
| Videos sobre un tema en un mes | "gravel racing" filter:native_video since:2026-10-01 until:2026-11-01 |
| Solo videos populares | #bikepacking filter:native_video min_faves:1000 |
| Videos y enlaces de YouTube | trail build filter:videos |
Todos los videos de una cuenta
- Consulta
from:northfield_video_lab filter:native_video
Todos los GIF de una cuenta
- Consulta
from:northfield_video_lab card_name:animated_gif
Videos sobre un tema en un mes
- Consulta
"gravel racing" filter:native_video since:2026-10-01 until:2026-11-01
Solo videos populares
- Consulta
#bikepacking filter:native_video min_faves:1000
Videos y enlaces de YouTube
- Consulta
trail build filter:videos
Cada operador, con ejemplos, está en la guía de operadores de búsqueda de Twitter. El script de abajo ejecuta una consulta de la primera página a la última.
-
Guarda el script. Recorre la búsqueda con
next_cursor, un token que marca dónde empieza la página siguiente, hasta que el cursor llegue vacío. Escribe los videos y GIF de cada post en<post id>_<n>.mp4y registra cada archivo envideos.csv.x_videos.py import csv import os import subprocess import sys import time import requests API = "https://api.sorsa.io/v3/search-tweets" HEADERS = {"ApiKey": "YOUR_API_KEY"} def search(body): while True: r = requests.post(API, headers=HEADERS, json=body, timeout=60) if r.status_code == 429: # over 20 requests a second: wait time.sleep(1) continue r.raise_for_status() # 403: no key, or no requests left return r.json() def videos(tweet): """(kind, link) for every video and GIF in a post.""" for e in tweet.get("entities") or []: link = e.get("link") or "" if e.get("type") == "video" and "video.twimg.com" in link: yield ("gif" if "/tweet_video/" in link else "video"), link def save(link, path): with requests.get(link, stream=True, timeout=120) as r: r.raise_for_status() with open(path, "wb") as f: for chunk in r.iter_content(1 << 16): f.write(chunk) def save_hd(post_url, n, path): """The post's highest-bitrate MP4 through yt-dlp; False if yt-dlp fails.""" cmd = ["yt-dlp", "-f", "best[protocol=https]", "--playlist-items", str(n), "-o", path, post_url] done = subprocess.run(cmd, capture_output=True).returncode == 0 return done and os.path.exists(path) def run(query, folder, hd=False): os.makedirs(folder, exist_ok=True) state = os.path.join(folder, "cursor.txt") body = {"query": query, "order": "latest"} if os.path.exists(state): # resume a stopped run body["next_cursor"] = open(state).read().strip() log_path = os.path.join(folder, "videos.csv") with open(log_path, "a", newline="", encoding="utf-8") as f: log = csv.writer(f) while True: page = search(body) for t in page.get("tweets", []): for n, (kind, link) in enumerate(videos(t), 1): path = os.path.join(folder, f"{t['id']}_{n}.mp4") if os.path.exists(path): continue url = f"https://x.com/{t['user']['username']}/status/{t['id']}" if not (hd and kind == "video" and save_hd(url, n, path)): save(link, path) log.writerow([t["id"], t["created_at"], kind, os.path.getsize(path), path]) cursor = page.get("next_cursor") if not cursor: break body["next_cursor"] = cursor with open(state, "w") as s: s.write(cursor) if os.path.exists(state): os.remove(state) if __name__ == "__main__": run(sys.argv[1], sys.argv[2], hd="--hd" in sys.argv[3:]) -
Ejecútalo con una consulta y una carpeta.
python x_videos.py "from:northfield_video_lab filter:native_video" northfieldguarda los videos de la cuenta en la carpetanorthfield. Un 403 significa que falta la clave o que se acabaron las solicitudes; un 429 significa más de 20 solicitudes en un segundo, y el script espera un segundo y reintenta. -
Vuelve a ejecutarlo cuando quieras. Los archivos que ya están en disco se omiten y el cursor se guarda después de cada página. Una ejecución detenida retoma donde se quedó, y una nueva ejecución agrega solo los videos nuevos.
Los videos de una cuenta entera toman pocas solicitudes: a unos 20 posts por página, una cuenta con 300 videos son unas 15 solicitudes, porque la búsqueda devuelve solo los posts que llevan uno. Para el texto y todos los demás campos del post en una hoja de cálculo, consulta cómo descargar todos los tweets de un usuario.
#Descarga el archivo 720p o 1080p de un post
Para el archivo 720p o 1080p de un post, pásale su enlace a yt-dlp, el descargador de línea de comandos de código abierto, que lee posts públicos sin iniciar sesión en X. El filtro de formato de abajo elige el MP4 con el bitrate más alto:
yt-dlp -f "best[protocol=https]" -o "%(id)s.%(ext)s" "https://x.com/northfield_video_lab/status/1984519203377641472"
Agrega --hd al script de arriba y hará esto con cada video, con el enlace de la API como respaldo cuando yt-dlp falle. En nuestro video de prueba de 82 segundos, yt-dlp 2026.10.26 eligió el archivo de 1920 × 1080. Su tabla de formatos, ejecutada con -F, mostraba ese archivo con unos 100 MiB, porque la tabla multiplica el bitrate indicado por la duración; la descarga pesó 22.2 MB. yt-dlp descarga un post a la vez desde tu propia dirección IP, así que Sorsa API se encarga de encontrar los videos en bloque y yt-dlp solo de los archivos HD que necesitas.
Para tener en cuenta
La API oficial de X devuelve la lista completa de versiones en una sola respuesta, pero solo si la pides. Agrega
expansions=attachments.media_keysymedia.fields=variantsa una consulta de post, y cada video vuelve enincludes.mediacon un arreglovariantsdebit_rate,content_typeyurl. Necesita una cuenta de desarrollador y OAuth, y desde el 22 de noviembre de 2026 cada objeto multimedia de esa respuesta se cobra a $0.005, además de los $0.005 de la lectura del post.
#Los GIF de Twitter en la API
Un GIF publicado en X vuelve como un MP4, porque X convierte cada GIF en un video corto, silencioso y en bucle cuando se publica. Su enlace está en video.twimg.com/tweet_video/, X no guarda otro tamaño, y ese único archivo es la mejor copia que existe. En los datos de X se tipifica como animated_gif con un bitrate de 0; en las entities de Sorsa API llega como un video cuyo enlace tiene esa ruta /tweet_video/.
Para convertirlo de nuevo en un archivo .gif, ejecuta ffmpeg con una pasada de paleta, que mantiene los colores limpios:
ffmpeg -i 1211797914437259264_1.mp4 \
-vf "fps=15,split[a][b];[a]palettegen[p];[b][p]paletteuse" \
-loop 0 1211797914437259264.gif
Espera un archivo mucho más grande: en nuestra prueba un MP4 de 83 KB se convirtió en un GIF de 1.76 MB con los mismos 498 × 272 píxeles, 21 veces el tamaño. Conserva el MP4 para almacenar y para los reproductores, y crea el GIF solo donde una página o un chat lo necesite. Para un solo GIF sin código, el Descargador de GIF de Twitter, gratuito, lo guarda a partir del enlace de un post.
#Cuánto cuesta, en solicitudes y en almacenamiento
En Sorsa API un post cuesta lo mismo sea cual sea el medio que lleve. Los posts consultados por ID cuestan desde $0.014 por cada 1,000, 100 por solicitud, y los posts encontrados por búsqueda desde $0.07 por cada 1,000, unos 20 por solicitud. Los archivos de video se descargan de los servidores de X y no cuestan solicitudes. En la API oficial de X cada video llega por la expansión de medios, y desde el 22 de noviembre de 2026 X cobra los objetos de expansión (se abre en una pestaña nueva) a la tarifa estándar. Un post con video cuesta entonces $0.005 por el post más $0.005 por sus medios: $10.00 por cada 1,000.
| Forma de obtener los enlaces de video | Qué necesita | Costo por cada 1,000 posts con video |
|---|---|---|
| Sorsa API, posts por ID | Una API key | desde $0.014 |
| Sorsa API, búsqueda | Una API key | desde $0.07 |
| API oficial de X | Cuenta de desarrollador y OAuth | $10.00 desde el 22 de nov de 2026 |
Sorsa API, posts por ID
- Qué necesita
- Una API key
- Costo por cada 1,000 posts con video
- desde $0.014
Sorsa API, búsqueda
- Qué necesita
- Una API key
- Costo por cada 1,000 posts con video
- desde $0.07
API oficial de X
- Qué necesita
- Cuenta de desarrollador y OAuth
- Costo por cada 1,000 posts con video
- $10.00 desde el 22 de nov de 2026
API oficial de X
$10,000
para 1M posts con video
$0.010 por post con video, desde el 22 de nov
Sorsa API
desde$14
para 1M posts con video
desde $0.014 por cada 1,000
714 veces más barato
El pago por uso (se abre en una pestaña nueva) de la API oficial de X también se detiene en 3M de lecturas de posts por ciclo de facturación, y por encima de eso X vende solo contratos Enterprise. Sorsa API corre a 20 solicitudes por segundo en todos los planes, así que los lotes de 100 posts consultan 2,000 posts con video por segundo, y las solicitudes fallidas nunca se cobran.
El almacenamiento es la factura más grande de un archivo de videos, y depende de la versión mucho más que de la cantidad. Con los bitrates promedio reales que medimos, 1,000 videos de treinta segundos ocupan unos 0.3 GB en 270p, 2.3 GB en 720p y 8.1 GB en 1080p. Fija tu propia duración y cantidad:
| Versión | Por video | Todos los videos | Tope |
|---|---|---|---|
| 270p | 0.34 MB | 341 MB | 0.96 MB |
| 360p | 0.87 MB | 874 MB | 3.1 MB |
| 720p | 2.3 MB | 2.3 GB | 8.2 MB |
| 1080p | 8.1 MB | 8.1 GB | 38.9 MB |
Por video: la mediana del bitrate real por versión (91, 233, 626 y 2,172 kbps). Tope: el bitrate que X indica (256, 832 y 2,176 kbps, y 10.4 Mbps) multiplicado por la duración.
Los tamaños por video salen de los bitrates promedio reales de 63 archivos MP4 medidos en los servidores de X el 2 de noviembre de 2026; el tope usa el bitrate que indica X.
#Empieza a obtener videos de X en código
Para obtener en código las URL MP4 de videos y GIF de X, usa Sorsa API: una solicitud devuelve hasta 100 posts con el enlace de cada video, desde $0.014 por cada 1,000. La búsqueda encuentra todos los videos de una cuenta o de un tema hasta 2006, y tu cuenta de X nunca interviene. Copia el script, agrega tu clave, y tus 100 solicitudes gratis devuelven los enlaces de tus primeros 10K posts con video.
#Preguntas frecuentes
¿La API oficial de X puede devolver URLs de videos de Twitter?
Sí. Agrega expansions=attachments.media_keys y media.fields=variants a una consulta o búsqueda de posts, y cada video en includes.media lista sus versiones MP4 con bit_rate y url; toma la de mayor bitrate. Sin esos dos parámetros obtienes solo una imagen de vista previa. Requiere una cuenta de desarrollador y OAuth, y desde el 22 de noviembre de 2026 cada objeto de medios suma $0.005 a los $0.005 de la lectura del post.
¿Qué API debo usar para obtener URLs de videos de Twitter?
Usa Sorsa API. POST /tweet-info-bulk devuelve hasta 100 posts por solicitud con el enlace MP4 y la vista previa de cada video, desde $0.014 por cada 1,000 posts. La API oficial de X cobra $10.00 por cada 1,000 posts con video desde el 22 de noviembre de 2026. Sorsa API necesita una API key en lugar de una cuenta de desarrollador y OAuth, encuentra videos por búsqueda hasta 2006 y corre a 20 solicitudes por segundo en todos los planes.
¿Por qué se ve borroso el video de Twitter que descargué?
Lo más probable es que hayas guardado una de las versiones más pequeñas. X guarda cada video como hasta cinco archivos MP4, de 270p a 1080p o más, y algunas herramientas y API entregan la primera o la más liviana. Elige el MP4 con el bitrate más alto de la lista. Si el mejor archivo sigue siendo 720p, la subida no recibió una versión 1080p: dos de las siete subidas 1080p de 2025 y 2026 que revisamos se quedaron en 720p.
¿Puedo descargar videos de cuentas privadas o de posts eliminados?
No. Los posts de una cuenta protegida solo los ven los seguidores que ella aprueba, así que ninguna API devuelve sus videos, Sorsa API incluida, y una solicitud por ellos nunca se cobra. Los posts eliminados desaparecen de la búsqueda y las consultas de X, así que ninguna API puede listarlos tampoco; solo una copia guardada antes de la eliminación conserva el video.
¿Es legal descargar videos de X?
Sí. Guardar videos públicos para investigación, moderación o un archivo es legal y habitual. Los derechos de autor siguen siendo de quien hizo cada video, así que pide permiso al dueño antes de publicar o revender los archivos. Sorsa API lee posts públicos con su propia API, así que tu cuenta de X no participa.
#Cómo lo verificamos
El 2 de noviembre de 2026 leímos las listas de versiones que X publica para 23 posts públicos con videos y GIF de 2017 a 2026 y medimos 72 de sus 75 archivos MP4 que sirvió video.twimg.com. De un video leímos además su lista de reproducción HLS y listamos sus formatos con yt-dlp 2026.10.26, sin iniciar sesión. Pasamos tres de los posts por nuestro descargador gratuito, que funciona sobre Sorsa API, para ver los enlaces que devuelve. El script se ejecutó contra un sustituto de la API que servía esos enlaces reales, y la línea de ffmpeg se ejecutó con un archivo GIF real. Los endpoints y campos salen de la referencia de API en vivo de Sorsa API; los campos de medios y los precios de X salen de docs.x.com y del aviso de X del 23 de octubre de 2026, leídos el mismo día.
Fuentes
- Sorsa API reference: Tweet Data (se abre en una pestaña nueva)
- Sorsa API reference: Tweet Data (Batch) (se abre en una pestaña nueva)
- Sorsa API reference: Search Tweets (se abre en una pestaña nueva)
- X API data dictionary: media object (se abre en una pestaña nueva)
- X API pricing (se abre en una pestaña nueva)
- X API PPU: Expansions Update, October 23, 2026 (se abre en una pestaña nueva)
- yt-dlp on GitHub (se abre en una pestaña nueva)