Por Sorsa Editorial

Atualizado em julho de 2026: adicionada a opção inicial de 100 requisições grátis e atualizada a comparação de custo com o pagamento por uso da API oficial do X.

Índice

Em resumo {#key-takeaway}

O monitoramento do Twitter em tempo real funciona fazendo polling de um endpoint REST a cada 5 a 30 segundos, comparando os IDs de tweet retornados com o último ID visto e enviando os tweets novos para um pipeline de alerta. Para acompanhar muitas contas de uma vez, agrupe até 5.000 em uma Lista do X e faça polling de um único endpoint de lista.

Por que o monitoramento do Twitter em tempo real ficou mais difícil depois de 2023 {#why-real-time-twitter-monitoring-got-harder-after-2023}

Monitoramento do Twitter em tempo real costumava significar uma coisa: abrir uma conexão persistente com o filtered stream, definir algumas regras e deixar os tweets fluírem para a sua aplicação conforme eram postados. A reforma de preços de 2023 transformou isso em um recurso de nível Pro de US$ 5.000 por mês, e no início de 2026 o X foi além: passou a um modelo de pagamento por uso em que cada post entregue é cobrado e uma carga de monitoramento contínuo chega aos milhares de dólares por mês antes de bater em um teto de 2 milhões de leituras. Para a maioria das equipes (desenvolvedores independentes, times de monitoramento de marca, bots de trading, redações, agências de geração de leads), esse preço matou o projeto. A alternativa prática é você mesmo puxar os dados de uma API REST simples.

Este guia constrói esse padrão baseado em pull sobre a Sorsa API, um provedor alternativo de API do Twitter (X) que retorna dados de tweet frescos em cada requisição, roda com uma única chave de API sem fluxo OAuth e sem fila de aprovação, permite um limite fixo de 20 requisições por segundo em todos os planos e deixa você dobrar até 5.000 contas em uma chamada /list-tweets. O acesso de leitura parte de US$ 0,02 por 1.000 tweets (e de US$ 0,01 por 1.000 perfis) nos endpoints em lote, e você pode testar tudo com 100 requisições grátis, uma única vez e sem cartão, que cobrem todos os 40 endpoints. Com tempos de resposta em torno de 300 ms e a escolha certa de endpoint, você detecta um tweet novo em segundos após a publicação, e, para monitoramento de leitura intensa, custa uma fração do que a API oficial cobra. Para a comparação mais ampla de provedores, veja nossa visão geral de alternativa à API do Twitter.

Uma nota de terminologia: este artigo usa "polling" de propósito. Não é um eufemismo para "atrasado". Bem feito, um loop de polling retorna um tweet dentro do intervalo que você escolher mais o tempo de resposta da API. Se o seu loop roda a cada 5 segundos contra um endpoint de 300 ms, a sua latência de pior caso é de cerca de 5,3 segundos. Isso iguala ou supera a maioria dos produtos de streaming de nível de consumo e, o mais importante, funciona em um orçamento REST de taxa fixa.

Polling contra streaming: qual abordagem serve ao seu caso? {#polling-vs-streaming-which-approach-fits-your-case}

Há duas formas de obter dados de uma rede social: baseado em push (streaming, webhooks) ou baseado em pull (polling). A maioria dos engenheiros escolhe streaming por padrão porque soa mais rápido. Na prática, a escolha depende de três coisas: quantas coisas você monitora, o seu orçamento de latência e o seu apetite por estado de conexão.

FatorPolling (REST)Streaming (WebSocket / filtered stream)
Latência até o primeiro tweetIntervalo + tempo de resposta da APILatência de conexão, geralmente de 1 a 3 segundos
Complexidade de configuraçãoUma chamada de API em loopConexão persistente, lógica de reconexão, tratamento de backpressure
AutenticaçãoChave de API em um cabeçalhoOAuth ou rotação de token
Recuperação após quedaRetoma do cursor salvoReconectar, replay buffer, janela de deduplicação
Modelo de custoPor requisiçãoPor recurso entregue, ou um contrato enterprise
Melhor para1 a 5.000 alvos monitorados, alertas com tolerância de 1 a 30sLatência abaixo de um segundo, ingestão de firehose completo, trading em escala de milissegundos

O streaming vence quando você precisa de alertas de nível de milissegundo em um grande espaço de palavras-chave e tem capacidade de engenharia para lidar com reconexões, recuperação de lacunas e gestão de regras. Para todo o resto (escuta de marca, monitoramento de notícias, geração de leads, alertas de conformidade, sinais de trading de frequência média, moderação de conteúdo), o polling é mais simples, mais barato e bom o bastante.

A outra vantagem subestimada do polling: se o seu script cai, ele retoma de onde parou no ciclo seguinte. Pipelines de streaming precisam de um replay buffer separado para lidar com quedas sem perda de dados. Não entregamos um produto de webhook gerenciado de propósito; o padrão de pull mantém o plano de controle nas suas mãos, e o limite fixo de 20 requisições por segundo dá folga suficiente para loops em escala de produção.

Escolha o endpoint certo para o que você está monitorando {#pick-the-right-endpoint-for-what-youre-monitoring}

A primeira decisão de projeto é escolher o endpoint que combina com o formato do seu alvo. Quatro endpoints cobrem praticamente toda necessidade de monitoramento em tempo real.

Alvo de monitoramentoEndpointMétodoPor quê
Uma única conta/user-tweetsPOSTRetorna os tweets mais recentes da timeline de um usuário
Até 5.000 contas de uma vez/list-tweetsGETUma requisição cobre cada membro de uma Lista do X
Uma palavra-chave, hashtag ou consulta de busca/search-tweetsPOSTSintaxe completa de operadores, suporta order: latest para resultados cronológicos
@menções a um perfil específico/mentionsPOSTFeito sob medida para rastrear menções com filtros de engajamento

O endpoint que surpreende a maioria das equipes é o /list-tweets. Colocar 50 contas em uma única Lista e fazer polling do endpoint de lista corta o volume de requisições em cerca de 50 vezes em comparação com fazer polling de cada conta individualmente. O mesmo padrão escala para 500 ou 5.000 contas sem mudança no volume de requisições, e você cria a própria lista no x.com.

Nível 1: acompanhar uma única conta {#level-1-track-a-single-account}

O caso mais simples. Você quer saber o momento em que uma conta posta: um concorrente, um CEO, um regulador, um influenciador. Útil para monitoramento de baixo volume ou para testar o seu pipeline antes de escalar. Usa o endpoint /user-tweets.

Python

python
import requests
import time

API_KEY = "YOUR_API_KEY"
USERNAME = "elonmusk"
POLL_INTERVAL = 5  # seconds

URL = "https://api.sorsa.io/v3/user-tweets"
HEADERS = {"ApiKey": API_KEY, "Content-Type": "application/json"}

last_seen_id = None

print(f"Monitoring @{USERNAME}...")

while True:
    try:
        resp = requests.post(URL, headers=HEADERS, json={"username": USERNAME})
        resp.raise_for_status()
        tweets = resp.json().get("tweets", [])

        if tweets:
            # Tweet IDs are Snowflake strings. Cast to int for safe comparison
            # since lexicographic order can break across ID length boundaries.
            top_id = int(tweets[0]["id"])

            if last_seen_id is None:
                last_seen_id = top_id
                print(f"Baseline set: {last_seen_id}")
            else:
                new_tweets = [t for t in tweets if int(t["id"]) > last_seen_id]
                # Print in chronological order (oldest first).
                for tweet in reversed(new_tweets):
                    print(f"[NEW] @{USERNAME}: {tweet['full_text'][:140]}")
                if new_tweets:
                    last_seen_id = top_id

    except requests.exceptions.RequestException as e:
        print(f"Request error: {e}")
        time.sleep(POLL_INTERVAL * 2)
        continue

    time.sleep(POLL_INTERVAL)

JavaScript

javascript
const API_KEY = "YOUR_API_KEY";
const USERNAME = "elonmusk";
const POLL_INTERVAL = 5000;

let lastSeenId = null;
console.log(`Monitoring @${USERNAME}...`);

while (true) {
  try {
    const resp = await fetch("https://api.sorsa.io/v3/user-tweets", {
      method: "POST",
      headers: { "ApiKey": API_KEY, "Content-Type": "application/json" },
      body: JSON.stringify({ username: USERNAME }),
    });
    if (!resp.ok) throw new Error(`HTTP ${resp.status}`);

    const tweets = (await resp.json()).tweets || [];

    if (tweets.length > 0) {
      // BigInt comparison avoids precision loss on 64-bit Snowflake IDs.
      const topId = BigInt(tweets[0].id);

      if (lastSeenId === null) {
        lastSeenId = topId;
        console.log(`Baseline set: ${lastSeenId}`);
      } else {
        const newTweets = tweets.filter((t) => BigInt(t.id) > lastSeenId);
        for (const t of [...newTweets].reverse()) {
          console.log(`[NEW] @${USERNAME}: ${t.full_text.slice(0, 140)}`);
        }
        if (newTweets.length) lastSeenId = topId;
      }
    }
  } catch (err) {
    console.error(`Error: ${err.message}`);
    await new Promise((r) => setTimeout(r, POLL_INTERVAL * 2));
    continue;
  }
  await new Promise((r) => setTimeout(r, POLL_INTERVAL));
}

Dois detalhes no código acima importam. Primeiro, os IDs de tweet são valores Snowflake e chegam como strings. Compará-los como strings funciona dentro de uma única janela de tempo, mas é frágil ao cruzar limites de comprimento de ID; converta para int em Python ou BigInt em JavaScript. Segundo, o loop estabelece uma linha de base na primeira chamada bem-sucedida em vez de despejar a timeline inteira. Isso evita uma rajada de spam na inicialização.

Isso funciona, mas escala mal. Monitorar 50 contas significa 50 loops de polling separados e 50 vezes mais requisições de API. É aí que entram as Listas do X.

Nível 2: acompanhar até 5.000 contas em uma requisição {#level-2-track-up-to-5000-accounts-in-one-request}

As Listas do X são a ferramenta mais útil e mais subutilizada para monitoramento de várias contas. Uma Lista é um grupo público de contas (até 5.000), e o endpoint /list-tweets retorna os tweets mais recentes mesclados de todos os membros em uma única requisição. Monte uma Lista uma vez, aponte o seu poller para ela, e você terá, na prática, construído o seu próprio firehose personalizado sem pagar pelo oficial.

Passo 1: crie uma Lista pública do X

  1. Vá para Listas do X e crie uma nova lista.
  2. Adicione as contas que quer monitorar (até 5.000).
  3. Defina a lista como Pública. Listas privadas não são acessíveis pela API.
  4. Copie o ID da Lista da URL. Para https://x.com/i/lists/1234567890 o ID é 1234567890.

Passo 2: faça polling da lista

python
import requests
import time

API_KEY = "YOUR_API_KEY"
LIST_ID = "YOUR_LIST_ID"
POLL_INTERVAL = 5

URL = f"https://api.sorsa.io/v3/list-tweets?list_id={LIST_ID}"
HEADERS = {"ApiKey": API_KEY, "Accept": "application/json"}


def monitor_list(callback, interval=POLL_INTERVAL):
    """Poll an X List and call `callback` for each new tweet detected."""
    last_seen_id = None
    print(f"Monitoring List {LIST_ID} (interval: {interval}s)")

    while True:
        try:
            resp = requests.get(URL, headers=HEADERS, timeout=10)
            resp.raise_for_status()
            tweets = resp.json().get("tweets", [])

            if not tweets:
                time.sleep(interval)
                continue

            top_id = int(tweets[0]["id"])

            if last_seen_id is None:
                last_seen_id = top_id
                print(f"Baseline set: {last_seen_id}")
            else:
                new_tweets = [t for t in tweets if int(t["id"]) > last_seen_id]
                if new_tweets:
                    for tweet in reversed(new_tweets):
                        callback(tweet)
                    last_seen_id = top_id

        except requests.exceptions.RequestException as e:
            print(f"Request error: {e}. Retrying in {interval * 2}s")
            time.sleep(interval * 2)
            continue

        time.sleep(interval)


def on_new_tweet(tweet):
    user = tweet["user"]
    print(f"[NEW] @{user['username']}: {tweet['full_text'][:120]}")
    print(
        f"       Likes: {tweet.get('likes_count', 0)} | "
        f"RTs: {tweet.get('retweet_count', 0)} | "
        f"Views: {tweet.get('view_count', 'N/A')}\n"
    )


if __name__ == "__main__":
    monitor_list(on_new_tweet)

O ganho de eficiência é dramático. Monitorar 50 contas individualmente em um intervalo de 10 segundos custa 432.000 requisições por dia (50 loops de 8.640 requisições cada). Colocar essas mesmas 50 contas em uma Lista do X e fazer polling de /list-tweets custa 8.640 requisições por dia. Isso é uma redução de 50 vezes sem perda de cobertura.

Um senão: /list-tweets retorna até 20 tweets por página. Se os membros da sua Lista tuítam com tanta frequência que mais de 20 tweets novos chegam dentro de um intervalo de polling, você pode perder alguns. Duas correções: baixe o intervalo para 2 a 3 segundos, ou pagine via next_cursor até chegar a um ID já visto. Para a maioria dos casos (monitoramento de marca, redações, pesquisa de audiência), 20 tweets a cada 5 a 10 segundos é folga mais que suficiente.

Nível 3: acompanhar palavras-chave, hashtags e consultas de busca {#level-3-track-keywords-hashtags-and-search-queries}

O monitoramento por conta pega o que fontes conhecidas dizem. O monitoramento por palavra-chave pega o que qualquer um diz sobre o seu tema. Use o endpoint /search-tweets com order: "latest" para ter resultados cronológicos.

python
import requests
import time

API_KEY = "YOUR_API_KEY"
QUERY = '"your brand" OR @yourbrand lang:en'
POLL_INTERVAL = 10

URL = "https://api.sorsa.io/v3/search-tweets"
HEADERS = {"ApiKey": API_KEY, "Content-Type": "application/json"}


def monitor_keyword(query, callback, interval=10):
    last_seen_id = None
    print(f"Monitoring: {query} (interval: {interval}s)")

    while True:
        try:
            resp = requests.post(
                URL,
                headers=HEADERS,
                json={"query": query, "order": "latest"},
                timeout=10,
            )
            resp.raise_for_status()
            tweets = resp.json().get("tweets", [])

            if tweets:
                top_id = int(tweets[0]["id"])
                if last_seen_id is None:
                    last_seen_id = top_id
                    print(f"Baseline set: {last_seen_id}")
                else:
                    new_tweets = [t for t in tweets if int(t["id"]) > last_seen_id]
                    for tweet in reversed(new_tweets):
                        callback(tweet)
                    if new_tweets:
                        last_seen_id = top_id

        except requests.exceptions.RequestException as e:
            print(f"Error: {e}")
            time.sleep(interval * 2)
            continue

        time.sleep(interval)

O poder de verdade vive na string de consulta. A API suporta o conjunto completo de operadores da busca avançada do Twitter (uma referência não oficial está em igorbrigadir/twitter-advanced-search). Por exemplo, para acompanhar menções em inglês de alto engajamento à sua marca e pular retweets:

python
monitor_keyword('"your brand" min_faves:10 lang:en -filter:retweets', on_new_tweet)

Alguns operadores que se pagam no monitoramento em tempo real:

  • min_faves:N, min_retweets:N para filtrar conteúdo que já viralizou.
  • -filter:retweets, -filter:replies para descartar ruído.
  • from:user1 OR from:user2 para monitorar um punhado de contas sem uma Lista.
  • (keyword1 OR keyword2) (problem OR issue OR broken) para pegar menções carregadas de sentimento.
  • near:"san francisco" within:25mi para monitoramento delimitado por geografia.

Os fluxos de palavra-chave em 2026 são mais ruidosos do que já foram: respostas automatizadas, contas de golpe e spam gerado por IA se acumulam em qualquer termo popular. Os limiares de engajamento são o seu filtro mais barato na fonte. Um piso como min_faves:5 ou min_replies:2 tira a maior parte do ruído descartável antes mesmo de chegar ao seu callback, então você fica com posts que têm pelo menos alguma tração. Se você observa especificamente as menções a um perfil, e não palavras-chave abertas, a API de menções do Twitter expõe o conjunto de filtros mais rico (min_likes, min_replies, min_retweets, limites de data) exatamente para esse tipo de limpeza.

Se a sua string de consulta começar a ficar difícil de manejar, o playground do construtor de buscas deixa você montá-la visualmente e ver o conjunto completo de operadores conforme avança.

Envie novos tweets para Slack, Discord ou qualquer endpoint HTTP {#push-new-tweets-to-slack-discord-or-any-http-endpoint}

O loop de polling é o produtor. O callback é onde você decide o que acontece com cada tweet novo. Como o callback é apenas uma função, o mesmo monitor pode rotear para qualquer coisa que fale HTTP. Slack primeiro, por ser o destino mais comum, depois algumas variantes rápidas.

Slack via Incoming Webhook

python
import requests

SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"


def send_to_slack(tweet):
    user = tweet["user"]
    text = (
        f"*New tweet from @{user['username']}*\n"
        f"{tweet['full_text']}\n"
        f"Likes: {tweet.get('likes_count', 0)} | "
        f"RTs: {tweet.get('retweet_count', 0)} | "
        f"Views: {tweet.get('view_count', 'N/A')}\n"
        f"https://x.com/{user['username']}/status/{tweet['id']}"
    )
    requests.post(SLACK_WEBHOOK_URL, json={"text": text})


# Plug into any monitor:
monitor_list(send_to_slack)
# or: monitor_keyword("bitcoin lang:en min_faves:50", send_to_slack)

Configure a URL do Incoming Webhook do Slack nas configurações do seu app do Slack (documentação oficial do Slack). Mesmo padrão para Discord, Telegram ou qualquer endpoint interno.

Discord

python
DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/YOUR/WEBHOOK"


def send_to_discord(tweet):
    user = tweet["user"]
    content = (
        f"**@{user['username']}** just tweeted:\n"
        f"{tweet['full_text']}\n"
        f"https://x.com/{user['username']}/status/{tweet['id']}"
    )
    requests.post(DISCORD_WEBHOOK_URL, json={"content": content})

A configuração do webhook do Discord está documentada em discord.com/developers/docs/resources/webhook.

Telegram

python
TELEGRAM_BOT_TOKEN = "YOUR_BOT_TOKEN"
TELEGRAM_CHAT_ID = "YOUR_CHAT_ID"


def send_to_telegram(tweet):
    user = tweet["user"]
    text = (
        f"New tweet from @{user['username']}\n\n"
        f"{tweet['full_text']}\n\n"
        f"https://x.com/{user['username']}/status/{tweet['id']}"
    )
    requests.post(
        f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage",
        json={"chat_id": TELEGRAM_CHAT_ID, "text": text},
    )

Qualquer endpoint HTTP personalizado

python
def send_to_internal_api(tweet):
    requests.post(
        "https://internal.example.com/events/twitter",
        json={
            "tweet_id": tweet["id"],
            "username": tweet["user"]["username"],
            "text": tweet["full_text"],
            "metrics": {
                "likes": tweet.get("likes_count", 0),
                "retweets": tweet.get("retweet_count", 0),
                "views": tweet.get("view_count", 0),
            },
            "url": f"https://x.com/{tweet['user']['username']}/status/{tweet['id']}",
        },
        headers={"Authorization": "Bearer YOUR_INTERNAL_TOKEN"},
        timeout=5,
    )

O que você construiu é, na prática, o seu próprio relay de webhook. A API fornece os dados; o seu callback decide quem ouve sobre cada tweet novo. A vantagem de ser dono desse relay é que você mantém todas as regras de roteamento no seu código (filtragem, rate limit, fan-out para vários canais, política de retentativa) em vez de dentro do painel de um fornecedor.

Com que frequência fazer o polling, e quanto custa? {#how-often-should-you-poll-and-what-does-it-cost}

Cada ciclo do seu loop custa uma requisição, e uma requisição da Sorsa é uma unidade do seu plano, não importa qual endpoint ela acerte. O intervalo que você escolher move o seu uso mensal diretamente, e no preço fixo por requisição ele mapeia de forma limpa para um plano.

IntervaloRequisições / horaRequisições / diaRequisições / 30 diasPlano para um loop
1 segundo3.60086.4002.592.000Sob medida (acima do Enterprise)
5 segundos72017.280518.400Sob medida (logo acima do Enterprise)
10 segundos3608.640259.200Enterprise (US$ 899/mês)
30 segundos1202.88086.400Pro (US$ 199/mês)
1 minuto601.44043.200Pro (US$ 199/mês)

Os números são para um único loop contínuo; rodar vários loops em paralelo soma os respectivos números de requisições. As cotas dos planos são Starter 10 mil, Pro 100 mil e Enterprise 500 mil requisições por mês, com cotas sob medida acima disso.

Algumas diretrizes práticas de rodar esses loops em produção:

  • Escuta de marca, monitoramento de notícias, geração de leads: 10 a 30 segundos é de sobra. Você pega qualquer tweet novo em até meio minuto após a publicação, e a pegada mensal é pequena.
  • Detecção de sinal financeiro, bots de notícias de última hora, fluxos de trading: 1 a 5 segundos. Você vai queimar mais requisições, mas o orçamento de latência justifica.
  • Conformidade, auditoria, pesquisa de ritmo lento: 1 a 5 minutos. Tempo real é exagero para casos em que a janela de ação é medida em horas.

Uma cadência de 30 segundos a 1 minuto em uma única Lista fica dentro do plano Pro a US$ 199 por mês. Apertar para um loop de 10 segundos (cerca de 259.000 requisições) move você para o Enterprise a US$ 899, e mesmo um loop de 1 segundo em um alvo de alta prioridade fica bem abaixo do que a API oficial do X cobra por acesso comparável em tempo real.

Robustez de produção: cinco coisas para resolver antes de ir ao ar {#production-hardening-five-things-to-fix-before-going-live}

Os exemplos acima são de propósito mínimos. Antes de apontar um deles para tráfego de produção, resolva estas cinco preocupações.

1. Persista o last_seen_id entre reinicializações

Se o seu script cai e reinicia sem lembrar do checkpoint, duas coisas dão errado: ou ele reprocessa tweets antigos (alertas duplicados no seu canal do Slack) ou define uma nova linha de base e perde a lacuna em silêncio. Guarde o checkpoint em um arquivo, no Redis ou no seu banco de dados.

python
import json
import os

STATE_FILE = "monitor_state.json"


def load_state():
    if os.path.exists(STATE_FILE):
        with open(STATE_FILE) as f:
            return json.load(f).get("last_seen_id")
    return None


def save_state(last_seen_id):
    with open(STATE_FILE, "w") as f:
        json.dump({"last_seen_id": last_seen_id}, f)

Carregue na inicialização, salve após cada polling bem-sucedido que atualize o cursor.

2. Backoff exponencial em erros

Problemas de rede, respostas 5xx transitórias e batidas de rate limit (HTTP 429) acontecem. Em vez de repetir na hora e piorar tudo, recue gradualmente com um teto.

python
retry_delay = POLL_INTERVAL
MAX_DELAY = 60

while True:
    try:
        resp = requests.get(URL, headers=HEADERS, timeout=10)
        if resp.status_code == 429:
            print(f"Rate limited. Backing off {retry_delay}s")
            time.sleep(retry_delay)
            retry_delay = min(retry_delay * 2, MAX_DELAY)
            continue
        resp.raise_for_status()
        retry_delay = POLL_INTERVAL  # reset on success
        # process tweets
    except requests.exceptions.RequestException as e:
        print(f"Error: {e}")
        time.sleep(retry_delay)
        retry_delay = min(retry_delay * 2, MAX_DELAY)
        continue

    time.sleep(POLL_INTERVAL)

Recue gradualmente, limite o atraso e volte ao seu intervalo normal na primeira vez que der certo, para que um 429 breve não prenda o seu monitor em uma cadência lenta.

3. Desacople o polling do processamento

Não rode operações caras (pontuação de sentimento, gravações em banco, chamadas de API externas, classificação por IA) de forma síncrona dentro do loop de polling. Se um sistema a jusante ficar lento, o seu loop atrasa e a latência dispara. Empurre os tweets novos para uma fila e processe-os em um worker separado.

python
from collections import deque
import threading

tweet_queue = deque()


def polling_loop():
    """Fast loop: poll and enqueue. No heavy work here."""
    # standard polling code, but instead of calling the callback directly:
    # tweet_queue.append(tweet)
    pass


def processing_worker():
    """Separate thread: dequeue and dispatch."""
    while True:
        if tweet_queue:
            tweet = tweet_queue.popleft()
            send_to_slack(tweet)
            save_to_database(tweet)
        else:
            time.sleep(0.1)


threading.Thread(target=processing_worker, daemon=True).start()
polling_loop()

Para cargas mais pesadas, troque o deque em memória por Redis, RabbitMQ, SQS ou qualquer message broker que o seu stack já rode.

4. Health checks e monitorar o monitor

Registre cada ciclo de polling: timestamp, contagem de tweets novos, tempo de resposta, erros. Alerte se o monitor não completou um polling bem-sucedido nos últimos N minutos. Falhas silenciosas são as mais caras, especialmente em pipelines de alerta, em que a ausência de alertas significa "nada aconteceu" até alguém notar a lacuna nos dados. Você pode checar o status operacional da API na página de status da Sorsa para descartar problemas de plataforma antes de depurar o seu próprio código.

5. Trate os casos de borda que mordem em produção

  • Tweets apagados: se um tweet é apagado entre a busca e o disparo do seu callback, a URL vai dar 404. Trate isso como esperado, não como erro.
  • Contas protegidas: se um usuário acompanhado fica privado, /user-tweets retorna uma lista vazia. Registre e continue.
  • Tweets fixados: o primeiro tweet em uma resposta de /user-tweets costuma ser o tweet fixado, não o mais recente. Ordene por created_at se você liga para ordem cronológica estrita.
  • Retweets contra tweets originais: tweet["retweeted_status"] é preenchido para retweets. Decida se você quer os dois ou só os originais.
  • Respostas limitadas: is_replies_limited indica que o autor restringiu as respostas. Sinal útil para alguns casos de monitoramento.

Na prática: uma migração de monitoramento de marca {#in-practice-a-brand-monitoring-migration}

Uma empresa de SaaS com quem trabalhamos vinha rodando monitoramento de marca no filtered stream oficial desde 2018. O setup deles acompanhava cerca de 200 regras de palavra-chave e 60 contas prioritárias e, no início de 2024, custava US$ 5.000 por mês no nível Pro. O pitch interno foi direto: cortar o stream, economizar o dinheiro e torcer para nada quebrar.

A migração levou duas semanas. Mesclamos as regras de palavra-chave em dois workers compostos de /search-tweets (as regras se juntaram em consultas booleanas com operadores OR) fazendo polling a cada 30 segundos, e substituímos o acompanhamento das 60 contas por uma Lista do X com polling a cada 15 segundos. A pegada combinada ficou em cerca de 350.000 requisições por mês, confortavelmente dentro do plano Enterprise a US$ 899 por mês contra os US$ 5.000 que vinham pagando. A latência de alerta de ponta a ponta foi de cerca de 2 segundos no filtered stream para cerca de 15 segundos no percentil 90. Para uma equipe de PR respondendo a menções de marca no Slack, a mudança de latência foi invisível. A mudança na conta, não.

Casos de uso em que essa abordagem se paga {#use-cases-where-this-approach-earns-its-keep}

Cinco padrões que mais vemos.

Escuta de marca e social CRM. Faça polling de /search-tweets para o @ da sua marca mais palavras-chave de nome de produto, a cada 15 a 30 segundos. Roteie para o Slack com dicas de sentimento embutidas na mensagem, e a equipe de PR responde em minutos. Esse é o núcleo de qualquer setup de escuta de marca e social listening.

Detecção de notícias e sinais. Monte uma Lista de perfis de notícias de última hora (Reuters, AP, Bloomberg, veículos regionais, repórteres de área) e faça polling a cada 5 segundos. Faça fan-out para um servidor do Discord ou um dashboard de trading. Essa é a versão mais barata de um "firehose de notícias" que dá para montar em 2026.

Inteligência competitiva. Uma Lista de contas de concorrentes mais seus CEOs e líderes de produto, com polling a cada 30 segundos. Tweets novos caem em um canal compartilhado, e o seu time de PMM ganha um feed de inteligência gratuito sem ninguém passar por 40 perfis. Essa é a camada ao vivo de um setup contínuo de acompanhamento de concorrentes.

Geração de leads. Faça polling de /search-tweets para consultas de enunciado de problema: "any recommendations for" (CRM OR analytics OR transcription), "looking for an alternative to", "we just churned from". Roteie para um canal do Slack revisado pelo time de vendas. A maioria das equipes que roda isso pega de 5 a 15 leads qualificados por semana por grupo de consulta. É o motor em tempo real por trás da geração de leads no Twitter em escala.

Sinais de KOLs de cripto. Monte uma Lista de influenciadores de cripto e contas de projetos, faça polling a 2 a 5 segundos e, opcionalmente, pondere os sinais pela qualidade da audiência usando os endpoints de Sorsa Score.

Custo contra a API oficial do X para monitoramento em tempo real {#cost-vs-the-official-x-api-for-real-time-monitoring}

Aviso: a Sorsa é o nosso produto, então trate isto como a nossa leitura e teste qualquer opção contra a sua própria carga. Os números dos dois lados são reais e atuais em julho de 2026.

Os dois provedores cobram em unidades completamente diferentes. A API oficial do X cobra por recurso buscado: no modelo de pagamento por uso em vigor desde o início de 2026, cada post lido custa US$ 0,005 e o perfil do autor anexado a um tweet é uma leitura de usuário separada de US$ 0,010. A Sorsa cobra por requisição, e uma requisição retorna cerca de 20 tweets (ou até 200 perfis nos endpoints de seguidores) com os dados do autor incluídos. Esse contraste estrutural é o que gera a diferença de custo para monitoramento.

API oficial do X (pagamento por uso, 2026)Sorsa
Modelo de preçoPor recurso buscadoFixo por requisição (1 chamada = 1 requisição)
Leituras de postsUS$ 0,005 por post lidoIncluídas na requisição, sem cobrança por post
Perfil do autor em um tweetCobrado à parte, US$ 0,010 por leitura de usuárioIncluído de graça na resposta do tweet
Monitoramento 24/7 (~1,7 milhão de leituras de posts/mês)~US$ 8.600/mêsPlano Enterprise, US$ 899/mês
Teto mensal de leitura2 milhões de leituras de posts, depois Enterprise obrigatórioCota por plano, sem teto por post
Acima do tetoContrato Enterprise, historicamente ~US$ 42.000+/mêsPlano sob medida com cota elevada
AutenticaçãoOAuth 2.0 + Bearer tokenUma única chave de API em um cabeçalho
Rate limitVaria por endpointFixo de 20 requisições/segundo em todos os planos

A troca é a latência: o filtered stream entrega tweets em um ou dois segundos, enquanto o polling os entrega dentro do seu intervalo mais cerca de 300 ms de tempo de resposta. Para a maioria dos casos de monitoramento, essa diferença é invisível. Para bots de trading abaixo de um segundo, não é, e um stream de verdade é a ferramenta certa, seja qual for o fornecedor. Mas, para monitoramento de leitura intensa em escala de marca, notícias ou concorrência, pagar por post entregue soma rápido e esbarra na parede de 2 milhões de leituras, onde um plano fixo por requisição não esbarra. Para o detalhamento completo de preços por caso de uso, veja preços da API do Twitter em 2026.

Perguntas frequentes {#faq}

O polling REST é mesmo "tempo real"?

O polling REST é quase tempo real. O orçamento de latência é o intervalo de polling mais o tempo de resposta da API, que fica em torno de 300 ms em um endpoint rápido. Em um intervalo de 5 segundos, o pior caso é de cerca de 5,3 segundos entre um tweet ser postado e o seu callback disparar. Para a imensa maioria dos casos de monitoramento, isso atende à definição prática de tempo real; só trading em escala de milissegundo e leilão de eventos ao vivo precisam de um stream de verdade.

Quantas contas dá para monitorar com uma chave de API?

Com a Sorsa, uma chave de API pode monitorar um número praticamente ilimitado de contas por meio das Listas do X. Uma única Lista comporta até 5.000 contas e conta como uma requisição /list-tweets por polling. Várias Listas rodam em paralelo dentro do limite fixo de 20 requisições por segundo, o que deixa espaço para centenas de jobs de monitoramento simultâneos em uma única chave.

O que acontece ao bater no rate limit?

A Sorsa retorna uma resposta HTTP 429 quando você excede o limite fixo de 20 requisições por segundo. Recue por um segundo, repita, e o loop continua; não há caixa de penalidade nem bloqueio. A maioria das cadências de polling fica bem abaixo de 20 requisições por segundo, então monitores de produção raramente veem um 429, e limites mais altos estão disponíveis sob solicitação.

Como evitar alertas duplicados quando o script reinicia?

Para evitar alertas duplicados, persista o último ID de tweet visto em um armazenamento durável (um arquivo, o Redis ou um banco de dados) após cada polling bem-sucedido. Na inicialização, carregue esse ID e use-o como linha de base para o loop só disparar tweets mais novos que o checkpoint. Sem persistência, um reinício ou reproduz tweets antigos ou pula a lacuna em silêncio.

Dá para monitorar contas privadas ou protegidas?

Nenhuma ferramenta acessa contas privadas ou protegidas do Twitter (X), e a Sorsa revela apenas dados públicos. Se uma conta acompanhada fica privada no meio do monitoramento, o endpoint retorna uma lista vazia e o loop de polling continua sem erro. Essa é uma regra de privacidade no nível da plataforma, não uma limitação específica de um provedor.

Webhooks gerenciados são suportados?

A Sorsa não entrega um produto de webhook gerenciado; o caminho de tempo real suportado é o padrão de polling deste guia, em que o seu próprio callback roteia cada tweet novo. A vantagem é o controle total sobre filtragem, fan-out e lógica de retentativa no seu próprio código. Equipes que querem especificamente entrega push hospedada pelo fornecedor olhariam para os webhooks Account Activity da API oficial do X, em níveis enterprise.

Quão frescos são os dados retornados?

Os dados são frescos em cada requisição, sem camada de cache entre a sua chamada e a plataforma. Se um tweet foi postado meio segundo atrás, o próximo polling o pega. Combinado com tempos de resposta em torno de 300 ms, essa frescura é o que torna o polling viável para monitoramento, e não só para análise posterior.

Dá para combinar monitoramento em tempo real com backfill histórico?

Sim, e a maioria dos pipelines de produção faz os dois. Os mesmos endpoints usados para monitoramento (/user-tweets, /search-tweets, /list-tweets) aceitam um parâmetro next_cursor para paginar para trás pelo histórico em um backfill único, e depois você troca para o loop de polling para dados novos daí em diante. Veja nosso guia de dados históricos do Twitter para o lado do backfill.

Primeiros passos {#getting-started}

Para montar o seu próprio pipeline de monitoramento em tempo real:

  1. Pegue uma chave de API no painel da Sorsa. Uma chave funciona em todos os endpoints, e toda conta começa com 100 requisições grátis (uma única vez, sem cartão), para você ligar um loop antes de escolher um plano.
  2. Teste de forma interativa no playground da API: acerte /user-tweets ou /list-tweets com um username ou ID de lista conhecido e confirme que vê resultados ao vivo.
  3. Copie um dos loops deste artigo (conta única, Lista ou palavra-chave) e troque a chave de API.
  4. Adicione um callback que roteia para onde você quer os alertas (Slack, Discord, API interna, fila).
  5. Adicione a robustez de produção (persistência de estado, backoff, processamento desacoplado) assim que o loop básico estiver estável.

Estime o seu uso mensal pela tabela de intervalos, escolha um plano e publique. O guia de início rápido percorre a primeira chamada de ponta a ponta. Se você precisa de rate limits mais altos ou volume acima dos planos padrão, fale com vendas e nós montamos uma cota sob medida.


Revisado por Keksich, fundador da Sorsa, profissional de marketing e pesquisador da API do X.

Este guia é escrito e mantido pela equipe que constrói e opera a Sorsa, uma API alternativa do Twitter (X) que já serviu mais de 5 bilhões de requisições desde 2022. Cada amostra de código roda contra os endpoints /user-tweets, /list-tweets e /search-tweets ao vivo, e os padrões de polling, backoff e persistência vêm de loops de monitoramento que rodamos em produção. A comparação de custo reflete o modelo de pagamento por uso da API oficial do X em vigor após a atualização de abril de 2026, com detalhes de preço e rate limit verificados em julho de 2026. Mais sobre a equipe está na nossa página sobre a Sorsa.