Twitter/X Scraper - Tweets, Profiles & Trends avatar

Twitter/X Scraper - Tweets, Profiles & Trends

Pricing

from $10.00 / 1,000 tweet scrapeds

Go to Apify Store
Twitter/X Scraper - Tweets, Profiles & Trends

Twitter/X Scraper - Tweets, Profiles & Trends

Scrape Twitter/X: tweets, user profiles, followers, hashtags, and trending topics.

Pricing

from $10.00 / 1,000 tweet scrapeds

Rating

5.0

(4)

Developer

viralanalyzer

viralanalyzer

Maintained by Community

Actor stats

0

Bookmarked

121

Total users

4

Monthly active users

4 days ago

Last modified

Share

Twitter/X Scraper 🐦

🔗 View on Apify Store | 🇺🇸 English | 🇧🇷 Português

Scrape tweets, profiles, and engagement metrics from Twitter/X. Bring your own X API v2 Bearer Token for reliable access (recommended — X blocks anonymous timeline access), or use the anonymous fallback with configurable proxies.


🇺🇸 English

What does it do?

This actor extracts public tweets and engagement metrics from any Twitter/X profile or search query. Get real data for social media analysis, brand monitoring, and competitive intelligence.

Features

  • Profile scraping — Get latest tweets from any public profile
  • Search scraping — Find tweets matching any keyword or hashtag
  • Full metrics — Views, likes, retweets, replies, quotes, bookmarks
  • Media extraction — Each attachment as { type, url }, from the anonymous strategies
  • Thread detection — Identifies if a tweet is part of a thread
  • Author info — Username, display name, follower count, verification status
  • Date filtering — dateFrom / dateTo restrict results to a date range (UTC, both bounds inclusive), applied to each tweet's created_at before billing
  • Reply/Retweet filters — Include or exclude replies and retweets
  • Replies mode — pass tweetUrls (or conversationIds) and get one row per reply of a post, with the author and the badge
  • Newest first — the batch is ordered by created_at and the pinned tweet is excluded before the cut, so maxTweets: 1 returns the most recent tweet, not a pinned one from years ago
  • Verification badge — author.verifiedType (blue | business | government | none), author.isBlueVerified and the legacy author.verified
  • No invented values — a metric the source did not expose is null, never 0/false

Capabilities & Limits

Built here — measured 2026-09-23, read this before choosing a path:

  • No token needed for the common case. The actor reads the server-rendered x.com page, which embeds the profile's 5 newest tweets with view counts, the pinned marker and reposts. Measured 2026-09-23: a profile whose syndication widget stopped in 2023 came back with its 2025 posts here, with views filled.
  • More than ~5 tweets falls back to X's syndication widget (up to 100 per profile). That widget orders by likes, not by date, has no view count and hides retweets and replies — the actor sorts by date anyway and the run log warns when the newest tweet delivered is over 30 days old.
  • Replies come from the post's own page (the first few, with author and badge). With an X API token the actor uses recent search instead, which covers the last 7 days.
  • With your X API token the official API is used first: it paginates, sends your dateFrom/dateTo as start_time/end_time (so you do not pay for reads the filter would throw away), asks for media expansions and reads the pinned post id. X bills your own plan at $0.005 per post read, with minimums of 5 posts per timeline request and 10 per search.
  • Optional unblocking fallback. If x.com refuses the ordinary request, and only then, the actor can fetch the same page through Bright Data Web Unlocker — billed per request, capped by maxUnlockerRequests (default 3). Leave brightDataApiToken empty to skip it.

What this actor can and cannot accept as a seed, based on the real input schema:

Discover bySupportedNotes
Handle / username✅ Yesprofiles array (without @)
Hashtag⚠️ PartialNo dedicated field — pass it inside searchQuery (e.g. #tech); search mode needs the X API Bearer Token
Keyword / search⚠️ PartialsearchQuery works only with an X API v2 Bearer Token (X removed anonymous search); recent tweets only
Profile URL✅ YesstartUrls or seeds + seedType: "url"; x.com/home, /search and /i/... are rejected and named in the log
Tweet URL (replies)✅ YestweetUrls — returns the replies of that post, one row each
Subreddit❌ N/ANot a Reddit actor

Output includes: tweet text ✅, views ✅, likes ✅, retweets ✅, replies count ✅, quotes ✅, bookmarks ✅, hashtags ✅, media ✅, author (username, displayName, followers, verified) ✅, created_at (ISO 8601) ✅, language ✅, is_thread / is_reply / is_retweet ✅.

Not in the outputWhy
Reply / comment text⚠️ replies modein timeline mode only the reply count is returned. Pass tweetUrls to get the text of each reply — with an X API token: without one, X answered the anonymous conversation request with HTTP 404 (measured 2026-09-23) and the run returns a diagnostic without charging
thumbnail on media items❌a media entry is { type, url } — X's own media URL. No separate thumbnail or :small variant is emitted
Impressions on the syndication fallback⚠️the widget carries no view count, so views is null for tweets that came from it. The x.com page (used first) does carry views

Input

FieldTypeDefaultDescription
profilesstring[]—Twitter/X usernames (with or without @). With no profile, search or tweet URL the run returns a diagnostic instead of scraping a default account
tweetUrlsstring[]—Replies mode: URLs (or ids) of the posts whose replies you want
includePinnedbooleanfalseKeep the pinned tweet in the results (it is excluded by default because it is often years old)
brightDataApiTokenstring—Optional unblocking fallback, billed per request. Empty = never used
maxUnlockerRequestsinteger3Hard cap on that paid fallback per run
searchQuerystring—Search term (alternative to profiles)
maxTweetsinteger20Max tweets per profile/search (1-100)
includeRepliesbooleanfalseInclude reply tweets
includeRetweetsbooleanfalseInclude retweets
dateFromstring—Inclusive lower bound on created_at. YYYY-MM-DD (= 00:00:00.000Z UTC) or full ISO-8601
dateTostring—Inclusive upper bound on created_at. YYYY-MM-DD (= 23:59:59.999Z UTC, whole day included) or full ISO-8601

Date range (dateFrom / dateTo) - exact behavior

Both fields are optional and independent; leaving one empty leaves that side unbounded, and leaving both empty disables the filter entirely.

  • Where it runs. With an X API token the bounds are sent to the API as start_time/end_time, so you are not billed for posts the filter would discard (the API accepts dates from 2010-11-06 on the timeline; recent search only covers the last 7 days). The anonymous strategies have no date parameter, so there the comparison happens locally on each tweet's created_at — a narrow or old range can return fewer items than maxTweets, or nothing at all.
  • Inclusive, UTC. A tweet is kept when dateFrom <= created_at <= dateTo. YYYY-MM-DD in dateFrom means 00:00:00.000Z of that day; in dateTo it means 23:59:59.999Z, so dateFrom = dateTo = 2026-01-20 returns that whole day. A full ISO-8601 timestamp is used exactly as given.
  • Billing. The filter runs before the tweet is stored and before the Pay Per Event counter is incremented. You are never charged for a tweet the date filter discards.
  • Tweets with no date. A few anonymous fallback paths return a tweet whose created_at is null. While any bound is set, such a tweet is dropped - its membership in the range cannot be verified, so it is neither returned nor charged. The run log reports how many were dropped for this reason.
  • Invalid input. An unreadable dateFrom / dateTo, or a range where dateFrom is after dateTo, stops the run with a labeled _dataQuality: "diagnostic" item explaining the problem, and charges nothing. The filter is never silently ignored.
  • Nothing in range. If tweets were found but all fell outside the range, the run succeeds with a diagnostic item stating how many were discarded - again with no charge.

Output Example

{
"tweet_id": "1891234567890123456",
"url": "https://x.com/elikifreitasdev/status/1891234567890123456",
"text": "🚀 Launched the new version! Performance 3x better #tech #automation",
"author": {
"username": "elikifreitasdev",
"displayName": "Eliki Freitas | Dev",
"followers": 12500,
"verified": false,
"isBlueVerified": true,
"verifiedType": "blue"
},
"created_at": "2026-01-20T14:30:00.000Z",
"views": 45200,
"likes": 892,
"retweets": 156,
"replies": 43,
"quotes": 12,
"bookmarks": 234,
"hashtags": ["tech", "automation"],
"media": [
{
"type": "image",
"url": "https://pbs.twimg.com/media/example.jpg"
}
],
"is_thread": false,
"is_reply": false,
"is_retweet": false,
"is_pinned": false,
"conversation_id": "1891234567890123456",
"in_reply_to_id": null,
"language": "en"
}

Use Cases

  1. Brand Monitoring — Track mentions and sentiment about your brand
  2. Competitor Analysis — Monitor competitor tweet performance
  3. Influencer Research — Evaluate engagement rates before partnerships
  4. Trend Detection — Discover viral topics and hashtags
  5. Content Strategy — Analyze what tweet formats get the most engagement

FAQ

Does it require a Twitter API key? Recommended. X blocks anonymous (guest) access to timelines, so for reliable results provide your own twitterBearerToken (X API v2 — your own plan/quota at https://developer.x.com). Search/keyword mode (searchQuery) requires the Bearer Token (X removed anonymous search). Without a token, the actor tries anonymous strategies (subject to blocking) and, if nothing is extracted, returns a diagnostic guide without charging PPE.

Why did dateFrom / dateTo return fewer tweets than maxTweets? Because the range is applied locally, to the tweets the actor was able to fetch (the most recent ones a strategy exposes), not as a remote query parameter. Tweets outside the range — and, while a bound is set, tweets with no readable created_at — are dropped before being stored, and are not charged. See "Date range — exact behavior" above.

Why did I get an old tweet / when is views null? The syndication widget returns a profile's tweets ordered by engagement, not by date, and the old build pushed whatever came first — that is why a 2022 post was returned for maxTweets: 1. The actor now reads the x.com page first (newest tweets, with view counts), orders everything by created_at and drops the pinned tweet before cutting. views is null only for tweets that came from the syndication fallback, which has no impression count — never a fabricated 0.

What do verified, isBlueVerified and verifiedType mean? verifiedType is X's own value: blue, business, government or none. isBlueVerified is true only for the blue badge. verified is the legacy flag. Any of them is null when the source did not say — null means unknown, false means the source said no.

How do I read the replies of a post? Set tweetUrls: ["https://x.com/nasa/status/123..."]. Without a token the actor reads the post's own page and returns the first replies X renders there (3 in the measurements, each with author and badge) — enough to sample a conversation, not to export all of it. With an X API token it uses recent search with the conversation_id operator instead, which returns the whole thread for the last 7 days (older threads need X's full-archive access).

Can it scrape protected/private accounts? No. Only public profiles and public tweets are accessible.

What about rate limits? The actor handles rate limiting automatically with built-in delays and retries.

How many tweets can I get per run? Up to 100 tweets per profile or search query per run.


🇧🇷 Português

O que faz?

Este actor extrai tweets públicos e métricas de engajamento de qualquer perfil ou busca no Twitter/X. Dados reais para análise de redes sociais, monitoramento de marca e inteligência competitiva.

Funcionalidades

  • Scraping de perfil — Últimos tweets de qualquer perfil público
  • Scraping de busca — Encontre tweets por palavra-chave ou hashtag
  • Métricas completas — Visualizações, curtidas, retweets, respostas, citações, bookmarks
  • Extração de mídia — Cada anexo como { type, url }, vindo das estratégias anônimas
  • Detecção de thread — Identifica se o tweet faz parte de uma thread
  • Info do autor — Username, nome, seguidores, verificação
  • Filtro por data — dateFrom / dateTo restringem os resultados a um período (UTC, ambos os limites inclusivos), aplicados ao created_at de cada tweet antes da cobrança
  • Filtros de resposta/retweet — Inclua ou exclua respostas e retweets
  • Modo replies — informe tweetUrls (ou conversationIds) e receba uma linha por resposta do post, com o autor e o selo
  • Mais recente primeiro — o lote é ordenado por created_at e o tweet fixado é excluído antes do corte, então maxTweets: 1 devolve o tweet mais recente, não um fixado de anos atrás
  • Selo de verificação — author.verifiedType (blue | business | government | none), author.isBlueVerified e o author.verified legado
  • Sem valor inventado — métrica que a fonte não expôs vem null, nunca 0/false

Capacidades e Limites

Medido em 2026-09-23, leia antes de escolher o caminho:

  • Sem token no caso comum. O actor lê a página do x.com renderizada no servidor, que já traz os 5 tweets mais recentes com contagem de visualizações, o marcador de fixado e as repostagens. Medido em 2026-09-23: um perfil cujo widget de syndication parava em 2023 voltou aqui com posts de 2025, com views preenchido.
  • Acima de ~5 tweets entra o widget de syndication (até 100 por perfil). Esse widget ordena por curtidas, não por data, não tem visualizações e esconde retweets e respostas — o actor ordena por data mesmo assim, e o log avisa quando o tweet mais recente tem mais de 30 dias.
  • Respostas vêm da página do próprio post (as primeiras, com autor e selo). Com token da API do X o actor usa a busca recente, que cobre os últimos 7 dias.
  • Com o seu token da API do X a API oficial vem primeiro: pagina, envia dateFrom/dateTo como start_time/end_time, pede as expansões de mídia e lê o id do fixado. O X cobra do seu plano US$ 0,005 por post lido, com mínimos de 5 posts por requisição de timeline e 10 por busca.
  • Fallback opcional de desbloqueio. Se o x.com recusar a requisição comum, e só nesse caso, o actor pode buscar a mesma página pelo Web Unlocker da Bright Data — cobrado por requisição, limitado por maxUnlockerRequests (padrão 3). Deixe brightDataApiToken vazio para não usar.

O que este actor aceita ou não como semente, conforme o input schema real:

Descobre porSuportadoObservações
Handle / username✅ SimArray profiles (sem @)
Hashtag⚠️ ParcialSem campo dedicado — passe dentro de searchQuery (ex.: #tech); o modo de busca exige o Bearer Token da API do X
Palavra-chave / busca⚠️ ParcialsearchQuery funciona apenas com Bearer Token da API X v2 (o X removeu a busca anônima); somente tweets recentes
URL de perfil✅ SimstartUrls ou seeds + seedType: "url"; x.com/home, /search e /i/... são rejeitados e nomeados no log
URL de tweet (replies)✅ SimtweetUrls — devolve as respostas daquele post, uma por linha
Subreddit❌ N/ANão é um actor de Reddit

A saída inclui: texto do tweet ✅, visualizações ✅, curtidas ✅, retweets ✅, contagem de respostas ✅, citações ✅, bookmarks ✅, hashtags ✅, mídia ✅, autor (username, displayName, seguidores, verificado) ✅, created_at (ISO 8601) ✅, idioma ✅, is_thread / is_reply / is_retweet ✅.

Não sai na saídaMotivo
TEXTO das respostas/comentários⚠️ modo repliesno modo timeline só a contagem é retornada. Informe tweetUrls para obter o texto de cada resposta — com token da API do X: sem token, o X respondeu 404 à consulta anônima de conversa (medido em 2026-09-23) e o run devolve diagnóstico sem cobrar
thumbnail nos itens de mídia❌cada anexo é { type, url } — a própria URL de mídia do X. Não há thumbnail separado nem variante :small
Visualizações no fallback de syndication⚠️o widget não traz contagem de views, então views vem null nos tweets vindos dele. A página do x.com, usada primeiro, traz views

Entrada

CampoTipoPadrãoDescrição
profilesstring[]—Usernames do Twitter/X (com ou sem @). Sem perfil, busca ou URL de tweet, o run devolve diagnóstico em vez de raspar uma conta padrão
tweetUrlsstring[]—Modo replies: URLs (ou ids) dos posts cujas respostas você quer
includePinnedbooleanfalseMantém o tweet fixado nos resultados (por padrão ele sai, porque costuma ser antigo)
brightDataApiTokenstring—Fallback opcional de desbloqueio, cobrado por requisição. Vazio = nunca usado
maxUnlockerRequestsinteiro3Teto do fallback pago por execução
searchQuerystring—Termo de busca (alternativa aos perfis)
maxTweetsinteger20Máx tweets por perfil/busca (1-100)
includeRepliesbooleanfalseIncluir tweets de resposta
includeRetweetsbooleanfalseIncluir retweets
dateFromstring—Limite inferior inclusivo sobre created_at. YYYY-MM-DD (= 00:00:00.000Z UTC) ou ISO-8601 completo
dateTostring—Limite superior inclusivo sobre created_at. YYYY-MM-DD (= 23:59:59.999Z UTC, dia inteiro incluído) ou ISO-8601 completo

Intervalo de datas (dateFrom / dateTo) - comportamento exato

Os dois campos são opcionais e independentes: deixar um vazio deixa aquele lado sem limite, e deixar os dois vazios desliga o filtro.

  • Onde roda. Com token da API do X os limites vão para a API como start_time/end_time, então você não paga por posts que o filtro descartaria (a API aceita datas a partir de 2010-11-06 na timeline; a busca recente cobre só os últimos 7 dias). As estratégias anônimas não têm parâmetro de data, então ali a comparação é local sobre o created_at — um intervalo estreito ou antigo pode devolver menos itens que maxTweets, ou nenhum.
  • Inclusivo, em UTC. O tweet é mantido quando dateFrom <= created_at <= dateTo. YYYY-MM-DD em dateFrom significa 00:00:00.000Z daquele dia; em dateTo significa 23:59:59.999Z, então dateFrom = dateTo = 2026-01-20 devolve o dia inteiro. Um timestamp ISO-8601 completo é usado exatamente como informado.
  • Cobrança. O filtro roda antes de o tweet ser gravado e antes de o contador do Pay Per Event ser incrementado. Você nunca é cobrado por um tweet descartado pelo filtro de data.
  • Tweets sem data. Alguns caminhos anônimos de fallback devolvem tweet com created_at igual a null. Com qualquer limite ativo, esse tweet é descartado - não dá para verificar se ele pertence ao intervalo, então ele não é devolvido nem cobrado. O log do run informa quantos caíram por esse motivo.
  • Entrada inválida. dateFrom / dateTo ilegível, ou intervalo em que dateFrom é posterior a dateTo, interrompe o run com um item _dataQuality: "diagnostic" explicando o problema, sem cobrar nada. O filtro nunca é ignorado em silêncio.
  • Nada no intervalo. Se tweets foram encontrados mas todos ficaram fora do intervalo, o run termina com sucesso e um item de diagnóstico dizendo quantos foram descartados - também sem cobrança.

Exemplo de Saída

{
"tweet_id": "1891234567890123456",
"url": "https://x.com/elikifreitasdev/status/1891234567890123456",
"text": "🚀 Lançamos a nova versão! Performance 3x melhor #tech #automation",
"author": {
"username": "elikifreitasdev",
"displayName": "Eliki Freitas | Dev",
"followers": 12500,
"verified": false,
"isBlueVerified": true,
"verifiedType": "blue"
},
"created_at": "2026-01-20T14:30:00.000Z",
"views": 45200,
"likes": 892,
"retweets": 156,
"replies": 43,
"quotes": 12,
"bookmarks": 234,
"hashtags": ["tech", "automation"],
"media": [
{
"type": "image",
"url": "https://pbs.twimg.com/media/example.jpg"
}
],
"is_thread": false,
"is_reply": false,
"is_retweet": false,
"is_pinned": false,
"conversation_id": "1891234567890123456",
"in_reply_to_id": null,
"language": "pt"
}

Casos de Uso

  1. Monitoramento de Marca — Acompanhe menções e sentimento sobre sua marca
  2. Análise de Concorrência — Monitore performance de tweets de concorrentes
  3. Pesquisa de Influenciadores — Avalie taxas de engajamento antes de parcerias
  4. Detecção de Tendências — Descubra tópicos virais e hashtags
  5. Estratégia de Conteúdo — Analise quais formatos de tweet geram mais engajamento

FAQ

Precisa de chave de API do Twitter? Recomendado. O X bloqueia acesso anônimo a timelines; informe seu twitterBearerToken (X API v2, plano/quota próprios — https://developer.x.com) para extração confiável. Sem token, o actor tenta estratégias anônimas (sujeitas a bloqueio) e, se nada for extraído, devolve um guia de diagnóstico sem cobrar PPE.

Por que dateFrom / dateTo devolveram menos tweets que maxTweets? Porque o intervalo é aplicado localmente, sobre os tweets que o actor conseguiu buscar (os mais recentes que a estratégia expõe), e não como parâmetro remoto de consulta. Tweets fora do intervalo — e, com um limite ativo, tweets sem created_at legível — são descartados antes de serem gravados, e não são cobrados. Veja "Intervalo de datas — comportamento exato" acima.

Por que veio um tweet antigo / quando views vem null? O widget de syndication devolve os tweets ordenados por engajamento, não por data, e a versão antiga gravava o primeiro que viesse — foi por isso que um post de 2022 saiu com maxTweets: 1. Agora o actor lê primeiro a página do x.com (mais recentes, com visualizações), ordena tudo por created_at e tira o fixado antes do corte. views só vem null nos tweets vindos do fallback de syndication, que não tem esse número — nunca um 0 inventado.

O que significam verified, isBlueVerified e verifiedType? verifiedType é o valor do próprio X: blue, business, government ou none. isBlueVerified só é verdadeiro no selo azul. verified é a flag legada. Qualquer um deles vem null quando a fonte não disse — null é desconhecido, false é a fonte dizendo que não.

Como leio as respostas de um post? Use tweetUrls: ["https://x.com/nasa/status/123..."]. Sem token o actor lê a página do próprio post e devolve as primeiras respostas que o X renderiza ali (3 nas medições, cada uma com autor e selo) — dá para amostrar uma conversa, não para exportá-la inteira. Com token da API do X ele usa a busca recente com o operador conversation_id, que devolve a thread dos últimos 7 dias (mais antigas exigem o acesso full-archive do X).

Pode scraper contas protegidas/privadas? Não. Apenas perfis públicos e tweets públicos são acessíveis.

E sobre limites de requisição? O actor gerencia rate limiting automaticamente com delays e retentativas.

Quantos tweets posso obter por execução? Até 100 tweets por perfil ou busca por execução.


💰 Pricing

This actor uses Pay Per Event (PPE) pricing. The rate depends on your Apify plan tier:

Plan tierPer tweetPer 1,000 tweets
Free$0.02$20.00
Bronze$0.0175$17.50
Silver$0.015$15.00
Gold$0.01$10.00
Platinum$0.0075$7.50
Diamond$0.005$5.00

You are never charged for a run that returned nothing. When X blocks the request and no tweet is extracted, the actor returns a labeled _dataQuality: "diagnostic" setup guide and charges no PPE event. The same holds for the dateFrom / dateTo filter: tweets discarded because they fall outside the requested range — or because they carry no readable date while a bound is set — are dropped before the Pay Per Event counter, so they are never billed.


✅ Available / Disponível — cross-actor upgrades

The items below were PLANNED in earlier versions and are now implemented and live in this actor. They are additive and backward-compatible: when the new input fields are omitted and normalizeOutput is false, the output is byte-for-byte identical to before — paying users are unaffected.

Os itens abaixo eram PLANEJADOS em versões anteriores e agora estão implementados e disponíveis neste actor. São aditivos e retrocompatíveis: quando os novos campos de input são omitidos e normalizeOutput é false, a saída é byte-a-byte idêntica à anterior — usuários pagantes não são afetados.

EN

  • Unified input vocabulary (#1) ✅ — maxResults (alias of maxTweets), seeds + seedType (handle | url | keyword) are accepted as a cross-actor unified seed list. The existing profiles / searchQuery / maxTweets fields keep working exactly as before; the new ones are optional aliases.
  • Normalized _normalized output block (#2) ✅ — set the optional input normalizeOutput: true to attach a cross-platform block to each item: { platform, url, author, text, views, likes, comments, shares, publishedAtISO, lang, hashtags[], engagementVelocity }, alongside the existing raw fields. For Twitter/X, comments maps from replies, shares from retweets + quotes, views from impressions. Default false.
  • ISO date + engagementVelocity (#6) ✅ — inside _normalized, publishedAtISO is the tweet date in ISO-8601 UTC, and engagementVelocity = (likes + comments + shares) / hours_since_published (or null when no date is available).
  • Quality flag _dataQuality (#7) ✅ — successful items carry _dataQuality: "full" (when normalizeOutput is on); the recoverable no-results setup guide carries _dataQuality: "diagnostic" and is not charged via PPE.

PT

  • Vocabulário de input unificado (#1) ✅ — maxResults (alias de maxTweets), seeds + seedType (handle | url | keyword) são aceitos como lista de sementes unificada entre actors. Os campos profiles / searchQuery / maxTweets continuam funcionando exatamente como antes; os novos são aliases opcionais.
  • Bloco de saída normalizado _normalized (#2) ✅ — defina o input opcional normalizeOutput: true para anexar a cada item um bloco cross-plataforma: { platform, url, author, text, views, likes, comments, shares, publishedAtISO, lang, hashtags[], engagementVelocity }, ao lado dos campos crus. No Twitter/X, comments vem de replies, shares de retweets + quotes, views das impressões. Padrão false.
  • Data ISO + engagementVelocity (#6) ✅ — dentro de _normalized, publishedAtISO é a data do tweet em ISO-8601 UTC, e engagementVelocity = (likes + comments + shares) / horas_desde_publicação (ou null quando não há data).
  • Flag de qualidade _dataQuality (#7) ✅ — itens bem-sucedidos carregam _dataQuality: "full" (quando normalizeOutput está ligado); o guia de diagnóstico recuperável (sem resultados) carrega _dataQuality: "diagnostic" e não é cobrado via PPE.

🛣️ Roadmap / Próximas melhorias (planned)

⚠️ The items below are PLANNED, not yet available. They are not current features — do not rely on them yet. Source: internal social-scrapers improvements handoff (2026-06-19).

⚠️ Os itens abaixo são PLANEJADOS, ainda não disponíveis. Não são funcionalidades atuais — não dependa deles ainda. Fonte: handoff interno de melhorias dos scrapers sociais (2026-06-19).

EN

  • (nothing pending here — the structured _blockReason shipped in v1.2: the diagnostic item now carries _blockReason: "USER_FILTER_EMPTY" when your own filters emptied the result.)

PT

  • (nada pendente aqui — o _blockReason estruturado entrou na v1.2: o item de diagnóstico agora traz _blockReason: "USER_FILTER_EMPTY" quando os seus próprios filtros esvaziaram o resultado.)

📝 Changelog

  • v1.3.0 (2026-09-23) — New primary source: the server-rendered x.com page, read without executing any of its JavaScript. It brings what the syndication widget never had — correct dates (a profile stuck in 2023 there returns its 2025 posts here), view counts, the pinned marker, reposts and the first replies of a post. Optional Bright Data Web Unlocker fallback, billed per request and capped per run (maxUnlockerRequests, default 3). The dead guest-token strategies were removed along with the hardcoded web-client bearer.
  • v1.2.0 (2026-09-23) — Fixed: the anonymous source returns tweets ordered by engagement, so maxTweets: 1 could return a post from years ago; the batch is now ordered by date and the pinned tweet is excluded by default (includePinned keeps it). Metrics the source does not expose are null instead of 0/false, and the author now carries isBlueVerified and verifiedType. New replies mode (tweetUrls / conversationIds). On the X API path: date bounds are sent as start_time/end_time, results paginate, media expansions are requested, 429 is retried using x-rate-limit-reset and every request has a timeout. Profile URLs like /home and /i/... are rejected instead of being scraped as a handle, and a run with nothing to scrape returns a diagnostic instead of falling back to a default account.
  • v1.1.0 (2026-08-27) — dateFrom / dateTo are now honored: the range is enforced in memory against each tweet's created_at (UTC, both bounds inclusive) before the tweet is stored and before Pay Per Event, so filtered-out tweets are never charged. Tweets with no readable date are dropped while a bound is set, and an invalid bound stops the run with a diagnostic item instead of being silently ignored.
  • v1.0.0 (2026-02-12) — Initial release: profile scraping, search, full engagement metrics, thread detection, media extraction