Como ler as respostas de um tweet de forma programática

Atualizado
Um endpoint grátis que retorna as respostas públicas de qualquer post do X em JSON ou Markdown, por engajamento ou data, com paginação.
Em resumo:
GET https://unifapi.com/tools/x/replies?id=<post id or URL>devolve o post e as respostas públicas abaixo dele em JSON. É grátis, sem fazer login, sem precisar de conta e sem chave de API, com limite por visitante.sort=top(padrão) ordena por engajamento,sort=recentpor tempo. As páginas têm 20 respostas com umnextCursor. Cada resposta traz autor, texto, métricas, mídia einReplyToPostId, então dá para reconstruir a thread. É o único pedaço do X que nenhum dos endpoints gratuitos de post único expõe, e o motivo de a maioria das tarefas de agente do tipo "leia essa thread" acabar em um navegador headless.
As respostas abaixo de um post são onde mora a reação. O post em si diz o que uma marca falou; as respostas dizem o que as pessoas acham disso, o que quebrou, o que elas querem e qual reclamação ganhou 4.000 curtidas. Para análise de sentimento, pesquisa com clientes e monitoramento de incidentes, elas são o dado.
Também são a parte mais difícil do X de ler sem conta. O FxTwitter e o vxTwitter leem um post. O endpoint de syndication lê um post. A própria página do X carrega as respostas com JavaScript depois do fato, então o curl recebe uma casca vazia. A API oficial expõe respostas via busca por conversa nos níveis pagos.
A requisição
curl -s "https://unifapi.com/tools/x/replies?id=https://x.com/NASA/status/2107237881668313108"
id aceita o ID numérico do post ou a URL completa de x.com / twitter.com. A resposta:
{
"post": {
"id": "2107237881668313108",
"text": "Time to bring them home 🌎 …",
"author": { "handle": "NASA", "name": "NASA", "verified": true },
"metrics": {
"likes": 7210,
"reposts": 846,
"replies": 262,
"quotes": 60,
"bookmarks": 197,
"views": 2823329
},
"conversationId": "2107237881668313108"
},
"replies": {
"items": [
{
"id": "2107252849688424504",
"text": "@NASA @Space_Station @SpaceX Those space suits don't look right…",
"createdAt": "2026-10-05T23:33:22.000Z",
"author": {
"handle": "Troyztoys",
"name": "Tee Crenshaw",
"verified": true,
"followers": 1823
},
"metrics": {
"likes": 15,
"reposts": 1,
"replies": 0,
"quotes": 0,
"bookmarks": 0,
"views": 894
},
"media": [],
"conversationId": "2107237881668313108",
"inReplyToPostId": "2107237881668313108"
}
],
"hasMore": true,
"nextCursor": "20@"
}
}
post é o original. replies.items são os posts públicos da conversa dele além do original, tanto respostas diretas quanto aninhadas. Cada um tem inReplyToPostId, então uma resposta a uma resposta aponta para o pai e a thread pode ser reconstruída como uma árvore.
Ordenação
sort=top (o padrão) ordena por curtidas mais reposts mais respostas, mais ou menos como a aba "Mais relevantes" do próprio X faz. sort=recent ordena do mais novo para o mais antigo. Para "qual é a reação", use top; para "o que aconteceu na última hora", use recent.
A página para humanos, /tools/x-reply-viewer, tem as mesmas duas opções como pílulas, e /tools/x-reply-viewer?q=<id>&sort=recent&format=json devolve exatamente o que a API devolve.
Paginação
As respostas vêm 20 por página. Devolva nextCursor como cursor para continuar. O primeiro cursor costuma se parecer com 20@, que significa "as próximas 20 da página já buscada"; os seguintes são os cursores opacos do próprio X. Trate todos como strings opacas.
Um post com 262 respostas tem cerca de 14 páginas. São 14 das suas 20 unidades gratuitas a cada 10 minutos, então leia X-RateLimit-Remaining nos headers e pare quando tiver o suficiente; a primeira página ordenada por top normalmente já contém as respostas que importam.
O que um registro de resposta contém
| Campo | Significado |
|---|---|
id, url | O id da resposta e a URL canônica em x.com |
text | Texto completo, com as @menções iniciais do jeito que o X as armazena |
createdAt | ISO 8601, UTC |
author | handle, name, verified, followers, avatarUrl, … |
metrics | likes, reposts, replies, quotes, bookmarks, views |
media | Fotos e vídeos com tamanhos e URLs de MP4 na CDN do X |
inReplyToPostId | O post que esta resposta responde |
conversationId | O post raiz da conversa |
possiblySensitive | A flag do próprio X |
O formato é o mesmo registro post que os endpoints de busca, perfil e mídia devolvem, então uma função que pontua um post funciona em uma resposta sem alteração.
Três coisas para construir
Um resumo de reações. Busque a página top, passe os 20 textos para um modelo junto com o post original e peça os três sentimentos mais comuns com uma citação representativa de cada. Vinte respostas e uma chamada; a ordenação top já fez o ranqueamento.
Um feed de reclamações. Para o anúncio de uma marca, consulte sort=recent a cada 10 minutos, guarde as respostas cujo metrics.likes passa de um limiar entre uma consulta e outra e encaminhe essas para uma pessoa. As que estão subindo são as que vão virar print.
Uma reconstrução de thread. Percorra todas as páginas, monte um mapa de id para resposta e então ligue cada resposta ao seu inReplyToPostId. Respostas ao original ficam na profundidade um; o resto se aninha. Renderize em Markdown e você tem uma transcrição legível da conversa para um relatório.
Limites
- Só respostas públicas. Respostas de contas protegidas e respostas apagadas não entram, e por isso a contagem de
repliesno post original pode ser maior do que o que dá para ler. - O limite gratuito é de 20 consultas a cada 10 minutos por visitante, somando todos os endpoints
/tools/x/*, e uma busca conta como duas. Um 429 trazRetry-Aftere a URL onde o teto é levantado. - Volume, histórico e garantias ficam na API do X / Twitter medida, pay as you go com uma chave de workspace, com os mesmos nomes de campo.
FAQ
Dá para pegar as respostas de um tweet sem a API do Twitter?
Sim. O endpoint acima lê respostas públicas grátis, sem fazer login, sem precisar de conta e sem chave, com limite por visitante. Devolve JSON por padrão e Markdown com format=md.
Por que o X diz 262 respostas e eu só vejo 200?
Algumas respostas são de contas protegidas, algumas foram apagadas e algumas foram ocultadas pelo autor. A contagem no post original é a do X; o conjunto legível é o que é público.
Inclui posts com citação?
Não. Citações são posts separados, não respostas. Busque a URL do post com /tools/x/search?q=<post url> para encontrá-las.
Dá para ler as respostas como texto para um modelo?
Sim. format=md devolve o post original e cada resposta como um bloco de Markdown com autor, texto, métricas e URL.