Pular para o conteúdo

Como migrar da API do Twitter/X

Migrar da API oficial do X exige cinco mudanças no código: mapear cada endpoint da v2 para o novo caminho, trocar o OAuth por uma chave de API, abandonar fields e expansions, reescrever o parsing do JSON e trocar o token de paginação.

Resposta rápida: O que se deve migrar são as leituras: a API oficial do X cobra US$ 0,005 por post e US$ 0,010 por usuário, e, a partir de 22 de novembro de 2026, cada autor devolvido com um post soma US$ 0,010. Para migrá-las, use a Sorsa API: um cabeçalho ApiKey, 20 tweets por requisição de busca a partir de US$ 0,07 por 1.000 e 100 requisições grátis para testar o mapa.

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

#O que mudou na API oficial do X desde 2023

O código escrito para a API oficial do X ainda funciona na maior parte; o que mudou desde 2023 foi o que ele pode chamar, o que recebe de volta e quanto cada resposta custa. A lista datada abaixo vem do changelog (abre em uma nova aba) do X e dos avisos em seu fórum de desenvolvedores, com a parte de uma integração que cada mudança atinge.

DataMudança na API oficial do XO que isso faz com o seu código
30 de mar de 2023Planos pagos substituem o acesso gratuito; o Free passa a ser só de escritaLeituras em um app gratuito devolvem erros
26 de jun de 2023Endpoints de follows removidos do Basic e do ProAs chamadas de seguidores e seguindo param nesses planos
28 de set de 2023search/tweets e users/search da v1.1 descontinuadosO código de busca da v1.1 precisa de um novo endpoint
19 de jan de 2026min_likes, min_replies, min_reposts removidos da buscaAs consultas que os usavam tiveram de abandoná-los até 4 de maio
6 de fev de 2026O pagamento por uso vira o modelo; créditos comprados antecipadamenteAs chamadas são bloqueadas quando o saldo chega a zero
23 de fev de 2026Respostas programáticas só permitidas quando o autor convoca vocêBots de resposta são recusados
20 de abr de 2026Seguir, curtir e quote-posts removidos do autoatendimentoEssas chamadas de escrita param de funcionar
4 de maio de 2026A busca passa para um novo índice; retweets saem dos resultados por palavra-chaveA mesma consulta devolve menos posts
1º de jun e 1º de set de 2026Planos legados Basic e, depois, Pro migrados para o pagamento por usoUm teto mensal vira uma cobrança por recurso
22 de nov de 2026Expansions cobradas: US$ 0,010 por autor, US$ 0,005 por item de mídiaexpansions=author_id pode triplicar o custo de um post
  • 30 de mar de 2023

    Mudança na API oficial do X
    Planos pagos substituem o acesso gratuito; o Free passa a ser só de escrita
    O que isso faz com o seu código
    Leituras em um app gratuito devolvem erros
  • 26 de jun de 2023

    Mudança na API oficial do X
    Endpoints de follows removidos do Basic e do Pro
    O que isso faz com o seu código
    As chamadas de seguidores e seguindo param nesses planos
  • 28 de set de 2023

    Mudança na API oficial do X
    search/tweets e users/search da v1.1 descontinuados
    O que isso faz com o seu código
    O código de busca da v1.1 precisa de um novo endpoint
  • 19 de jan de 2026

    Mudança na API oficial do X
    min_likes, min_replies, min_reposts removidos da busca
    O que isso faz com o seu código
    As consultas que os usavam tiveram de abandoná-los até 4 de maio
  • 6 de fev de 2026

    Mudança na API oficial do X
    O pagamento por uso vira o modelo; créditos comprados antecipadamente
    O que isso faz com o seu código
    As chamadas são bloqueadas quando o saldo chega a zero
  • 23 de fev de 2026

    Mudança na API oficial do X
    Respostas programáticas só permitidas quando o autor convoca você
    O que isso faz com o seu código
    Bots de resposta são recusados
  • 20 de abr de 2026

    Mudança na API oficial do X
    Seguir, curtir e quote-posts removidos do autoatendimento
    O que isso faz com o seu código
    Essas chamadas de escrita param de funcionar
  • 4 de maio de 2026

    Mudança na API oficial do X
    A busca passa para um novo índice; retweets saem dos resultados por palavra-chave
    O que isso faz com o seu código
    A mesma consulta devolve menos posts
  • 1º de jun e 1º de set de 2026

    Mudança na API oficial do X
    Planos legados Basic e, depois, Pro migrados para o pagamento por uso
    O que isso faz com o seu código
    Um teto mensal vira uma cobrança por recurso
  • 22 de nov de 2026

    Mudança na API oficial do X
    Expansions cobradas: US$ 0,010 por autor, US$ 0,005 por item de mídia
    O que isso faz com o seu código
    expansions=author_id pode triplicar o custo de um post

Duas dessas mudanças alteraram resultados sem mudar uma linha de código. Desde que o novo índice de busca (abre em uma nova aba) entrou no ar em 4 de maio, uma busca por palavra-chave que funcionava bem em abril volta sem os retweets. E, a partir de 22 de novembro, a mesma requisição com expansions=author_id que custava US$ 5,00 por 1.000 posts passa a custar até US$ 15,00, porque o aviso sobre expansions (abre em uma nova aba) do X cobra cada autor devolvido como uma leitura de usuário.

Os planos também mudaram por baixo de código que já estava rodando. O X encerrou as assinaturas do Basic legado (abre em uma nova aba) nas datas de migração depois de 1º de junho de 2026, e as do Pro legado (abre em uma nova aba) depois de 1º de setembro; uma conta Pro mensal recebeu um crédito de US$ 5.000 na migração, com a recarga automática ativada. Hoje toda leitura consome créditos a US$ 0,005 por post e US$ 0,010 por usuário ou seguidor, até 3 milhões de leituras de posts por mês, e a tabela completa de tarifas está em nosso detalhamento dos preços da API do X.

#O que migra para a Sorsa API e o que fica no X

Toda leitura de dados públicos pode migrar: busca, timelines, consultas de posts e usuários, seguidores, listas, quotes, retweeters, respostas, Spaces, comunidades e trends. A Sorsa API, uma API e scraper do Twitter (X) em produção desde 2022, com mais de 6 bilhões de requisições atendidas, devolve tudo isso com uma única chave, sem OAuth e, como explica o guia sobre a API do Twitter sem conta de desenvolvedor, sem conta de desenvolvedor do X. Ela é somente leitura por princípio, então as chamadas que escrevem ficam onde estão.

Mantenha estas na API oficial do X:

  • Postar, responder, apagar e enviar mídia.
  • Mensagens diretas, e curtidas, follows, bookmarks e bloqueios, como ações ou como listas da atividade da sua própria conta.
  • Quem curtiu um post e qualquer coisa de contas protegidas.
  • Filtered stream, firehose, webhooks e a X Activity API: a Sorsa API é consultada por polling, não recebe dados por push (o padrão de polling está mais abaixo).
  • Contagens de posts, Community Notes e a Ads API.

Sua conta do X não participa das leituras, porque a Sorsa API nunca pede seu login nem seus cookies. Depois da divisão, a API oficial do X cobra apenas as escritas, por requisição: US$ 0,015 por post criado e US$ 0,20 por um post com link.

É nas leituras que o dinheiro vai. Em leituras de busca e de timeline, 1 milhão de tweets custa US$ 5.000 na API oficial do X antes de qualquer cobrança de autores, e a partir de US$ 70 na Sorsa API, que devolve o autor de cada tweet dentro dele sem custo extra. As consultas por ID rendem mais: o POST /tweet-info-bulk devolve 100 tweets por requisição, a partir de US$ 0,014 por 1.000.

Tweets lidos por busca

API oficial do X

US$ 5.000

para 1 milhão tweets

US$ 0,005 por post, antes dos autores

Sorsa API

a partir deUS$ 70

para 1 milhão tweets

a partir de US$ 0,07 por 1.000, autor incluído

#Migre para a Sorsa API em seis passos

Seis passos levam uma integração da v2 do inventário até a troca definitiva. Os cinco primeiros são edições no seu código; o último dura alguns dias, enquanto as duas APIs respondem às mesmas leituras.

  1. Liste todas as chamadas que o seu código faz. Procure no código por api.x.com/2, api.twitter.com/2 e pelos nomes dos métodos do seu cliente, como search_recent_tweets do Tweepy ou posts.search_recent do xdk. Exporte o uso do mês passado por recurso no Developer Console do X e marque cada chamada como leitura ou escrita.

  2. Obtenha uma chave e envie uma requisição. Cadastre-se, copie a chave do painel e chame o endpoint que substitui a sua leitura mais frequente.

    Terminal
    curl -X POST "https://api.sorsa.io/v3/search-tweets" \
      -H "ApiKey: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"query": "from:mira_moves_reads", "order": "latest"}'
    
    Resposta200 OK
    {
      "tweets": [
        {
          "id": "1852331946812457001",
          "full_text": "Read path moved. Writes stay where they were.",
          "created_at": "2026-10-30T14:05:12Z",
          "lang": "en",
          "likes_count": 41,
          "retweet_count": 6,
          "reply_count": 3,
          "quote_count": 1,
          "view_count": 2380,
          "conversation_id_str": "1852331946812457001",
          "is_reply": false,
          "user": {
            "id": "1592041833471827968",
            "username": "mira_moves_reads",
            "display_name": "Mira Moves Reads",
            "followers_count": 912,
            "verified": false
          }
        }
      ],
      "next_cursor": "DAADDAABCgABGbHk7m4WYAEKAAIZsd"
    }
    
  3. Mapeie cada leitura para o seu endpoint. A tabela e o conversor da próxima seção associam cada leitura da v2 ao caminho e aos parâmetros correspondentes da Sorsa API.

  4. Troque OAuth, fields e expansions por um único cabeçalho. Nas chamadas de leitura, apague o bearer token ou a assinatura OAuth 1.0a e envie ApiKey: YOUR_API_KEY no lugar. Abandone tweet.fields, user.fields e expansions: todos os campos e o autor já vêm por padrão.

  5. Reescreva o parsing e a paginação. Leia tweets ou users onde você lia data e includes, renomeie os campos que diferem e envie next_cursor de volta até que ele venha vazio.

  6. Faça um shadow run e depois a troca. Envie uma cópia das suas leituras à Sorsa API por alguns dias, compare os resultados, mova o tráfego em etapas e mantenha a chave do X para as escritas.

#Mapeie cada endpoint da API v2 do X para a Sorsa API

Toda leitura pública que uma integração provavelmente chama tem um endpoint na Sorsa API. A tabela associa cada caminho da v2, como escrito na especificação OpenAPI (abre em uma nova aba) do X, ao seu substituto e à quantidade que uma requisição devolve; a Sorsa API cobra por requisição, não por item, então a última coluna define o preço.

Chamada da API v2 do XEndpoint da Sorsa APIUma requisição devolve
GET /2/tweets/search/recentPOST /search-tweets (abre em uma nova aba)cerca de 20 tweets
GET /2/tweets/search/allPOST /search-tweets com since: e until:cerca de 20 tweets
GET /2/tweets/:idPOST /tweet-info (abre em uma nova aba)1 tweet
GET /2/tweets (por IDs)POST /tweet-info-bulk (abre em uma nova aba)até 100 tweets
GET /2/users/:id/tweetsPOST /user-tweets (abre em uma nova aba)cerca de 20 tweets
GET /2/users/:id/mentionsPOST /mentions (abre em uma nova aba)cerca de 20 tweets
GET /2/tweets/:id/quote_tweetsPOST /quotes (abre em uma nova aba)cerca de 20 tweets
GET /2/tweets/:id/retweeted_byPOST /retweeters (abre em uma nova aba)uma página de perfis
Busca com conversation_id:POST /comments (abre em uma nova aba)cerca de 20 respostas
GET /2/users/by/username/:usernameGET /info (abre em uma nova aba)1 perfil
GET /2/users e GET /2/users/byGET /info-batch (abre em uma nova aba)até 100 perfis
GET /2/users/:id/followersGET /followers (abre em uma nova aba)até 200 perfis
GET /2/users/:id/followingGET /follows (abre em uma nova aba)até 200 perfis
GET /2/users/searchPOST /search-users (abre em uma nova aba)uma página de perfis
GET /2/lists/:id/membersGET /list-members (abre em uma nova aba)uma página de perfis
GET /2/lists/:id/followersGET /list-followers (abre em uma nova aba)uma página de perfis
GET /2/lists/:id/tweetsGET /list-tweets (abre em uma nova aba)cerca de 20 tweets
GET /2/spaces/:idGET /spaces (abre em uma nova aba)1 Space
GET /2/communities/:idPOST /community-info (abre em uma nova aba)1 comunidade
GET /2/communities/searchPOST /search-communities (abre em uma nova aba)uma página de comunidades
GET /2/trends/by/woeid/:woeidGET /trends (abre em uma nova aba)os trends de 1 localidade
GET /2/usage/tweetsGET /key-usage-info (abre em uma nova aba)seu saldo, sem custo

Quatro hábitos mudam com os caminhos. Os endpoints de tweets usam POST com um corpo JSON, enquanto as consultas de usuários, listas e utilidades continuam em GET. Um username funciona onde a v2 pedia um ID numérico, então a consulta extra antes de cada chamada de timeline desaparece. O tweet_link aceita a URL completa de um post ou só o ID. E o POST /user-tweets continua paginando além dos 3.200 posts mais recentes, onde a timeline de usuário do X trava.

Algumas leituras da v2 não têm equivalente, porque a Sorsa API devolve apenas o que qualquer pessoa vê em um perfil público: usuários que curtiram, curtidas e bookmarks de um usuário, contagens de posts, a timeline inicial e todos os streams. A Sorsa API também responde a perguntas que a v2 não responde: o POST /check-follow (abre em uma nova aba) diz em uma requisição se uma conta segue outra, e o GET /about (abre em uma nova aba) devolve o país de uma conta e o histórico de usernames.

O conversor abaixo transforma uma chamada da v2 por vez na requisição equivalente da Sorsa API, com os campos que mudam e o preço de 1.000 resultados em cada lado.

Antes: API oficial do X v2
curl -G "https://api.x.com/2/tweets/search/recent" \
  -H "Authorization: Bearer $X_BEARER_TOKEN" \
  --data-urlencode "query=from:mira_moves_reads" \
  -d "max_results=100" \
  -d "expansions=author_id" \
  -d "tweet.fields=created_at,public_metrics"
Depois: Sorsa API
curl -X POST "https://api.sorsa.io/v3/search-tweets" \
  -H "ApiKey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "from:mira_moves_reads", "order": "latest"}'
Endpoint da Sorsa API
POST /search-tweets
Uma requisição retorna
cerca de 20 tweets
API oficial do X, 1,000 resultados
US$ 5,00, mais até US$ 10,00 pelos autores
Sorsa API, 1,000 resultados
a partir de US$ 0,07

Paginação: next_token vira next_cursor no corpo JSON. A mesma consulta busca desde 2006, e não só nos últimos 7 dias, e cada tweet traz o seu autor.

Escolha a chamada da v2 que o seu código faz para ver a mesma requisição na Sorsa API e quanto custam 1,000 resultados em cada uma.

Se o seu código usa filtered stream ou webhooks

A Sorsa API não tem stream nem webhook, então uma regra de filtered stream vira uma consulta de busca que você consulta por polling. Envie a regra como consulta do POST /search-tweets com "order": "latest", acrescente since_id: com o ID mais novo que você guardou e siga o next_cursor, para que um minuto movimentado com mais de 20 posts novos não perca nenhum deles.

poll.py
import os
import time
import requests

URL = "https://api.sorsa.io/v3/search-tweets"
HEADERS = {"ApiKey": os.environ.get("SORSA_API_KEY", "YOUR_API_KEY")}
RULE = '"open data" lang:en'


def new_tweets(since_id):
    body = {"query": f"{RULE} since_id:{since_id}", "order": "latest"}
    found = []
    while True:
        r = requests.post(URL, headers=HEADERS, json=body, timeout=30)
        if r.status_code == 429:
            time.sleep(1)
            continue
        r.raise_for_status()
        page = r.json()
        found += page.get("tweets", [])
        if not page.get("next_cursor"):
            return found
        body["next_cursor"] = page["next_cursor"]


newest = "1852331946812457001"
while True:
    tweets = new_tweets(newest)
    for t in sorted(tweets, key=lambda t: int(t["id"])):
        print(t["id"], t["user"]["username"], t["full_text"][:60])
    if tweets:
        newest = max((t["id"] for t in tweets), key=int)
    time.sleep(15)

Uma chave roda 20 requisições por segundo em todos os planos, o que dá 1.200 consultas de uma página por minuto, compartilhadas entre as suas regras. Agendamento, alertas e deduplicação para tarefas de monitoramento são tratados no guia de monitoramento do Twitter em tempo real.

#Reescreva o parsing da resposta

A Sorsa API envia cada tweet como um único objeto com o autor dentro, então o join entre data e includes desaparece e o trabalho que sobra é renomear campos.

X API oficial v2 Sorsa API GET /2/tweets/search/recent { "data": [{ "id": "18523319…", "text": "Read path moved…", "author_id": "15920418…", "public_metrics": { "like_count": 41 } }], "includes": {"users": [{ "id": "15920418…", "username": "mira_moves_reads" }]}, "meta": {"next_token": "b26v8…"} } 1 2 3 4 3 5 POST /search-tweets { "tweets": [{ "id": "18523319…", "full_text": "Read path moved…", "user": { "id": "15920418…", "username": "mira_moves_reads" }, "likes_count": 41 }], "next_cursor": "DAADDAAB…" } 1 2 3 4 5 O autor vai dentro de todo tweet: sem campos nem expansions a pedir.
A API v2 do X separa o tweet do autor e pagina com next_token; a Sorsa API põe o autor dentro do tweet e pagina com next_cursor.

Os nomes de campos abaixo vêm do dicionário de dados do X e da referência em produção da Sorsa API, lidos em 2 de novembro de 2026. A maioria das mudanças é um achatamento, em que uma métrica sai de public_metrics e mantém o nome, e algumas são renomeações.

Campo da API v2 do XCampo da Sorsa API
data[]tweets[], ou users[] para listas de contas
text e note_tweet.textfull_text
author_id com includes.users[]user, o perfil completo
public_metrics.like_countlikes_count
public_metrics.impression_countview_count
public_metrics.retweet_count, reply_count, quote_count, bookmark_countos mesmos nomes, um nível acima
conversation_idconversation_id_str
referenced_tweets com includes.tweets[]quoted_status, retweeted_status, in_reply_to_tweet_id
attachments.media_keys com includes.media[]entities[] com type, link, preview
name em um usuáriodisplay_name
public_metrics.following_count, tweet_count em um usuáriofollowings_count, tweets_count
meta.next_token e pagination_tokennext_cursor, nos dois sentidos
errors[] com title e detail{"message": "..."}
  • data[]

    Campo da Sorsa API
    tweets[], ou users[] para listas de contas
  • text e note_tweet.text

    Campo da Sorsa API
    full_text
  • author_id com includes.users[]

    Campo da Sorsa API
    user, o perfil completo
  • public_metrics.like_count

    Campo da Sorsa API
    likes_count
  • public_metrics.impression_count

    Campo da Sorsa API
    view_count
  • public_metrics.retweet_count, reply_count, quote_count, bookmark_count

    Campo da Sorsa API
    os mesmos nomes, um nível acima
  • conversation_id

    Campo da Sorsa API
    conversation_id_str
  • referenced_tweets com includes.tweets[]

    Campo da Sorsa API
    quoted_status, retweeted_status, in_reply_to_tweet_id
  • attachments.media_keys com includes.media[]

    Campo da Sorsa API
    entities[] com type, link, preview
  • name em um usuário

    Campo da Sorsa API
    display_name
  • public_metrics.following_count, tweet_count em um usuário

    Campo da Sorsa API
    followings_count, tweets_count
  • meta.next_token e pagination_token

    Campo da Sorsa API
    next_cursor, nos dois sentidos
  • errors[] com title e detail

    Campo da Sorsa API
    {"message": "..."}

Os IDs continuam strings e as datas continuam em ISO 8601, então os dados guardados mantêm o formato. A paginação se reduz a um único nome: envie next_cursor como parâmetro de query nos endpoints GET ou no corpo JSON nos endpoints POST, e pare quando ele vier vazio. O rate limiting também fica mais simples. As janelas de 15 minutos e os cabeçalhos x-rate-limit-* descritos em nosso guia sobre os rate limits da API do X dão lugar a um único limite de 20 requisições por segundo por chave: um 429 significa esperar um segundo e tentar de novo, e um 403 significa que a chave está ausente ou que as requisições do mês acabaram.

Bom saber

O tamanho das páginas não é fixo. Uma página de busca tem até 20 tweets e pode ter menos enquanto ainda restam páginas, então faça o loop com base no next_cursor, nunca no número de itens, ou uma página curta encerra o trabalho antes da hora.

#Código Tweepy e xdk, antes e depois

Tweepy e xdk são bibliotecas gratuitas; a conta vem da API oficial do X por trás delas, então a migração troca o cliente, não a linguagem. Aqui está a mesma busca com autores, paginada até o fim, primeiro em Tweepy e depois em Python puro na Sorsa API:

import tweepy

client = tweepy.Client(bearer_token="X_BEARER_TOKEN")

for page in tweepy.Paginator(
        client.search_recent_tweets,
        query="from:mira_moves_reads",
        tweet_fields=["created_at", "public_metrics"],
        expansions=["author_id"],
        user_fields=["username", "name"],
        max_results=100):
    users = {u.id: u for u in page.includes.get("users", [])}
    for t in page.data or []:
        author = users[t.author_id]
        print(t.id, author.username, t.public_metrics["like_count"])

As listas de campos, o join de includes e o paginador saem do código; entra um cabeçalho. O código com xdk muda do mesmo modo: Client(bearer_token=...) e client.posts.search_recent(...) paginam os mesmos data e includes, por isso dão lugar ao loop acima. A consulta também alcança mais longe depois da migração, porque o POST /search-tweets busca desde 2006 em todos os planos, enquanto a busca recente da v2 cobre os últimos 7 dias.

O código construído sobre o pacote twitter-api-v2 para Node.js migra do mesmo modo, para fetch e um cabeçalho:

Node.js
const URL = "https://api.sorsa.io/v3/search-tweets";
const headers = {
  ApiKey: process.env.SORSA_API_KEY ?? "YOUR_API_KEY",
  "Content-Type": "application/json",
};

const body = { query: "from:mira_moves_reads", order: "latest" };
do {
  const res = await fetch(URL, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
  });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  const page = await res.json();
  for (const t of page.tweets ?? []) {
    console.log(t.id, t.user.username, t.likes_count);
  }
  body.next_cursor = page.next_cursor;
} while (body.next_cursor);

Para código Tweepy que só lê, mova as leituras para a Sorsa API: a busca devolve 20 tweets por requisição a partir de US$ 0,07 por 1.000, os perfis vêm 100 por requisição a partir de US$ 0,014 por 1.000, e não é preciso OAuth. Novas tentativas, lotes e um controlador de ritmo para 20 requisições por segundo estão no guia da API do Twitter com Python.

#Traduza suas consultas de busca

O POST /search-tweets aceita a sintaxe da Busca Avançada do X, a linguagem da caixa de busca do x.com, então palavras-chave, frases entre aspas, from:, to:, lang:, conversation_id: e hashtags passam sem alteração. O que muda são os operadores is: e has: da v2 e seus parâmetros de tempo, que passam para dentro da consulta:

API v2 do XConsulta na Sorsa API
parâmetros start_time e end_timesince:2026-10-01 e until:2026-11-01
parâmetros since_id e until_idsince_id:ID e max_id:ID (inclusivo)
sort_order=recency ou relevancy"order": "latest" ou "popular" no corpo
-is:retweetnada: os retweets ficam de fora por padrão
is:reply e -is:replyfilter:replies e -filter:replies
is:quotefilter:quote
has:media, has:images, has:linksfilter:media, filter:images, filter:links
has:video_linkfilter:native_video
min_likes:, min_reposts:, min_replies:min_faves:, min_retweets:, min_replies:
point_radius:geocode:
  • parâmetros start_time e end_time

    Consulta na Sorsa API
    since:2026-10-01 e until:2026-11-01
  • parâmetros since_id e until_id

    Consulta na Sorsa API
    since_id:ID e max_id:ID (inclusivo)
  • sort_order=recency ou relevancy

    Consulta na Sorsa API
    "order": "latest" ou "popular" no corpo
  • -is:retweet

    Consulta na Sorsa API
    nada: os retweets ficam de fora por padrão
  • is:reply e -is:reply

    Consulta na Sorsa API
    filter:replies e -filter:replies
  • is:quote

    Consulta na Sorsa API
    filter:quote
  • has:media, has:images, has:links

    Consulta na Sorsa API
    filter:media, filter:images, filter:links
  • has:video_link

    Consulta na Sorsa API
    filter:native_video
  • min_likes:, min_reposts:, min_replies:

    Consulta na Sorsa API
    min_faves:, min_retweets:, min_replies:
  • point_radius:

    Consulta na Sorsa API
    geocode:

Três detalhes atrapalham as consultas traduzidas. Os retweets nativos ficam de fora, a menos que você acrescente include:nativeretweets. O geocode: recebe a latitude primeiro, como em geocode:37.77,-122.41,5km, enquanto o point_radius: da v2 recebia a longitude primeiro. E o max_id: inclui o próprio ID, enquanto o until_id da v2 o exclui. A lista completa de operadores, com receitas, está em nosso guia de operadores de busca do Twitter.

#Teste com um shadow run e depois faça a troca

Um shadow run envia uma cópia de cada leitura à Sorsa API enquanto a API oficial do X continua atendendo o seu app, de modo que os resultados são comparados antes de qualquer coisa depender deles.

Etapa 1 Sombra A X API atende toda leitura; a Sorsa API recebe uma cópia Leituras X API 100% Cópia na Sorsa API Etapa 2 Compare Cruze IDs de posts, campos e erros de cada consulta Leituras X API 100% Cópia na Sorsa API Etapa 3 Canary 10% das leituras vêm da Sorsa API; acompanhe os erros Leituras X API 90% Sorsa API 10% Etapa 4 Virada Toda leitura roda na Sorsa API; apague o código antigo de leitura Leituras Sorsa API 100% Escritas X API oficial em todas as etapas: posts, respostas, DMs
As leituras migram em quatro etapas; as escritas nunca saem da API oficial do X.

O script executa uma consulta sobre o mesmo dia encerrado nas duas APIs e compara os IDs dos posts. Execute-o para cada consulta e timeline de que você depende; uma janela fechada impede que posts novos distorçam a contagem.

shadow_run.py
import os
import requests

X_URL = "https://api.x.com/2/tweets/search/recent"
X_HEADERS = {"Authorization": "Bearer " + os.environ["X_BEARER_TOKEN"]}
S_URL = "https://api.sorsa.io/v3/search-tweets"
S_HEADERS = {"ApiKey": os.environ.get("SORSA_API_KEY", "YOUR_API_KEY")}


def x_ids(query, start, end):
    params = {"query": query, "start_time": start,
              "end_time": end, "max_results": 100}
    ids = set()
    while True:
        r = requests.get(X_URL, headers=X_HEADERS, params=params, timeout=30)
        r.raise_for_status()
        page = r.json()
        ids |= {t["id"] for t in page.get("data", [])}
        token = page.get("meta", {}).get("next_token")
        if not token:
            return ids
        params["next_token"] = token


def sorsa_ids(query, since, until):
    body = {"query": f"{query} since:{since} until:{until}",
            "order": "latest"}
    ids = set()
    while True:
        r = requests.post(S_URL, headers=S_HEADERS, json=body, timeout=30)
        r.raise_for_status()
        page = r.json()
        ids |= {t["id"] for t in page.get("tweets", [])}
        if not page.get("next_cursor"):
            return ids
        body["next_cursor"] = page["next_cursor"]


query = "from:mira_moves_reads"
a = x_ids(query, "2026-10-30T00:00:00Z", "2026-10-31T00:00:00Z")
b = sorsa_ids(query, "2026-10-30_00:00:00_UTC", "2026-10-31_00:00:00_UTC")
print(f"official X API {len(a)}, Sorsa API {len(b)}, shared {len(a & b)}")
print("only on X:", sorted(a - b)[:10])
print("only on Sorsa API:", sorted(b - a)[:10])

Espere pequenas diferenças em vez de zero: posts apagados entre as duas chamadas somem, e a busca por palavra-chave do X deixa os retweets de fora desde 4 de maio de 2026. A busca recente do X alcança 7 dias para trás, então mantenha a janela dentro da última semana. Quando os IDs baterem nas leituras que você mais executa, faça a troca em etapas:

  • Coloque os dois clientes atrás de uma mesma interface e de uma única flag de configuração, para que qualquer tipo de leitura possa voltar com um só valor.
  • Mova 10% das leituras, acompanhe os erros e o GET /key-usage-info, que é grátis e nunca desconta das suas requisições, e depois mova o restante.
  • Mantenha a chave da API oficial do X só para as escritas, e reduza o limite de gastos e o valor da recarga automática no Developer Console.
  • Apague os caminhos de código de leitura, as listas de campos e a paginação antiga depois que um ciclo de cobrança completo passar.

#Tire suas leituras da API oficial do X

Uma integração da v2 só de leitura migra para a Sorsa API, a API do Twitter feita para ler dados públicos do X, com um cabeçalho, um endpoint por chamada e um parser que perde o join. A busca sai a partir de US$ 0,07 por 1.000 tweets em vez de US$ 5,00, os seguidores a partir de US$ 0,007 por 1.000 em vez de US$ 10,00, e todos os planos respondem a 20 requisições por segundo. Comece pela leitura mais cara, faça um shadow run dela por alguns dias e mantenha a API oficial do X só para o que escreve.

#Perguntas frequentes

Para qual API do Twitter devo migrar a partir da API oficial do X?

Para ler dados públicos do X, migre para a Sorsa API: cada leitura da v2 corresponde a um endpoint, os tweets custam a partir de US$ 0,014 por 1.000 por ID e a partir de US$ 0,07 por busca, contra US$ 5,00 na API oficial do X, todos os planos rodam a 20 requisições por segundo e a busca chega até 2006. Uma chave de API substitui o OAuth. A Sorsa API é somente leitura, então mantenha a API oficial do X para postar.

Quanto tempo leva uma migração da API oficial do X?

A mudança de código cresce com o número de chamadas distintas da v2, não com o volume de dados: cada chamada vira um endpoint, um cabeçalho e alguns campos renomeados. Some um shadow run de alguns dias, em que as duas APIs respondem às mesmas leituras e você compara os IDs. Postagens, DMs e outras escritas ficam na API oficial do X, então só o caminho de leitura migra.

Posso continuar postando no X depois de migrar as leituras para a Sorsa API?

Pode. Mantenha a API oficial do X para postar, responder e enviar DMs, e mande as leituras para a Sorsa API. A Sorsa API é somente leitura por princípio: a chave dela não consegue agir em nenhuma conta do X e nunca precisa do seu login do X, então as duas convivem sem conflito. Se o seu caminho de escrita ainda assina com tokens de usuário OAuth 1.0a, o X permite que os apps os troquem por tokens OAuth 2.0 desde 21 de setembro de 2026.

Preciso migrar da v1.1 para a v2 primeiro?

Não. O código que ainda chama leituras da v1.1 pode ser mapeado direto para a Sorsa API: statuses/user_timeline vira POST /user-tweets, statuses/show vira POST /tweet-info e users/show vira GET /info. O X classifica a v1.1 como legada, com suporte limitado, e descontinuou a busca da v1.1 em 2023, então parar na v2 significa reescrever para OAuth 2.0 e para a cobrança por uso antes de migrar de novo.

O que aconteceu com os planos legados Basic e Pro da API do X?

O X os migrou para o pagamento por uso: as assinaturas do Basic legado terminaram nas datas de migração depois de 1º de junho de 2026, e as do Pro, depois de 1º de setembro de 2026. Uma conta Pro mensal recebeu um crédito de US$ 5.000 na migração, com a recarga automática ativada. Agora as leituras são cobradas por recurso, US$ 0,005 por post e US$ 0,010 por usuário, enquanto os mesmos tweets custam a partir de US$ 0,07 por 1.000 por busca na Sorsa API.

#Como verificamos

Em 2 de novembro de 2026, montamos o mapa de endpoints comparando a especificação OpenAPI do próprio X (versão 2.173, 200 caminhos) com a referência em produção da Sorsa API (45 endpoints), e conferimos cada operador da v2 na lista de operadores do X e cada substituto nos operadores de busca da Sorsa API. No mesmo dia, lemos o changelog do X, a página de preços, a documentação de paginação e de rate limits, a referência do XDK para Python e o cliente do Tweepy 4.17.0, além dos avisos do fórum do X sobre o índice de busca, os planos legados e a cobrança de expansions. Não tínhamos uma chave da Sorsa API para esta rodada, então a resposta exibida usa valores de demonstração; executamos os blocos em Python e Node.js contra um mock local que responde nos formatos documentados das duas APIs.

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
  • Reescrito do zero como um guia de migração: as mudanças do X de 2023 a 2026 e o que cada uma quebra, um mapa de endpoints da v2 para a Sorsa API montado a partir das especificações das duas APIs, um conversor de requisições, os mapas de campos e operadores, código Tweepy antes e depois, polling no lugar de streams e um plano de teste com shadow run.
  • Primeira publicação.