Pular para o conteúdo

Feed RSS do Twitter para qualquer conta ou List do X

O X não publica feeds RSS, então um feed RSS do Twitter precisa ser construído: um script lê os posts mais novos de uma conta como JSON, cerca de 20 por requisição, e os reescreve como um arquivo RSS 2.0 que o seu leitor consulta.

Resposta curta: Atualizado a cada 15 minutos, um feed leva cerca de 2.880 requisições por mês, e uma List pública do X reúne até 5.000 contas nessa mesma requisição única. Para montá-lo, use a Sorsa API: o POST /user-tweets devolve 20 posts por requisição a partir de US$ 0,07 por 1.000, e 100 requisições grátis cobrem seus primeiros 2.000 posts.

Endpoint
POST /user-tweets
Tamanho da página
20 posts por requisição
Preço
a partir de US$ 0,07 por 1.000 posts

#O X tem feed RSS?

Não. O X não tem feed RSS para perfis, buscas ou Lists: acrescente /rss ao endereço de um perfil e o x.com responde com a sua página web comum, o que confirmamos em 2 de novembro de 2026. Todo feed RSS do Twitter que funciona hoje é gerado por alguém a partir de dados do X, então a escolha de verdade é sobre o que você usa para construí-lo e quem o mantém funcionando.

As rotas prontas vêm com condições:

  • A rota do X no RSSHub agora só roda com o cookie auth_token de uma conta do X logada ou com chaves da API oficial do X, segundo o código-fonte da rota. Um cookie amarra o feed a uma conta real e põe essa conta em risco.
  • Geradores de feed hospedados vendem o feed como assinatura, e os planos deles decidem quantos posts cada feed guarda e com que frequência é atualizado.

O RSS em si está vivo. Feedly, Inoreader, NetNewsWire, FreshRSS, Miniflux e o nó RSS Read do n8n assinam RSS 2.0, então um feed que você constrói se encaixa nas ferramentas que você já usa. Se você quer um aviso no celular ou no Slack em vez de um feed, veja como receber um aviso quando alguém tuitar.

#Como um feed RSS do Twitter é construído

Um feed RSS do Twitter tem cinco etapas, e só a primeira toca nos dados do X. O resto é um script curto e um agendador.

  1. Busque os posts mais novos como JSON. Uma requisição devolve os 20 posts mais recentes de uma conta, com texto, data, mídia e autor.

  2. Guarde o que você já tem. Um pequeno arquivo de estado evita repetições e deixa o feed manter mais de uma página.

  3. Converta cada post em um item RSS. Título, link, data e texto vão para os elementos que todo leitor entende.

  4. Escreva o arquivo XML. Escreva primeiro num arquivo temporário e troque depois, para que o leitor nunca baixe um feed pela metade.

  5. Atualize em intervalos regulares. De 15 a 60 minutos serve para a maioria dos feeds.

    A cada 15 minutos: uma requisição, um arquivo novo 1 Sorsa API /user-tweets 20 posts mais novos em JSON 2 Seu script x_rss.py guarda 50 posts, converte em itens 3 O arquivo do feed feed.xml RSS 2.0, servido do seu servidor 4 Seu leitor Feedly, Inoreader, NetNewsWire, FreshRSS ou n8n Entrada: uma conta do X, uma Lista pública ou uma busca Consulta o arquivo no próprio ritmo
    Só a primeira etapa lê dados do X; o script, o arquivo e o leitor são seus.

Para a etapa dos dados, use a Sorsa API, uma API e scraper do Twitter (X): uma requisição POST /user-tweets devolve os 20 posts mais novos de uma conta como JSON limpo com uma única chave de API, sem conta de desenvolvedor, e ela nunca pede o login do seu X. O esquema da resposta é o mesmo de uma versão para outra, então um script de feed que você escreve hoje continua funcionando.

Cinco elementos RSS carregam tudo o que um leitor mostra, e cada um corresponde a um campo dessa resposta:

Elemento RSSCampo da Sorsa APIPor que importa
titleprimeiros 80 caracteres de full_textOs leitores listam os itens pelo título
link e guidhttps://x.com/ + user.username + /status/ + idUm guid estável evita repetições
pubDatecreated_at, ISO 8601O RSS pede datas RFC 822
descriptionfull_text mais as imagens de entities[].previewO post em HTML
dc:creatoruser.display_nameO author do RSS precisa ser um e-mail
  • title

    Campo da Sorsa API
    primeiros 80 caracteres de full_text
    Por que importa
    Os leitores listam os itens pelo título
  • link e guid

    Campo da Sorsa API
    https://x.com/ + user.username + /status/ + id
    Por que importa
    Um guid estável evita repetições
  • pubDate

    Campo da Sorsa API
    created_at, ISO 8601
    Por que importa
    O RSS pede datas RFC 822
  • description

    Campo da Sorsa API
    full_text mais as imagens de entities[].preview
    Por que importa
    O post em HTML
  • dc:creator

    Campo da Sorsa API
    user.display_name
    Por que importa
    O author do RSS precisa ser um e-mail

#Pegue os posts de uma conta como JSON

Envie o handle da conta ao POST /user-tweets e os 20 posts mais novos voltam numa única resposta. Três passos levam você do zero a essa primeira resposta.

  1. Pegue uma chave. Cadastre-se e copie a sua chave de API no painel. As primeiras 100 requisições são grátis e nunca expiram.

  2. Chame o endpoint. Envie o nome de usuário num corpo JSON com a sua chave no cabeçalho ApiKey. A lista completa de parâmetros está na referência de tweets do usuário (abre em uma nova aba).

    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"}'
    
    Response200 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. Escolha o que o feed mostra. O type escolhe posts (o padrão), replies ou retweets, e with_replies: true mistura respostas aos posts. O next_cursor busca os 20 posts mais antigos seguintes.

Cada post também traz o perfil completo do autor, então um feed nunca precisa de uma segunda requisição para nomes ou avatares. Um 403 significa chave ausente ou sem requisições, um 429 significa mais de 20 requisições em um segundo, e requisições com falha nunca são cobradas.

#Transforme o JSON em RSS com Python

O script abaixo transforma esse JSON num arquivo RSS 2.0 válido usando apenas a biblioteca padrão do Python, então não há nada para instalar. Ele funciona para uma conta, uma List ou uma busca, e lembra os últimos 50 posts entre as execuções.

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])

Três detalhes fazem este feed se comportar melhor do que uma conversão simples de uma página:

  • Ele nunca perde uma rajada. Quando uma conta publica mais de 20 vezes entre duas execuções, o script segue o next_cursor para trás até encontrar um post que já tem, em até 5 páginas.
  • Ele guarda 50 posts, não 20. O arquivo de estado JSON mantém os posts anteriores, então um dia parado não esvazia o feed.
  • Ele passa pelas verificações usuais de um validador de feeds. As datas são RFC 822, todo item tem um guid permanente, o autor fica em dc:creator e o HTML do post é escapado uma vez para XML.

Rode python x_rss.py user nasa_launch_desk e o arquivo nasa_launch_desk.xml aparece ao lado do script. A primeira execução custa uma requisição; cada execução seguinte custa uma requisição mais uma por página extra de que precisar para se atualizar.

#Um feed para uma List inteira ou para uma busca

Uma List pública do X transforma até 5.000 contas em um feed que custa o mesmo que o feed de uma única conta. Com a Sorsa API, o GET /list-tweets devolve os posts mais novos de todos os membros da List numa só página cronológica, então o feed gasta uma requisição por atualização, não importa quantas contas siga.

200 contas, atualizadas a cada 15 minutos Requisições por mês, 30 dias Um feed por conta 200 requisições a cada atualização 576K Um feed de Lista na Sorsa API 1 requisição a cada atualização 2,880
Feeds separados multiplicam as requisições pelo número de contas; um feed de List não.

Acompanhar 200 contas como feeds separados a cada 15 minutos leva 576 mil requisições por mês; as mesmas 200 contas numa só List levam 2.880. Para configurar, crie uma List pública no app do X (ou use a List pública de outra pessoa), copie o número no fim do endereço (x.com/i/lists/<number>) e passe-o como list_id. A referência de tweets de List (abre em uma nova aba) tem os parâmetros, e o guia da API de Lists do Twitter cobre também membros e seguidores.

Terminal
python x_rss.py list 1700000000000000001

Um feed de busca funciona do mesmo jeito pelo POST /search-tweets, com order definido como latest. Use-o para um punhado de contas sem criar uma List, ou para um assunto:

Search feed queries
from:nasa_launch_desk OR from:orbit_news_digest
#artemis -filter:replies
"launch window" lang:en min_faves:50

Todos os operadores de busca do X funcionam aqui, até 2006; o guia de operadores de busca do Twitter os lista com exemplos, e a referência de busca de tweets (abre em uma nova aba) tem o formato da requisição. Uma List ou hashtag movimentada pode publicar mais de 20 vezes entre duas atualizações: o script então lê páginas extras, uma requisição cada, então atualize os feeds movimentados com mais frequência, não menos.

#Rode em intervalos regulares e assine

Um feed se mantém atualizado quando o script roda num agendador e um servidor web entrega o arquivo ao seu leitor. Em qualquer servidor Linux, duas linhas no seu crontab guardam a chave e atualizam o feed a cada 15 minutos:

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

Depois sirva a pasta. Qualquer servidor web que já rode na máquina (nginx, Caddy, Apache) pode publicar /srv/feeds; um leitor auto-hospedado como FreshRSS ou Miniflux no mesmo servidor pode ler o arquivo de um endereço local. Para um teste rápido, python3 -m http.server 8080 --directory /srv/feeds o serve em http://localhost:8080/nasa_launch_desk.xml.

Cole o endereço do feed na caixa "Adicionar feed" do seu leitor. Configure o leitor para atualizar com frequência igual ou menor que a do cron: um leitor que consulta a cada 5 minutos vê o mesmo arquivo três vezes em cada quatro.

Bom saber

Um endereço de feed serve ao seu próprio leitor ou às ferramentas da sua equipe. Mantenha-o atrás de um caminho aleatório longo ou do login do seu leitor, e não numa página pública: os posts nele pertencem aos seus autores, e o feed leva apenas posts públicos.

#Sirva o feed pelo n8n em vez disso

O n8n pode servir o mesmo feed no seu próprio endereço com quatro nós e sem servidor seu. Cada vez que o seu leitor busca esse endereço, o workflow chama a Sorsa API uma vez e responde com XML novo.

  1. Adicione um nó Webhook. Defina HTTP Method como GET, dê a ele um caminho aleatório longo e defina Respond como "Using 'Respond to Webhook' Node".

  2. Adicione um nó HTTP Request. Faça um POST para https://api.sorsa.io/v3/user-tweets com o cabeçalho ApiKey e envie o corpo JSON {"username": "nasa_launch_desk"}.

  3. Adicione um nó Code. Ele transforma o array tweets em itens RSS; o código está no workflow abaixo.

  4. Adicione um nó Respond to Webhook. Defina Respond With como Text, arraste o campo xml do nó Code para Response Body e adicione o cabeçalho de resposta Content-Type com application/rss+xml; charset=utf-8.

  5. Ative o workflow. Assine o seu leitor na Production URL do nó Webhook.

    Workflow do n8n: quatro nós, uma URL de feed
    1. WebhookFeed URLGET, responde pelo último nó
    2. HTTP RequestSorsa API user tweetsPOST /user-tweets, cabeçalho ApiKey
    3. CodeBuild RSStweets em itens 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 } }];

    No n8n, cole o JSON em um canvas vazio, coloque sua chave no nó HTTP Request, ative o workflow e assine a Production URL.

    O nó Code transforma o array de tweets da Sorsa API em RSS 2.0; o JSON do workflow traz os quatro nós de uma vez.

Aqui o intervalo de atualização do leitor define o custo: um leitor que consulta de hora em hora gasta 720 requisições por mês com o feed. Para feeds de List ou de busca, mude a URL e o corpo do nó HTTP Request. Se os posts só alimentam o resto de um workflow (Slack, Sheets, uma etapa de IA), pule o RSS e leia o JSON direto, como mostra o guia da API do Twitter no n8n.

#Quanto custa um feed RSS do Twitter

Um feed RSS do Twitter custa uma requisição por atualização, então o preço depende de com que frequência ele é atualizado e de quantos feeds você roda, não de quanto as contas publicam. Num mês de 30 dias:

Atualizar a cadaRequisições por mês, um feedFeeds nas 10 mil requisições do Starter
5 minutos8.6401
15 minutos2.8803
30 minutos1.4406
1 hora72013
6 horas12083
  • 5 minutos

    Requisições por mês, um feed
    8.640
    Feeds nas 10 mil requisições do Starter
    1
  • 15 minutos

    Requisições por mês, um feed
    2.880
    Feeds nas 10 mil requisições do Starter
    3
  • 30 minutos

    Requisições por mês, um feed
    1.440
    Feeds nas 10 mil requisições do Starter
    6
  • 1 hora

    Requisições por mês, um feed
    720
    Feeds nas 10 mil requisições do Starter
    13
  • 6 horas

    Requisições por mês, um feed
    120
    Feeds nas 10 mil requisições do Starter
    83
Atualizar a cada
Requisições por mês 2,880 1 requisição por feed por atualização, 30 dias
Plano da Sorsa API que cobre Starter 10K requisições por mês por US$ 49. com espaço para 3 feeds como estes

Conte cada Lista ou busca como um feed, não importa quantas contas ela siga.

Quando as páginas voltam cheias, como numa List movimentada ou na primeira execução, a Sorsa API entrega posts a partir de US$ 0,07 por 1.000. A API oficial do X cobra US$ 5,00 por 1.000 posts lidos nos seus preços de pagamento por uso (abre em uma nova aba), depois de uma conta de desenvolvedor e de um app OAuth, e limita o pagamento por uso a 3 milhões de leituras de posts por mês. A partir de 22 de novembro de 2026, o X também cobra o autor e a mídia de cada post devolvidos por expansions, a US$ 0,010 por usuário, segundo o aviso do X de 23 de outubro (abre em uma nova aba).

#Monte seu primeiro feed hoje

Um feed RSS do Twitter é um script de cerca de 100 linhas e um agendador, e a única parte que você não consegue escrever sozinho são os dados. Para essa parte, use a Sorsa API: uma requisição por atualização, 20 posts por requisição, uma List inteira de até 5.000 contas num único feed e 20 requisições por segundo em todos os planos. Ela pede uma chave de API em vez de uma conta de desenvolvedor e nunca pede o login do seu X. Suas 100 requisições grátis puxam seus primeiros 2.000 posts, o bastante para montar o feed e vê-lo atualizar antes de escolher um plano.

#FAQ

Com que frequência um feed RSS do Twitter deve atualizar?

De 15 a 60 minutos serve para a maioria dos feeds RSS do Twitter. Um feed atualizado a cada 15 minutos usa 2.880 requisições por mês, e um de hora em hora usa 720, porque cada atualização é uma requisição. Alinhe a atualização do seu leitor com o agendamento do script, e atualize Lists ou hashtags movimentadas com mais frequência para que cada execução se atualize em uma ou duas páginas.

Existe um feed RSS do Twitter grátis?

O X não oferece feed RSS próprio, nem grátis nem pago. O jeito gratuito de começar são as 100 requisições grátis da Sorsa API: elas não pedem cartão, nunca expiram e puxam cerca de 2.000 posts, o bastante para montar, testar e rodar um feed por alguns dias antes de escolher um plano.

Posso ter a minha timeline inicial do X como feed RSS?

Não diretamente, porque a timeline inicial pertence a uma conta logada. A cópia prática é uma List: adicione as contas que você segue a uma List pública do X no app e monte um feed a partir dela com o GET /list-tweets. Uma List comporta até 5.000 contas e custa uma requisição por atualização, o mesmo que uma única conta.

O RSSHub ainda funciona para o Twitter?

A rota do X no RSSHub ainda existe, mas agora exige uma conta do X logada ou chaves da API oficial do X. O código-fonte da rota lista duas formas de acesso: o cookie auth_token de uma conta do X logada ou chaves da API oficial do X com pagamento por uso. Um feed montado na Sorsa API usa uma chave de API e nunca pede o login do seu X.

Posso fazer um feed RSS de uma conta protegida do X?

Não. Os posts de contas protegidas só são visíveis para seguidores aprovados, então nenhuma ferramenta de feed ou API consegue lê-los. A Sorsa API devolve só dados públicos, então ela também nunca os lê. Os feeds funcionam para qualquer conta pública, qualquer List pública e qualquer busca de posts públicos.

Qual API devo usar para montar um feed RSS do Twitter?

Use a Sorsa API para montar um feed RSS do Twitter: o POST /user-tweets devolve 20 posts por requisição a partir de US$ 0,07 por 1.000, o GET /list-tweets coloca até 5.000 contas num feed com uma requisição por atualização, e todos os planos permitem 20 requisições por segundo. Ela usa uma chave de API e nunca pede o login do seu X, então nenhuma conta sua corre risco.

#Como conferimos

Em 2 de novembro de 2026 pedimos x.com/NASA/rss e recebemos a página web do X em vez de um feed, lemos a página de preços do X e o aviso de 23 de outubro sobre a cobrança de expansions, e lemos o código-fonte da rota do X no RSSHub e dos nós Webhook e Respond to Webhook do n8n no GitHub. As requisições, a resposta e o script seguem a referência de API ao vivo da Sorsa API; não tínhamos uma chave de teste nesta rodada, então a resposta mostra os campos documentados com valores de exemplo.

Pela equipe da Sorsa API. Construímos e operamos a Sorsa API, a API e scraper somente leitura do Twitter (X), em produção desde 2022 (antiga TweetScout API), com mais de 6 bilhões de requisições atendidas. Sobre a Sorsa API

O que mudou
  • Primeira publicação.