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

116

Total users

5

Monthly active users

6 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 filteringdateFrom / 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

Capabilities & Limits

Built here: the anonymous GraphQL path bootstraps itself at runtime. It loads x.com, pulls up to 5 client-web JS bundles from abs.twimg.com and regex-extracts the current queryId for UserByScreenName and UserTweets before calling /i/api/graphql/. Nothing is hardcoded, so the actor survives X rotating its query IDs - and aborts that strategy rather than returning stale data if the bundles change shape.

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
URL❌ NoNo tweet/profile URL input field in the schema
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 textonly the reply count is returned, never the text of individual replies
thumbnail on media itemsa media entry is { type, url } — X's own media URL. No separate thumbnail or :small variant is emitted
Media on the Bearer Token paththe official X API v2 strategy returns media: []. Attachments come only from the anonymous strategies (syndication / GraphQL)

Input

FieldTypeDefaultDescription
profilesstring[]["elikifreitasdev"]Twitter/X usernames (without @)
searchQuerystringSearch term (alternative to profiles)
maxTweetsinteger20Max tweets per profile/search (1-100)
includeRepliesbooleanfalseInclude reply tweets
includeRetweetsbooleanfalseInclude retweets
dateFromstringInclusive lower bound on created_at. YYYY-MM-DD (= 00:00:00.000Z UTC) or full ISO-8601
dateTostringInclusive 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. The bounds are not sent to any remote API or URL parameter. The actor fetches the most recent tweets each strategy exposes and then compares each tweet's created_at locally. A narrow or old range can therefore return fewer items than maxTweets, or nothing at all, even for an active profile.
  • 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
},
"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,
"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.

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 datadateFrom / 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

Capacidades e Limites

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❌ NãoNão há campo de URL de tweet/perfil no schema
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áriossó a contagem de respostas é retornada, nunca o texto de cada resposta
thumbnail nos itens de mídiacada anexo é { type, url } — a própria URL de mídia do X. Não há thumbnail separado nem variante :small
Mídia no caminho com Bearer Tokena estratégia oficial da API X v2 devolve media: []. Os anexos vêm apenas das estratégias anônimas (syndication / GraphQL)

Entrada

CampoTipoPadrãoDescrição
profilesstring[]["elikifreitasdev"]Usernames do Twitter/X (sem @)
searchQuerystringTermo de busca (alternativa aos perfis)
maxTweetsinteger20Máx tweets por perfil/busca (1-100)
includeRepliesbooleanfalseIncluir tweets de resposta
includeRetweetsbooleanfalseIncluir retweets
dateFromstringLimite inferior inclusivo sobre created_at. YYYY-MM-DD (= 00:00:00.000Z UTC) ou ISO-8601 completo
dateTostringLimite 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. Os limites não são enviados a nenhuma API ou parâmetro de URL. O actor busca os tweets mais recentes que cada estratégia expõe e compara o created_at de cada um localmente. Por isso um intervalo estreito ou antigo pode devolver menos itens que maxTweets, ou nenhum, mesmo em um perfil ativo.
  • 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
},
"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,
"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.

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

  • Structured _blockReason code (part of #7) — on a confirmed block, emit a machine-readable reason (403 | 429 | captcha) on the diagnostic item. Not yet implemented to avoid changing the current anti-bot/diagnostic gate; today blocks are surfaced as a labeled _dataQuality: "diagnostic" guide only.

PT

  • Código _blockReason estruturado (parte do #7) — em bloqueio confirmado, emitir um motivo legível por máquina (403 | 429 | captcha) no item de diagnóstico. Ainda não implementado para não alterar o gate anti-bot/diagnóstico atual; hoje os bloqueios são expostos apenas como guia rotulado _dataQuality: "diagnostic".

📝 Changelog

  • 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