Ir al contenido

Feed RSS de Twitter para cualquier cuenta o Lista de X

X no publica feeds RSS, así que un feed RSS de Twitter hay que construirlo: un script lee en JSON los posts más recientes de una cuenta, unos 20 por solicitud, y los reescribe como un archivo RSS 2.0 que tu lector consulta.

Respuesta corta: Con una actualización cada 15 minutos, un feed consume unas 2,880 solicitudes al mes, y una Lista pública de X reúne hasta 5,000 cuentas en esa misma solicitud única. Para construirlo, usa Sorsa API: POST /user-tweets devuelve 20 posts por solicitud desde $0.07 por 1,000, y las 100 solicitudes gratis cubren tus primeros 2,000 posts.

Endpoint
POST /user-tweets
Tamaño de página
20 posts por solicitud
Precio
desde $0.07 por 1,000 posts

#¿X tiene un feed RSS?

No. X no tiene feed RSS para perfiles, búsquedas ni Listas: si añades /rss a la dirección de un perfil, x.com responde con su página web normal, lo que comprobamos el 2 de noviembre de 2026. Todo feed RSS de Twitter que funciona hoy lo genera alguien a partir de datos de X, así que la decisión real es sobre qué lo construyes y quién lo mantiene en marcha.

Las opciones ya hechas traen condiciones:

  • La ruta de X en RSSHub ahora solo funciona con la cookie auth_token de una cuenta de X con sesión iniciada o con claves de la API oficial de X, según el código fuente de la ruta. Una cookie ata el feed a una cuenta real y pone esa cuenta en riesgo.
  • Los generadores de feeds alojados venden el feed como una suscripción, y sus planes deciden cuántos posts guarda cada feed y con qué frecuencia se actualiza.

El RSS sigue vivo. Feedly, Inoreader, NetNewsWire, FreshRSS, Miniflux y el nodo RSS Read de n8n se suscriben a RSS 2.0, así que un feed que construyas se conecta con las herramientas que ya usas. Si prefieres un aviso en el celular o en Slack en lugar de un feed, mira cómo recibir un aviso cuando alguien tuitea.

#Cómo se construye un feed RSS de Twitter

Un feed RSS de Twitter lleva cinco pasos, y solo el primero toca datos de X. Lo demás es un script corto y un temporizador.

  1. Obtén los posts más recientes en JSON. Una solicitud devuelve los últimos 20 posts de una cuenta con texto, fecha, multimedia y autor.

  2. Conserva lo que ya tienes. Un pequeño archivo de estado evita repeticiones y permite que el feed guarde más de una página.

  3. Convierte cada post en un elemento RSS. El título, el enlace, la fecha y el texto van a los elementos que entiende cualquier lector.

  4. Escribe el archivo XML. Escríbelo primero en un archivo temporal y reemplaza el anterior, para que un lector nunca descargue un feed a medias.

  5. Actualiza con un horario. Cada 15 a 60 minutos sirve para la mayoría de los feeds.

    Cada 15 minutos: una solicitud, un archivo nuevo 1 Sorsa API /user-tweets 20 posts más nuevos en JSON 2 Tu script x_rss.py guarda 50 posts, los convierte en items 3 Archivo del feed feed.xml RSS 2.0, servido desde tu servidor 4 Tu lector Feedly, Inoreader, NetNewsWire, FreshRSS o n8n Entrada: una cuenta de X, una Lista pública o una búsqueda Consulta el archivo con su propio temporizador
    Solo el primer paso lee datos de X; el script, el archivo y el lector son tuyos.

Para el paso de los datos, usa Sorsa API, una API y scraper de Twitter (X): una solicitud POST /user-tweets devuelve los 20 posts más recientes de una cuenta como JSON limpio con una sola clave API, sin cuenta de desarrollador, y nunca te pide tu login de X. El esquema de la respuesta se mantiene igual de una versión a otra, así que un script de feed que escribas hoy sigue funcionando.

Cinco elementos de RSS llevan todo lo que muestra un lector, y cada uno corresponde a un campo de esa respuesta:

Elemento RSSCampo de Sorsa APIPor qué importa
titleprimeros 80 caracteres de full_textLos lectores listan los elementos por título
link y guidhttps://x.com/ + user.username + /status/ + idUn guid estable evita repeticiones
pubDatecreated_at, ISO 8601RSS pide fechas en RFC 822
descriptionfull_text más las imágenes de entities[].previewEl post como HTML
dc:creatoruser.display_nameEl author de RSS debe ser un correo
  • title

    Campo de Sorsa API
    primeros 80 caracteres de full_text
    Por qué importa
    Los lectores listan los elementos por título
  • link y guid

    Campo de Sorsa API
    https://x.com/ + user.username + /status/ + id
    Por qué importa
    Un guid estable evita repeticiones
  • pubDate

    Campo de Sorsa API
    created_at, ISO 8601
    Por qué importa
    RSS pide fechas en RFC 822
  • description

    Campo de Sorsa API
    full_text más las imágenes de entities[].preview
    Por qué importa
    El post como HTML
  • dc:creator

    Campo de Sorsa API
    user.display_name
    Por qué importa
    El author de RSS debe ser un correo

#Obtén los posts de una cuenta en JSON

Envía el handle de la cuenta a POST /user-tweets y los 20 posts más recientes llegan en una sola respuesta. Tres pasos te llevan de cero a esa primera respuesta.

  1. Consigue una clave. Regístrate y copia tu clave API del panel. Las primeras 100 solicitudes son gratis y nunca vencen.

  2. Llama al endpoint. Envía el nombre de usuario en un cuerpo JSON con tu clave en el encabezado ApiKey. La lista completa de parámetros está en la referencia de user tweets (se abre en una pestaña nueva).

    Terminal
    curl -X POST "https://api.sorsa.io/v3/user-tweets" \
      -H "ApiKey: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"username": "nasa_launch_desk"}'
    
    Respuesta200 OK
    {
      "tweets": [
        {
          "id": "1985012345678901234",
          "full_text": "Static fire complete. Launch window opens Thursday.",
          "created_at": "2026-11-02T14:05:00Z",
          "lang": "en",
          "likes_count": 1840,
          "retweet_count": 312,
          "reply_count": 95,
          "view_count": 120400,
          "is_reply": false,
          "entities": [
            {
              "type": "photo",
              "link": "https://t.co/k3x9demo",
              "preview": "https://pbs.twimg.com/media/demo-static-fire.jpg"
            }
          ],
          "user": {
            "id": "1700000000000000042",
            "username": "nasa_launch_desk",
            "display_name": "Launch Desk"
          }
        }
      ],
      "next_cursor": "DAABCgABG8a1demoAAA"
    }
    
  3. Elige qué muestra el feed. type escoge posts (el valor por defecto), replies o retweets, y with_replies: true mezcla las respuestas con los posts. next_cursor trae los 20 posts anteriores siguientes.

Cada post también incluye el perfil completo del autor, así que un feed nunca necesita una segunda solicitud para nombres o avatares. Un 403 significa que falta la clave o que no quedan solicitudes, un 429 significa más de 20 solicitudes en un segundo, y las solicitudes fallidas nunca se cobran.

#Convierte el JSON en RSS con Python

El script de abajo convierte ese JSON en un archivo RSS 2.0 válido usando solo la biblioteca estándar de Python, así que no hay nada que instalar. Sirve para una cuenta, una Lista o una búsqueda, y recuerda los últimos 50 posts entre ejecuciones.

x_rss.py
"""Write an RSS 2.0 feed of an X account, List or search.

python x_rss.py user nasa_launch_desk
python x_rss.py list 1700000000000000001
python x_rss.py search "from:nasa_launch_desk OR #artemis"
"""
import json
import os
import sys
import urllib.parse
import urllib.request
from datetime import datetime
from email.utils import format_datetime
from xml.sax.saxutils import escape

API = "https://api.sorsa.io/v3"
KEY = os.environ.get("SORSA_API_KEY", "YOUR_API_KEY")
KEEP = 50       # posts the feed keeps
MAX_PAGES = 5   # pages one run may read to catch up


def page(kind, target, cursor):
    if kind == "list":
        query = {"list_id": target}
        if cursor:
            query["next_cursor"] = cursor
        url = API + "/list-tweets?" + urllib.parse.urlencode(query)
        req = urllib.request.Request(url)
    else:
        if kind == "user":
            path, body = "/user-tweets", {"username": target}
        else:
            path, body = "/search-tweets", {"query": target,
                                            "order": "latest"}
        if cursor:
            body["next_cursor"] = cursor
        req = urllib.request.Request(
            API + path, data=json.dumps(body).encode(),
            headers={"Content-Type": "application/json"})
    req.add_header("ApiKey", KEY)
    with urllib.request.urlopen(req, timeout=30) as resp:
        return json.load(resp)


def fetch_new(kind, target, seen):
    new, cursor = [], None
    for _ in range(MAX_PAGES):
        data = page(kind, target, cursor)
        tweets = data.get("tweets") or []
        new += [t for t in tweets if t["id"] not in seen]
        cursor = data.get("next_cursor")
        caught_up = any(t["id"] in seen for t in tweets)
        if not cursor or not seen or caught_up:
            break
    return new


def to_item(t):
    user = t.get("user") or {}
    name = user.get("username", "")
    link = f"https://x.com/{name}/status/{t['id']}"
    text = " ".join(t.get("full_text", "").split())
    when = datetime.fromisoformat(t["created_at"].replace("Z", "+00:00"))
    pics = "".join(f'<p><img src="{escape(e["preview"])}"></p>'
                   for e in t.get("entities") or []
                   if e.get("type") == "photo" and e.get("preview"))
    author = escape(user.get("display_name") or name)
    xml = ("<item>"
           f"<title>{escape(text[:80])}</title>"
           f"<link>{link}</link>"
           f'<guid isPermaLink="true">{link}</guid>'
           f"<pubDate>{format_datetime(when)}</pubDate>"
           f"<dc:creator>{author}</dc:creator>"
           f"<description>{escape(escape(text) + pics)}</description>"
           "</item>")
    return {"id": t["id"], "date": when.isoformat(), "xml": xml}


def main(kind, target):
    safe = (c if c.isalnum() or c in "_-" else "-" for c in target)
    name = "".join(safe)[:60]
    state, feed = name + ".json", name + ".xml"
    items = []
    if os.path.exists(state):
        with open(state, encoding="utf-8") as f:
            items = json.load(f)
    seen = {i["id"] for i in items}
    items += [to_item(t) for t in fetch_new(kind, target, seen)]
    items = sorted(items, key=lambda i: i["date"], reverse=True)[:KEEP]
    with open(state, "w", encoding="utf-8") as f:
        json.dump(items, f)
    home = {"user": f"https://x.com/{target}",
            "list": f"https://x.com/i/lists/{target}"}
    title = escape(f"X {kind}: {target}")
    xml = ('<?xml version="1.0" encoding="UTF-8"?>'
           '<rss version="2.0" '
           'xmlns:dc="http://purl.org/dc/elements/1.1/"><channel>'
           f"<title>{title}</title>"
           f"<link>{home.get(kind, 'https://x.com/')}</link>"
           f"<description>{title}, built with Sorsa API</description>"
           + "".join(i["xml"] for i in items) + "</channel></rss>")
    with open(feed + ".tmp", "w", encoding="utf-8") as f:
        f.write(xml)
    os.replace(feed + ".tmp", feed)
    print(f"{feed}: {len(items)} posts")


if __name__ == "__main__":
    main(sys.argv[1], sys.argv[2])

Tres detalles hacen que este feed se comporte mejor que una simple conversión de una página:

  • Nunca pierde una ráfaga. Cuando una cuenta publica más de 20 veces entre ejecuciones, el script sigue next_cursor hacia atrás hasta encontrar un post que ya tiene, hasta 5 páginas.
  • Guarda 50 posts, no 20. El archivo de estado en JSON conserva los posts anteriores, así que un día tranquilo no deja el feed vacío.
  • Pasa las comprobaciones habituales de un validador de feeds. Las fechas están en RFC 822, cada elemento tiene un guid permanente, el autor va en dc:creator y el HTML del post se escapa una sola vez para XML.

Ejecuta python x_rss.py user nasa_launch_desk y el archivo nasa_launch_desk.xml aparece junto al script. La primera ejecución cuesta una solicitud; cada ejecución posterior cuesta una solicitud más una por cada página adicional que necesite para ponerse al día.

#Un solo feed para una Lista completa o una búsqueda

Una Lista pública de X convierte hasta 5,000 cuentas en un solo feed que cuesta lo mismo que el feed de una cuenta. Con Sorsa API, GET /list-tweets devuelve en una página cronológica los posts más recientes de todos los miembros de la Lista, así que el feed gasta una solicitud por actualización sin importar cuántas cuentas siga.

200 cuentas, actualizadas cada 15 minutos Solicitudes al mes, 30 días Un feed por cuenta 200 solicitudes por actualización 576K Un feed de Lista en Sorsa API 1 solicitud por actualización 2,880
Los feeds separados multiplican las solicitudes por el número de cuentas; el feed de una Lista no.

Seguir 200 cuentas como feeds separados cada 15 minutos toma 576K solicitudes al mes; las mismas 200 cuentas en una Lista toman 2,880. Para configurarlo, crea una Lista pública en la app de X (o usa la Lista pública de otra persona), copia el número del final de su dirección (x.com/i/lists/<number>) y pásalo como list_id. La referencia de List tweets (se abre en una pestaña nueva) tiene los parámetros, y la guía de la API de Listas de Twitter también cubre miembros y seguidores.

Terminal
python x_rss.py list 1700000000000000001

Un feed de búsqueda funciona igual con POST /search-tweets y order en latest. Úsalo para un puñado de cuentas sin crear una Lista, o para un tema:

Consultas de feeds de búsqueda
from:nasa_launch_desk OR from:orbit_news_digest
#artemis -filter:replies
"launch window" lang:en min_faves:50

Aquí funciona todo operador de búsqueda de X, hasta 2006; la guía de operadores de búsqueda de Twitter los enumera con ejemplos, y la referencia de search tweets (se abre en una pestaña nueva) tiene el formato de la solicitud. Una Lista o un hashtag muy activos pueden publicar más de 20 veces entre actualizaciones: el script entonces lee páginas adicionales, una solicitud cada una, así que actualiza los feeds muy activos con más frecuencia, no con menos.

#Prográmalo y suscríbete

Un feed se mantiene al día cuando el script corre con un temporizador y un servidor web le entrega el archivo a tu lector. En cualquier servidor Linux, dos líneas en tu crontab guardan la clave y actualizan el feed cada 15 minutos:

crontab -e
SORSA_API_KEY=YOUR_API_KEY
*/15 * * * * cd /srv/feeds && python3 x_rss.py user nasa_launch_desk

Después sirve la carpeta. Cualquier servidor web que ya corra en la máquina (nginx, Caddy, Apache) puede publicar /srv/feeds; un lector autoalojado como FreshRSS o Miniflux en el mismo servidor puede leer el archivo desde una dirección local. Para una prueba rápida, python3 -m http.server 8080 --directory /srv/feeds lo sirve en http://localhost:8080/nasa_launch_desk.xml.

Pega la dirección del feed en el cuadro "Add feed" de tu lector. Configura el lector para que actualice con una frecuencia no mayor que la de cron: un lector que revisa cada 5 minutos ve el mismo archivo tres de cada cuatro veces.

Para tener en cuenta

La URL de un feed es para tu propio lector o para las herramientas de tu equipo. Mantenla detrás de una ruta larga y aleatoria o del inicio de sesión de tu lector, en lugar de en una página pública: los posts que contiene pertenecen a sus autores, y el feed lleva solo posts públicos.

#Sirve el feed desde n8n

n8n puede servir el mismo feed en su propia URL con cuatro nodos y sin un servidor tuyo. Cada vez que tu lector pide esa URL, el flujo llama una vez a Sorsa API y responde con XML nuevo.

  1. Añade un nodo Webhook. Define HTTP Method como GET, dale una ruta larga y aleatoria, y define Respond como "Using 'Respond to Webhook' Node".

  2. Añade un nodo HTTP Request. Haz POST a https://api.sorsa.io/v3/user-tweets con el encabezado ApiKey y envía el cuerpo JSON {"username": "nasa_launch_desk"}.

  3. Añade un nodo Code. Convierte el arreglo tweets en elementos RSS; el código está en el flujo de abajo.

  4. Añade un nodo Respond to Webhook. Define Respond With como Text, arrastra el campo xml del nodo Code a Response Body y añade el encabezado de respuesta Content-Type con application/rss+xml; charset=utf-8.

  5. Activa el flujo. Suscribe tu lector a la Production URL del nodo Webhook.

    Flujo de n8n: cuatro nodos, una URL de feed
    1. WebhookFeed URLGET, responde desde el último nodo
    2. HTTP RequestSorsa API user tweetsPOST /user-tweets, header ApiKey
    3. CodeBuild RSStweets a ítems RSS 2.0
    4. Respond to WebhookReturn the feedTexto, application/rss+xml
    const tweets = $input.first().json.tweets || [];
    const esc = (s) => String(s).replace(/&/g, '&amp;')
      .replace(/</g, '&lt;').replace(/>/g, '&gt;');
    const items = tweets.map((t) => {
      const link = 'https://x.com/' + t.user.username + '/status/' + t.id;
      const text = t.full_text.replace(/\s+/g, ' ');
      return '<item><title>' + esc(text.slice(0, 80)) + '</title>' +
        '<link>' + link + '</link>' +
        '<guid isPermaLink="true">' + link + '</guid>' +
        '<pubDate>' + new Date(t.created_at).toUTCString() + '</pubDate>' +
        '<description>' + esc(esc(text)) + '</description></item>';
    }).join('');
    const xml = '<?xml version="1.0" encoding="UTF-8"?>' +
      '<rss version="2.0"><channel><title>X feed</title>' +
      '<link>https://x.com/</link>' +
      '<description>Built with Sorsa API</description>' +
      items + '</channel></rss>';
    return [{ json: { xml } }];

    En n8n, pega el JSON en un lienzo vacío, pon tu clave en el nodo HTTP Request, activa el flujo y suscríbete a la Production URL.

    El nodo Code convierte el arreglo tweets de Sorsa API en RSS 2.0; el JSON del flujo trae los cuatro nodos de una vez.

Aquí el intervalo de actualización del lector fija el costo: un lector que revisa cada hora gasta 720 solicitudes al mes en el feed. Para feeds de Listas o de búsqueda, cambia la URL y el cuerpo del nodo HTTP Request. Si los posts solo alimentan el resto de un flujo (Slack, Sheets, un paso de IA), omite el RSS y lee el JSON directamente, como muestra la guía de la API de Twitter en n8n.

#Cuánto cuesta un feed RSS de Twitter

Un feed RSS de Twitter cuesta una solicitud por actualización, así que su precio depende de la frecuencia con que se actualiza y de cuántos feeds tienes, no de cuánto publican las cuentas. En un mes de 30 días:

Actualización cadaSolicitudes al mes, un feedFeeds en las 10K solicitudes de Starter
5 minutos8,6401
15 minutos2,8803
30 minutos1,4406
1 hora72013
6 horas12083
  • 5 minutos

    Solicitudes al mes, un feed
    8,640
    Feeds en las 10K solicitudes de Starter
    1
  • 15 minutos

    Solicitudes al mes, un feed
    2,880
    Feeds en las 10K solicitudes de Starter
    3
  • 30 minutos

    Solicitudes al mes, un feed
    1,440
    Feeds en las 10K solicitudes de Starter
    6
  • 1 hora

    Solicitudes al mes, un feed
    720
    Feeds en las 10K solicitudes de Starter
    13
  • 6 horas

    Solicitudes al mes, un feed
    120
    Feeds en las 10K solicitudes de Starter
    83
Actualizar cada
Solicitudes al mes 2,880 1 solicitud por feed por actualización, 30 días
Plan de Sorsa API que lo cubre Starter 10K solicitudes al mes por $49, espacio para 3 feeds de este tipo

Cuenta cada Lista o búsqueda como un feed, sin importar cuántas cuentas siga.

Cuando las páginas llegan llenas, como en una Lista muy activa o en una primera ejecución, Sorsa API entrega posts desde $0.07 por 1,000. La API oficial de X cobra $5.00 por 1,000 posts leídos en su precio de pago por uso (se abre en una pestaña nueva), después de una cuenta de desarrollador y una app de OAuth, y limita el pago por uso a 3 millones de lecturas de posts al mes. A partir del 22 de noviembre de 2026, X también cobra el autor y la multimedia de cada post que se devuelven mediante expansiones, a $0.010 por usuario, según el aviso de X del 23 de octubre (se abre en una pestaña nueva).

#Construye tu primer feed hoy

Un feed RSS de Twitter es un script de unas 100 líneas y un temporizador, y lo único que no puedes escribir tú mismo son los datos. Para eso, usa Sorsa API: una solicitud por actualización, 20 posts por solicitud, una Lista completa de hasta 5,000 cuentas en un solo feed y 20 solicitudes por segundo en todos los planes. Usa una sola clave API en lugar de una cuenta de desarrollador y nunca te pide tu login de X. Tus 100 solicitudes gratis traen tus primeros 2,000 posts, suficientes para construir el feed y verlo actualizarse antes de elegir un plan.

#Preguntas frecuentes

¿Con qué frecuencia debe actualizarse un feed RSS de Twitter?

Cada 15 a 60 minutos sirve para la mayoría de los feeds RSS de Twitter. Un feed que se actualiza cada 15 minutos usa 2,880 solicitudes al mes, y uno cada hora usa 720, porque cada actualización es una solicitud. Haz coincidir la actualización de tu lector con el horario del script, y actualiza con más frecuencia las Listas o los hashtags muy activos para que cada ejecución se ponga al día en una o dos páginas.

¿Existe un feed RSS de Twitter gratis?

X no ofrece un feed RSS propio, ni gratis ni de pago. La forma gratuita de empezar son las 100 solicitudes gratis de Sorsa API: no piden tarjeta, nunca vencen y traen unos 2,000 posts, suficientes para construir, probar y mantener un feed unos días antes de elegir un plan.

¿Puedo obtener mi timeline de inicio de X como feed RSS?

No directamente, porque el timeline de inicio pertenece a una cuenta con sesión iniciada. La copia práctica es una Lista: añade las cuentas que sigues a una Lista pública de X en la app de X y construye un feed a partir de ella con GET /list-tweets. Una Lista admite hasta 5,000 cuentas y cuesta una solicitud por actualización, igual que una sola cuenta.

¿RSSHub sigue funcionando con Twitter?

La ruta de X en RSSHub todavía existe, pero ahora necesita una cuenta de X con sesión iniciada o claves de la API oficial de X. El código fuente de la ruta indica dos formas de acceso: la cookie auth_token de una cuenta de X con sesión iniciada o claves de pago por uso de la API oficial de X. Un feed construido con Sorsa API usa una sola clave API y nunca te pide tu login de X.

¿Puedo crear un feed RSS de una cuenta protegida de X?

No. Los posts de las cuentas protegidas solo los ven los seguidores aprobados, así que ninguna herramienta de feeds ni API puede leerlos. Sorsa API devuelve solo datos públicos, así que tampoco los lee. Los feeds funcionan con cualquier cuenta pública, cualquier Lista pública y cualquier búsqueda de posts públicos.

¿Qué API debo usar para construir un feed RSS de Twitter?

Usa Sorsa API para construir un feed RSS de Twitter: POST /user-tweets devuelve 20 posts por solicitud desde $0.07 por 1,000, GET /list-tweets reúne hasta 5,000 cuentas en un solo feed con una solicitud por actualización, y todos los planes permiten 20 solicitudes por segundo. Usa una sola clave API y nunca te pide tu login de X, así que ninguna cuenta tuya corre riesgo.

#Cómo lo comprobamos

El 2 de noviembre de 2026 pedimos x.com/NASA/rss y obtuvimos la página web de X en lugar de un feed, leímos la página de precios de X y su aviso del 23 de octubre sobre la facturación de expansiones, y leímos el código fuente de la ruta de X en RSSHub y el de los nodos Webhook y Respond to Webhook de n8n en GitHub. Las solicitudes, la respuesta y el script siguen la referencia de la API en vivo de Sorsa API; en esta pasada no teníamos una clave de prueba, así que la respuesta muestra los campos documentados con valores de ejemplo.

Por el equipo de Sorsa API. Creamos y operamos Sorsa API, la API y scraper de Twitter/X de solo lectura, en producción desde 2022 (antes TweetScout API) y con más de 6 mil millones de solicitudes procesadas. Acerca de Sorsa API

Qué cambió
  • Primera publicación.