Uma API de busca do Twitter gratuita que devolve JSON, com os operadores de busca do X

Atualizado
Pesquise posts públicos recentes do X em JSON a partir de um script ou agent de AI sem API key: o endpoint, operadores que funcionam, paginação e limites.
Em resumo:
GET https://unifapi.com/tools/x/search?q=<query>devolve em JSON os posts públicos do X que batem com uma consulta. É grátis, sem fazer login, sem precisar de conta e sem chave de API, com limite por visitante. Os operadores de busca do X funcionam emq:from:,to:,since:,until:,min_faves:,min_retweets:,filter:media,filter:links,-filter:replies,lang:e frases entre aspas. Os resultados vêm 20 por página, os mais recentes primeiro, com umnextCursorpara paginar. O limite gratuito é de 20 unidades a cada 10 minutos por visitante, impresso nos headersX-RateLimit-*, e uma busca custa 2 unidades porque é a chamada mais cara no upstream, o que dá 10 buscas. Sem datas, você recebe os posts mais recentes; adicionesince:euntil:e a mesma busca volta até 2006.
De tudo o que as pessoas querem do X sem conta, busca é o item que não tem uma boa resposta gratuita. As APIs de prévia de link (FxTwitter, vxTwitter) leem posts individuais. O endpoint de syndication lê posts individuais. O Nitter tinha busca, e a maioria das instâncias públicas do Nitter sumiu ou está bloqueada por motivos legais. Sobrava ou uma conta de desenvolvedor com nível pago ou um navegador headless controlando x.com/search, o que é lento, frágil e contra os termos.
Isto é o que o endpoint de busca gratuito faz, como consultá-lo e onde ele para.
A requisição
curl -s "https://unifapi.com/tools/x/search?q=from%3Anasa%20filter%3Amedia"
{
"query": "from:nasa filter:media",
"posts": {
"items": [
{
"id": "2107566197579341846",
"text": "After delivering science and supplies to the @Space_Station earlier this year, Northrop Grumman's Cygnus XL cargo spacecraft is scheduled to depart on Friday…",
"createdAt": "2026-10-06T20:18:32.000Z",
"url": "https://x.com/NASA/status/2107566197579341846",
"author": { "handle": "NASA", "name": "NASA", "verified": true, "followers": 92373839 },
"metrics": {
"likes": 2195,
"reposts": 302,
"replies": 114,
"quotes": 20,
"bookmarks": 104,
"views": 1520159
},
"media": [
{
"kind": "photo",
"url": "https://pbs.twimg.com/media/…jpg",
"width": 1920,
"height": 1280
}
]
}
],
"hasMore": true,
"nextCursor": "DAACCgACHUAq4qFAJxAKAAMd…"
}
}
A mesma requisição na página para humanos é https://unifapi.com/tools/x-search?q=from:nasa filter:media, e adicionar &format=json à URL dessa página devolve o JSON acima. Adicione format=md em vez disso, ou envie Accept: text/markdown, para receber os posts em Markdown, que cabe melhor na janela de contexto de um modelo do que JSON.
Operadores que funcionam
A consulta vai para a busca do X como foi escrita, então os operadores que o X documenta para a própria caixa de busca funcionam aqui. Estes são os que mais usamos:
| Operador | Exemplo | O que faz |
|---|---|---|
from: | from:nasa | Posts de uma conta |
to: | to:nasa | Respostas endereçadas a uma conta |
@handle | @nasa | Posts que mencionam uma conta |
#tag | #Formula1 | Posts com uma hashtag |
"phrase" | "crew-12" | Frase exata |
since: / until: | since:2026-10-01 | Limites de data (dias inteiros) |
min_faves: | min_faves:100 | Pelo menos N curtidas |
min_retweets: | min_retweets:50 | Pelo menos N reposts |
filter:media | from:nasa filter:media | Só posts com foto ou vídeo |
filter:links | filter:links | Só posts com link |
-filter:replies | #Formula1 -filter:replies | Exclui respostas |
-filter:retweets | from:nasa -filter:retweets | Exclui reposts |
lang: | lang:ja | Código de idioma |
OR | nasa OR esa | Qualquer um dos termos |
Eles se combinam. "Posts da NASA na última semana com pelo menos 100 curtidas e uma foto, sem respostas" é:
from:nasa since:2026-09-30 min_faves:100 filter:media -filter:replies
A página de busca tem um filtro para cada um dos cinco mais comuns (conta, data, curtidas, mídia, respostas) e mostra a consulta que eles montam, que é a mesma string que a API recebe.
Mais recentes, não Principais
A busca do X tem duas ordenações: "Principais" (Top), que mistura relevância e idade e não hesita em abrir com um post de 2009, e "Mais recentes" (Latest), estritamente do mais novo para o mais antigo. O endpoint gratuito pede Mais recentes. Para monitoramento, reações a um evento e qualquer coisa com limite since:, é essa que você quer. Se quiser "os posts mais curtidos sobre X nesta semana", ordene você mesmo os resultados de Mais recentes por metrics.likes ou adicione min_faves: para cortar a cauda.
Paginação
Toda lista na API gratuita é { items, hasMore, nextCursor }. Para continuar, devolva o cursor:
curl -s "https://unifapi.com/tools/x/search?q=%23Formula1&cursor=DAACCgACHUAq4qFAJxAKAAMd…"
Cursores são strings opacas; não tente interpretá-los. hasMore é true exatamente quando nextCursor está definido. Uma página de busca tem 20 posts, então três requisições leem cerca de 60 posts por 6 das suas 20 unidades.
Limites, na resposta
HTTP/2 200
X-RateLimit-Limit: 20
X-RateLimit-Remaining: 16
X-RateLimit-Reset: 1791357984
O nível gratuito é de 20 unidades a cada 10 minutos por visitante, somando todos os endpoints /tools/x/*, e uma busca custa 2. Quando acaba, a resposta é um 429 com Retry-After e um corpo em JSON dizendo onde levantar o teto:
{
"error": {
"type": "rate_limited",
"message": "Free limit of 20 requests per 10 minutes reached. Retry after 412s, or use a UnifAPI workspace key (pay as you go) for uncapped access.",
"retryAfterSeconds": 412,
"upgrade": "https://unifapi.com/apis/twitter"
}
}
Um agente bem-comportado lê X-RateLimit-Remaining antes de decidir paginar e dorme pelo tempo de Retry-After em vez de tentar de novo em loop.
O que ele não faz
- Relevância. Os resultados vêm só do mais novo para o mais antigo. Posts antigos podem ser alcançados com datas (
from:jack until:2006-04-01devolve posts de março de 2006), mas nada coloca os melhores de um período em primeiro lugar, e o X traça os limites de dia desince:/until:no fuso horário dele, então um intervalo pode transbordar algumas horas para um lado ou para o outro. - Contas protegidas. Só posts públicos são devolvidos.
- Contagens. Não existe um número de "quantos posts bateram"; o X não expõe isso para busca.
- Garantias. O nível gratuito é infraestrutura compartilhada com teto por visitante. Um fluxo de trabalho que precisa de volume ou de SLA migra para a API medida, onde os nomes de campo são os mesmos.
Um loop de monitoramento em vinte linhas
import requests, time
BASE = "https://unifapi.com/tools/x/search"
seen = set()
def poll(query):
r = requests.get(BASE, params={"q": query}, headers={"Accept": "application/json"})
if r.status_code == 429:
time.sleep(int(r.headers.get("Retry-After", "60")))
return []
r.raise_for_status()
fresh = [p for p in r.json()["posts"]["items"] if p["id"] not in seen]
seen.update(p["id"] for p in fresh)
return fresh
while True:
for post in poll('"unifapi" -filter:replies'):
print(post["createdAt"], post["author"]["handle"], post["metrics"]["likes"], post["url"])
time.sleep(600)
Uma busca a cada 10 minutos são 2 das 20 unidades gratuitas; o loop nunca estoura o limite e, mesmo assim, trata o caso do 429.
FAQ
Existe uma API de busca do Twitter gratuita em 2026?
Sim, esta: é grátis, sem fazer login e sem chave de API, com limite por visitante de 10 buscas a cada 10 minutos. A API oficial do X não tem nível gratuito de busca; o plano gratuito dela só permite publicar.
Os operadores da busca avançada do Twitter funcionam?
Sim. A consulta é repassada à busca do X sem alteração, então from:, since:, until:, min_faves:, filter:media, -filter:replies, lang: e frases entre aspas funcionam.
Até onde a busca vai no tempo?
Até 2006. Sem datas, você recebe primeiro os posts mais recentes; adicione since: e until: para pular para um período, por exemplo from:jack until:2006-04-01.
Dá para receber os resultados em Markdown em vez de JSON?
Sim. Adicione format=md ou envie Accept: text/markdown. A renderização em Markdown lista cada post com autor, texto, métricas e URL.