Archived run

This is the page as published on 19 September 2026, from the runs of that day, kept for the record. The current version is at /blog/best-twitter-scraper-apify/. Nothing in the text or the data below was edited; the page’s asset links were repointed so it renders from this folder.

Deep comparison · No. 1 · X (Twitter) tweet scrapers · September 2026

Best Twitter (X) scrapers on Apify, tested: six tweet scrapers, the same three jobs, every byte kept

There are hundreds of Twitter (X) scrapers on the Apify Store and no way to tell them apart from their listings. We picked six tweet scrapers, each for a different reason, gave them the same three jobs at the same second, and kept every byte they returned. This page explains how the six were chosen, what we sent, what came back, and where they differ. The raw data is at the bottom. Every run is dated, every run is kept, and the page is re-tested; the numbers here are from the run of 2026-09-19.

6
actors, from 5 publishers
24
runs on 2026-09-19, all SUCCEEDED
955
rows returned
$0.36
charged in total
The short answer
  • Cheapest full-text keyword search: scrape.badger ($0.14 per 1,000 tweets, 18 s) or xquik ($0.16 all-in, 5 s; note that 17 of its 100 results differed from the other five, section 4).
  • Profile timeline with retweets, as X shows it: apidojo Tweet Scraper V2, danek or xquik. Only xquik returned it in date order; sort the other two.
  • Original posts only, no replies: none of the six modes we ran does that now; filter on the reply flag (apidojo, kaitoeasyapi, xquik).
  • Single-tweet lookups: xquik (3–4 s), danek or scrape.badger (4–7 s). Not apidojo Unlimited ($0.05 each), not kaitoeasyapi (15 billed rows each).
  • Long-form posts: any of the four that are not apidojo; both apidojo actors cut at ~280 characters.
  • Most filters: apidojo V2. Smallest records: danek.

Details and every number behind this list are in section 11; how we tested is in section 2. This page was re-tested on 2026-09-19; section 13 lists what changed since the first run on 2026-09-08.

A note on time

Every measured number on this page comes from runs made on 19 September 2026. The first run, on 8 September, is kept in full under archive/2026-09-08/, and section 13 lists what moved between the two. Between the runs the build number advanced by 73 on xquik, by 11 on each apidojo actor, by 3 on kaitoeasyapi, and not at all on danek and scrape.badger. By the time you read this, some of it will be stale and some of it may simply be wrong. These actors change often, and a few of them change daily: in the six weeks before the first test, xquik renamed its listing twice, apidojo renamed Tweet Scraper V2 once, scrape.badger and xquik each changed their pricing once, apidojo’s two actors shipped a new build on every one of the 18 days we looked, xquik shipped 12, kaitoeasyapi 5, scrape.badger 2, and danek did not change once. We record every listing in the store every day. If a number here matters to you, open the actor’s page on this site and follow it; you will see the change the day it happens. The six: apidojo / Tweet Scraper V2, kaitoeasyapi / Tweet Scraper (“cheapest”), apidojo / Twitter Scraper Unlimited, xquik / X Tweet Scraper, danek / Twitter Scraper, scrape.badger / X Tweet Scraper.

1. How we chose the six tweet scrapers

The census behind this site tracks every X (Twitter) actor on the Apify Store; 53 of them have at least 30 monthly users. We removed everything that is not a tweet scraper: profile and user scrapers, follower scrapers, trend scrapers, list scrapers, reply-only scrapers, a video downloader. Fifteen remained.

Ranking the fifteen by monthly users and taking the top six would put four actors from two publishers on the page and tell you little. We took one actor per reason instead. The six were chosen on 8 September from that day’s census and were not re-chosen for the re-run; the table below is the census as it stood then.

Actor and why it is inUsers, 30 d6-week changeFirst publishedSuccess, 30 dRating / reviewsListed price
apidojo / Tweet Scraper V2 (apidojo/tweet-scraper)Widest user base and the oldest listing7,459+6%2023-11-2495.4%3.94 / 195$0.00040
kaitoeasyapi / Tweet Scraper (“cheapest”) (kaitoeasyapi/twitter-x-data-tweet-scraper-pay-per-result-cheapest)Second-largest user base; “cheapest” is in its slug4,004+6%2024-10-1499.6%4.22 / 83$0.00025
apidojo / Twitter Scraper Unlimited (apidojo/twitter-scraper-lite)Highest rating among the high-volume actors1,957-8%2024-05-0999.8%4.76 / 101$0.00040
xquik / X Tweet Scraper (xquik/x-tweet-scraper)Fastest-growing and youngest of the fifteen; lowest listed price1,006+39%2026-03-2899.7%4.55 / 14$0.00015
danek / Twitter Scraper (danek/twitter-scraper)Most runs of any actor in the set, with a 100.0% 30-day success rate576-13%2024-03-28100.0%4.43 / 20$0.00030
scrape.badger / X Tweet Scraper (scrape.badger/twitter-tweets-scraper)xquik’s price twin: same listed price, and since 10 August the same title401-18%2025-05-1799.6%3.30 / 17$0.00015

Census snapshot of 2026-09-08. “6-week change” compares monthly users on 28 July and 8 September. “First published” is the actor’s creation date from the Apify API. Success is the store’s public 30-day run statistic. Listed price is the primary pay-per-event price shown on the store listing.

Two of the six share a name

Since 10 August the listings of xquik/x-tweet-scraper and scrape.badger/twitter-tweets-scraper carry the same title, character for character: X Tweet Scraper | $0.15/1K Tweets | Pay-Per-Result. scrape.badger’s is the older listing (May 2025 against March 2026). Our title history starts on 24 July, so we cannot say which wording came first. On 24 July xquik’s title still read From $0.15/1K Tweets | Pay-Per Result; it changed on 31 July and again on 10 August and arrived at the identical string. We report this because a buyer scanning the store sees two identical names and has no way to tell them apart. The rest of this page is one way.

Who we left out, and why

  • api-ninja/x-twitter-advanced-search — 398 users, rated 4.86 from 45 reviews, but $0.015 per tweet: 100× the cheapest actor here. It is a search-only actor and deserves its own test at its own price point.
  • scraper_one/x-profile-posts-scraper + x-posts-search — 417 and 313 users. The publisher splits profile posts and search into two actors; you would need both for our three jobs.
  • altimis/scweet — 192 users. It entered our candidate list only on the latest snapshot, so we have no six-week history for it.
  • automation-lab/twitter-scraper — 145 users, 92.6% success, down from 194 users six weeks ago.
  • maximedupre/twitter-scraper — 83 users; its 30-day success rate swung from 50% to 94% inside the six-week window.
  • scrapesmith, igolaizola, fastcrawler — 69, 50 and 30 users; the last two run at 87% and 90% success.

2. What we asked each scraper to do

Three jobs, the same for everyone.

  1. Keyword search. The phrase web scraping, newest first, 100 tweets.
  2. Profile timeline. The 50 newest posts by @apify.
  3. Single-tweet lookup. Two tweets by id: a post with an image and some engagement, and a long-form post of 1,334 characters.

Rules

  • We set only the query, the sort (Latest), the item cap and the handle or id. Everything else stayed at the actor’s documented default or console prefill. Where an actor’s console prefills an output shape (xquik: rich, camelCase, flat), we kept the prefill.
  • Two actors have no profile mode. kaitoeasyapi and scrape.badger ran the profile job as a search for from:apify, which is what their READMEs suggest. Section 5 shows what that does to the result.
  • All 24 runs were started inside the same second (12:56:49 UTC, 19 September 2026) from one Apify account on the Starter plan, through the API, with each actor’s default memory. On the first run (8 September) the twelve search and profile runs started at 22:13:48 UTC and the lookups about ten minutes later.
  • One run per job per actor. No retries. We kept whatever came back.
  • Costs are read from the run object after charges settled. Durations are the platform’s own startedAt to finishedAt, so they include the actor’s cold start.

What we expected back

A tweet record with, at minimum: Tweet id, Tweet URL, Text, Created at, Language, Author handle, Author name, Author id, Author followers, Likes, Retweets, Replies, Quotes, Views, Bookmarks, Reply flag, Retweet flag, Quote flag, Conversation id, Media, Links, Hashtags, Long-form flag, Source app. Section 7 shows who returns which.

Exact inputs, keyword search (6)
apidojo / Tweet Scraper V2
{
 "searchTerms": [
  "web scraping"
 ],
 "sort": "Latest",
 "maxItems": 100
}
kaitoeasyapi / Tweet Scraper (“cheapest”)
{
 "twitterContent": "web scraping",
 "queryType": "Latest",
 "maxItems": 100
}
apidojo / Twitter Scraper Unlimited
{
 "searchTerms": [
  "web scraping"
 ],
 "sort": "Latest",
 "maxItems": 100
}
xquik / X Tweet Scraper
{
 "mode": "search",
 "searchTerms": [
  "web scraping"
 ],
 "queryType": "Latest",
 "maxItems": 100,
 "outputVariant": "rich",
 "fieldStyle": "camelCase",
 "outputPreset": "flat"
}
danek / Twitter Scraper
{
 "query": "web scraping",
 "search_type": "Latest",
 "max_posts": 100
}
scrape.badger / X Tweet Scraper
{
 "mode": "Advanced Search",
 "query": "web scraping",
 "query_type": "Latest",
 "max_results": 100
}
Exact inputs, profile timeline (6)
apidojo / Tweet Scraper V2
{
 "twitterHandles": [
  "apify"
 ],
 "maxItems": 50
}
kaitoeasyapi / Tweet Scraper (“cheapest”)
{
 "twitterContent": "from:apify",
 "queryType": "Latest",
 "maxItems": 50
}
apidojo / Twitter Scraper Unlimited
{
 "twitterHandles": [
  "apify"
 ],
 "maxItems": 50
}
xquik / X Tweet Scraper
{
 "mode": "profileTweets",
 "twitterHandles": [
  "apify"
 ],
 "maxItems": 50,
 "outputVariant": "rich",
 "fieldStyle": "camelCase",
 "outputPreset": "flat"
}
danek / Twitter Scraper
{
 "username": "apify",
 "max_posts": 50
}
scrape.badger / X Tweet Scraper
{
 "mode": "Advanced Search",
 "query": "from:apify",
 "query_type": "Latest",
 "max_results": 50
}
Exact inputs, single-tweet lookups (12)
apidojo / Tweet Scraper V2
{
 "startUrls": [
  "https://x.com/apify/status/2095479050911309827"
 ],
 "maxItems": 1
}
kaitoeasyapi / Tweet Scraper (“cheapest”)
{
 "tweetIDs": [
  "2095479050911309827"
 ],
 "maxItems": 1
}
apidojo / Twitter Scraper Unlimited
{
 "startUrls": [
  "https://x.com/apify/status/2095479050911309827"
 ],
 "maxItems": 1
}
xquik / X Tweet Scraper
{
 "mode": "tweet",
 "startUrls": [
  "https://x.com/apify/status/2095479050911309827"
 ],
 "maxItems": 1,
 "outputVariant": "rich",
 "fieldStyle": "camelCase",
 "outputPreset": "flat"
}
danek / Twitter Scraper
{
 "lookup_post_ids": [
  "2095479050911309827"
 ],
 "max_posts": 1
}
scrape.badger / X Tweet Scraper
{
 "mode": "Get Tweet by ID",
 "id": "2095479050911309827",
 "max_results": 1
}
apidojo / Tweet Scraper V2
{
 "startUrls": [
  "https://x.com/i/status/2096838373524812149"
 ],
 "maxItems": 1
}
kaitoeasyapi / Tweet Scraper (“cheapest”)
{
 "tweetIDs": [
  "2096838373524812149"
 ],
 "maxItems": 1
}
apidojo / Twitter Scraper Unlimited
{
 "startUrls": [
  "https://x.com/i/status/2096838373524812149"
 ],
 "maxItems": 1
}
xquik / X Tweet Scraper
{
 "mode": "tweet",
 "startUrls": [
  "https://x.com/i/status/2096838373524812149"
 ],
 "maxItems": 1,
 "outputVariant": "rich",
 "fieldStyle": "camelCase",
 "outputPreset": "flat"
}
danek / Twitter Scraper
{
 "lookup_post_ids": [
  "2096838373524812149"
 ],
 "max_posts": 1
}
scrape.badger / X Tweet Scraper
{
 "mode": "Get Tweet by ID",
 "id": "2096838373524812149",
 "max_results": 1
}

3. Results at a glance

Every run finished with status SUCCEEDED. Total charged for all 24 runs: $0.36.

Keyword search: 100 tweets for “web scraping”

ActorRowsTimeChargedPer 1,000 rowsEvent price appliedPlatform usageBytes / rowFields / row
apidojo / Tweet Scraper V210037.4 s$0.0400$0.400$0.00040publisher pays4,58228.5
kaitoeasyapi / Tweet Scraper (“cheapest”)10020.1 s$0.0220$0.220$0.00022publisher pays5,73030.1
apidojo / Twitter Scraper Unlimited10040.0 s$0.0400$0.400$0.00040publisher pays5,34428.5
xquik / X Tweet Scraper1005.3 s$0.0158$0.158$0.00015user pays7,74760.0
danek / Twitter Scraper10020.4 s$0.0280$0.280$0.00028publisher pays2,00920.5
scrape.badger / X Tweet Scraper10018.1 s$0.0140$0.140$0.00014publisher pays2,17643.2

Profile timeline: 50 newest posts by @apify

ActorRowsTimeChargedPer 1,000 rowsEvent price appliedPlatform usageBytes / rowFields / row
apidojo / Tweet Scraper V25032.9 s$0.0200$0.400$0.00040publisher pays6,17229.0
kaitoeasyapi / Tweet Scraper (“cheapest”)6016.5 s$0.0132$0.220$0.00022publisher pays6,59530.2
apidojo / Twitter Scraper Unlimited5030.4 s$0.0220$0.440$0.00040publisher pays6,18429.0
xquik / X Tweet Scraper506.0 s$0.0080$0.161$0.00015user pays9,42762.4
danek / Twitter Scraper559.4 s$0.0154$0.280$0.00028publisher pays1,59416.3
scrape.badger / X Tweet Scraper5016.6 s$0.0070$0.140$0.00014publisher pays1,97743.8

Single tweet, the one with an image

ActorRowsTimeChargedEvent price appliedPlatform usageBytes / rowFields / row
apidojo / Tweet Scraper V212.9 s$0.0004$0.00040publisher pays5,78328
kaitoeasyapi / Tweet Scraper (“cheapest”)15 (14 filler)15.9 s$0.0033$0.00022publisher pays1,1524.8
apidojo / Twitter Scraper Unlimited151.2 s$0.0504$0.00040publisher pays5,78328
xquik / X Tweet Scraper13.7 s$0.0004$0.00015user pays6,94462
danek / Twitter Scraper14.0 s$0.0003$0.00028publisher pays3,06423
scrape.badger / X Tweet Scraper16.5 s$0.0001$0.00014publisher pays2,50643

Single tweet, the long-form one

ActorRowsTimeChargedEvent price appliedPlatform usageBytes / rowFields / row
apidojo / Tweet Scraper V2151.9 s$0.0004$0.00040publisher pays13,61928
kaitoeasyapi / Tweet Scraper (“cheapest”)15 (14 filler)16.1 s$0.0033$0.00022publisher pays1,3164.8
apidojo / Twitter Scraper Unlimited130.3 s$0.0504$0.00040publisher pays13,61928
xquik / X Tweet Scraper13.1 s$0.0003$0.00015user pays17,00761
danek / Twitter Scraper15.8 s$0.0003$0.00028publisher pays3,30725
scrape.badger / X Tweet Scraper16.4 s$0.0001$0.00014publisher pays3,23745

“Charged per row” is the per-event price the platform applied to our run, which is not always the listed price (section 9). “Platform usage” says who pays compute and storage for the run: for five actors the publisher absorbs it, for xquik the user pays it on top of the per-tweet price. “Fields / row” is the average number of top-level keys per record.

4. Scraping tweets by keyword: the same 100 tweets for five of the six, different text and different bills

Five actors returned the same 100 tweets. apidojo V2, apidojo Unlimited, kaitoeasyapi, danek and scrape.badger agree on every id, and the newest tweet is the same across all six (12:53:34 UTC, three minutes before the runs). Whatever these five do behind the scenes, they read the same source at the same moment. xquik did not: it shares 83 ids with the other five, returned 17 that none of them did, and left out 17 that all of them had. The union of the six result sets is 117 ids and 83 appear in all six. Of the 17 only xquik returned, 4 contain the phrase “web scraping”; of the 17 it left out, 9 do. On the first run, eleven days earlier, xquik agreed with the rest (99 of 101 ids in all six) and its search took 34 seconds; this time it took 5, and it did not read the same result set as the other five. View counts are identical for 98 of 100 shared tweets.

Where the five differ is the text. X allows posts far beyond 280 characters (long-form, or “note” tweets). 28 of the 100 tweets the five agreeing actors returned are long-form. kaitoeasyapi, danek and scrape.badger return 27 of them whole, xquik 34 of the 35 it saw. apidojo’s two actors return the first ~280 characters and stop, on 26 of the 28.

ActorLong-form posts returned in fullLongest text, charsTimePer 1,000
apidojo / Tweet Scraper V22 / 2831137.4 s$0.400
kaitoeasyapi / Tweet Scraper (“cheapest”)27 / 286,13420.1 s$0.220
apidojo / Twitter Scraper Unlimited2 / 2831140.0 s$0.400
xquik / X Tweet Scraper34 / 354,3265.3 s$0.158
danek / Twitter Scraper27 / 286,13420.4 s$0.280
scrape.badger / X Tweet Scraper27 / 286,13418.1 s$0.140

“In full” means the text is at least 95% as long as the longest version any actor returned for the same id. The long-form set is the ids xquik flags as isNoteTweet; the other actors do not flag them, but four of them return the same 1,000–6,000-character bodies. The one long-form post that no actor but apidojo returns “in full” is a 283-character post that apidojo returns with an expanded link, at 307 characters; the others’ 283 fall under the 95% rule, not under a cut. xquik sees 35 because 7 of its 17 extra tweets are long-form.

Speed ran from 5 s (xquik) to 40 s (apidojo Unlimited) for 100 tweets. Price per 1,000 ran from $0.14 (scrape.badger) to $0.40 (both apidojo actors). Records ran from 2.0 KB (danek) to 7.7 KB (xquik) each; the difference is nested author objects, entity lists and, in xquik’s case, about thirty flattened author* fields per row.

5. Profile timeline: “the 50 newest posts by @apify” still means different things

This is the job where the six stop agreeing. The union of the six outputs is 81 distinct posts; 31 of them appear in all six, and 8 appear in exactly one.

ActorRowsRetweetsRepliesNewest post (UTC)Oldest postSorted newest-firstOverlap with apidojo V2Time
apidojo / Tweet Scraper V25011 (10 truncated in the row, original attached for 11)142026-09-19 08:072026-08-1263%5032.9 s
kaitoeasyapi / Tweet Scraper (“cheapest”)600292026-09-19 08:072026-09-05100%3216.5 s
apidojo / Twitter Scraper Unlimited5011 (10 truncated in the row, original attached for 11)142026-09-19 08:072026-08-1263%5030.4 s
xquik / X Tweet Scraper5010 (0 truncated in the row, original attached for 10)162026-09-19 08:072026-09-09100%476.0 s
danek / Twitter Scraper55 (1 dup)11 (10 truncated in the row, original attached for 11)8*2026-09-19 08:072026-09-0872%499.4 s
scrape.badger / X Tweet Scraper500282026-09-19 08:072026-09-09100%3116.6 s

Retweets are rows whose text starts with “RT @”. Replies use the actor’s own flag; * marks actors without a reply flag, where we counted texts that start with “@”. “Sorted newest-first” is the share of consecutive rows in descending date order. Overlap is the number of ids in common with apidojo/tweet-scraper’s 50.

  • apidojo V2 and Unlimited return the account’s timeline as X shows it: original posts, 11 retweets and 14 replies, with the pinned post first and flagged by both. The rows are not in date order: the pinned post, then a block that descends from 18 September to 15 September, then a jump back to 19 September and a second descent, and so on, which looks like several fetches concatenated. Sort before you use it. The retweet rows carry a cut text (“RT @…”, 10 of 11 end in “…”) with the original post attached as an object.
  • xquik in profileTweets mode now returns the timeline too: 47 of its 50 are in apidojo V2’s 50, with 10 retweets and 16 replies, every one flagged (isRetweet, isReply), the retweeted text in full in the row and the original attached as retweetedTweet, in strict date order, in 6 seconds. (The same input returned no replies on the first run; section 13.)
  • danek returns nearly the same set as apidojo (49 of 50 in common), attaches the original post to every retweet, and finished in 9 seconds. It returned 55 rows for a cap of 50, one of them twice, and billed 55.
  • kaitoeasyapi and scrape.badger have no profile mode, so from:apify is a search. Search excludes retweets and includes every reply, so their “timeline” is 29 and 28 replies out of 60 and 50 rows, reaches back only to 5 and 9 September, and has 32 and 31 posts in common with apidojo V2. kaitoeasyapi again returned 60 rows for a cap of 50 and billed 60; its schema warns that “the final response may slightly exceed the specified max_items”.

None of these is wrong. They are different definitions of a profile pull. If you need what a visitor sees on the profile page, use a timeline actor; xquik gives it to you sorted and labelled, apidojo V2 and danek need a sort. If you need only original posts, no mode we ran does that now: filter on the reply and retweet flags. If you need replies, the two search-based actors give you mostly that.

6. Single-tweet lookup: one id, six answers

ActorImage post: text, charsLong-form post: text, charsLikes / views (image post)Time (image / long-form)Charged (image / long-form)
apidojo / Tweet Scraper V2238277312 / 53,5622.9 s / 51.9 s$0.0004 / $0.0004
kaitoeasyapi / Tweet Scraper (“cheapest”)238 +14 filler rows1,334312 / 53,56215.9 s / 16.1 s$0.0033 / $0.0033
apidojo / Twitter Scraper Unlimited238277312 / 53,56251.2 s / 30.3 s$0.0504 / $0.0504
xquik / X Tweet Scraper2381,334312 / 53,5623.7 s / 3.1 s$0.0004 / $0.0003
danek / Twitter Scraper2381,334312 / 53,5624.0 s / 5.8 s$0.0003 / $0.0003
scrape.badger / X Tweet Scraper2381,334312 / 53,5626.5 s / 6.4 s$0.0001 / $0.0001
  • The long-form post is 1,334 characters. Four actors returned all of it. apidojo V2 and Unlimited returned 277 characters, the same cut as in the search job. This is a direct lookup of one id, so it is not a paging artefact; the actors do not read the long-form body.
  • kaitoeasyapi returned 15 rows for one tweet and billed 15. One row is the tweet. The other fourteen are of type mock_tweet with id −1 and this text: From KaitoEasyAPI, a reminder: Our API pricing is based on the volume of data returned. However, to ensure we can cover our costs on the Apify platform, we have a minimum charge of $X per API call, even if the response contains no results. Thus, we returned N pieces of mock data. We will monitor and adjust the size of N based on the infrastructure costs incurred by Apify. The publisher states the policy in the row itself; the store listing says $0.00025 per tweet and the input schema says nothing about a minimum. On a one-tweet lookup the effective price was $0.0033, fifteen times the per-tweet price, and any pipeline that counts rows will count fifteen tweets.
  • apidojo Unlimited charged $0.0504 for one tweet. Its pricing has three event types: $0.016 per search or profile query (“includes first ~40 results”), $0.0004 per row above that, and $0.05 per single-tweet URL. The search and profile jobs cost the same as V2 because the query fee replaced the first 40 rows; the lookup did not. Both are in the run’s chargedEventCounts, and in the raw data below.
  • Timings on a single lookup spread from 3 to 52 seconds. apidojo V2 answered the image post in 3 s and the long-form post in 52; xquik took 4 and 3; danek 4 and 6; scrape.badger 6 and 6; kaitoeasyapi 16 and 16; apidojo Unlimited 51 and 30. On the first run xquik answered both in 2 s and apidojo V2 took 16 and 4. One run per job, so treat a single lookup time as a sample, not a rate.
  • Metrics agree. All six report 312 likes and 53,562 views on the image post.

7. Field coverage

Read from the 100 search rows of each actor, after mapping every actor’s names onto one list. “✓ when set” means the key is present only when it has a value (an empty media list is omitted rather than written as []). “—” means the actor never returns the field under any name.

Fieldapidojo
Tweet Scraper V2
kaitoeasyapi
Tweet Scraper (“cheapest”)
apidojo
Twitter Scraper Unlimited
xquik
X Tweet Scraper
danek
Twitter Scraper
scrape.badger
X Tweet Scraper
Tweet id✓✓✓✓✓✓
Tweet URL✓✓✓✓——
Text✓✓✓✓✓✓
Created at✓✓✓✓✓✓
Language✓✓✓✓✓✓
Author handle✓✓✓✓✓✓
Author name✓✓✓✓✓✓
Author id✓✓✓✓✓✓
Author followers✓✓✓✓✓✓
Likes✓✓✓✓✓✓
Retweets✓✓✓✓✓✓
Replies✓✓✓✓✓✓
Quotes✓✓✓✓✓✓
Views✓✓✓✓✓✓
Bookmarks✓✓✓✓✓✓
Reply flag✓✓✓✓✓ when set✓ when set
Retweet flag✓✓✓✓—✓
Quote flag✓✓✓✓✓ when set✓
Conversation id✓✓✓✓✓✓
Media✓✓ when set✓✓✓✓
Links✓ when set✓ when set✓ when set✓✓✓
Hashtags✓ when set✓ when set✓ when set✓✓✓
Long-form flag———✓——
Source app✓ when set—✓✓✓✓
  • Tweet URL is missing from danek and scrape.badger. Both give you the id and the handle, so you build it yourself.
  • Retweet flag is missing from danek in this output; the nested retweeted_tweet object tells you anyway. xquik carries an explicit isRetweet.
  • Long-form flag exists only in xquik (isNoteTweet).
  • Source app is missing from kaitoeasyapi (the key exists, empty in every row).
  • Naming. apidojo, kaitoeasyapi and xquik use camelCase; danek and scrape.badger use snake_case. danek returns three different record shapes for the three jobs (user_info on search, author on profile, likes instead of favorites on lookup) and returns views as a string. kaitoeasyapi’s record is apidojo’s record with four fields renamed, which makes the two nearly interchangeable.

8. Filters and the shape of the input

Read from each actor’s published input schema on 8 September 2026 and read again on 19 September: the field counts and the required fields did not change (the schemas as read on 19 September are in the raw data). We did not exercise every filter; this is what the schema offers.

ActorInput fieldsRequiredTargets / modesDate rangeLanguageEngagement filtersMedia filtersSortSeveral queries per run
apidojo / Tweet Scraper V226noneURLs, search terms, handles, conversation ids in one runstart / end date fieldsyesmin retweets / likes / repliesimage, video, quote onlyTop, Latest, bothyes
kaitoeasyapi / Tweet Scraper (“cheapest”)48maxItemstweet ids, one query string, or a list of search termssince_time / until_time as unix seconds, or since_id / max_idyesmin and max retweets / likes / replies12 filter:* switches (images, videos, spaces, links, news…)Latest, Top, Photos, Videosyes
apidojo / Twitter Scraper Unlimited8nonesearch terms, handles, URLsstart / end date fieldsnononoTop, Latest, bothyes
xquik / X Tweet Scraper100none12 modes (search, profile tweets/replies/media/likes, list, article, replies, quotes…) or auto-routesince / until (hidden fields), plus the operator setyesmin and max retweets / likes / repliesthe same 12 filter:* switches as kaitoLatest, Top, bothyes
danek / Twitter Scraper7max_postsone username, or one query, or post idsno field; put operators in the queryno fieldno fieldsearch_type MediaTop, Latest, Media, People, Listsno: one target per run
scrape.badger / X Tweet Scraper6mode8 modes, chosen from a dropdown whose values are UI labels (Get a Few Tweets, Advanced Search)no field; put operators in the queryno fieldno fieldquery_type MediaTop, Latest, Mediano: one query per run
  • apidojo / Tweet Scraper V2. Clean field names; a custom JavaScript map function for reshaping output.
  • kaitoeasyapi / Tweet Scraper (“cheapest”). Every X search operator is its own field, named after the operator (filter:blue_verified, -min_faves). No profile mode: use from:.
  • apidojo / Twitter Scraper Unlimited. The small sibling of Tweet Scraper V2: same output, a fraction of the filters.
  • xquik / X Tweet Scraper. Roughly a third of the 100 fields are aliases: the item cap alone can be spelled maxItems, maxResults, max_results, resultsLimit, resultsCount, numberOfTweets, maxPosts or max_posts. Output shape is configurable (legacy / rich / raw; camelCase / snake_case; nested / flat).
  • danek / Twitter Scraper. Seven flat fields. Which ones apply depends on what you fill in; the schema does not say.
  • scrape.badger / X Tweet Scraper. No profile mode: use from:. The mode string must match the label exactly.

9. Cost: what each Twitter scraper actually charged

ActorListed per tweetApplied to our runPricing modelOur total, 4 runs
apidojo / Tweet Scraper V2$0.00040$0.00040flat per row$0.0608
kaitoeasyapi / Tweet Scraper (“cheapest”)$0.00025$0.00022flat per row, padded on empty or tiny results$0.0418
apidojo / Twitter Scraper Unlimited$0.00040$0.00040per query + per row tiers + per single-tweet URL$0.1628
xquik / X Tweet Scraper$0.00015$0.00015flat per row + platform usage billed to you$0.0245
danek / Twitter Scraper$0.00030$0.00028flat per row$0.0440
scrape.badger / X Tweet Scraper$0.00015$0.00014flat per row$0.0213
  • The listed price is not always the applied price. Apify lets publishers set different per-event prices for the FREE, BRONZE, SILVER and GOLD account tiers; the store shows one number. Our Starter-plan account was charged $0.00022 by kaitoeasyapi (listed $0.00025), $0.00028 by danek (listed $0.0003) and $0.00014 by scrape.badger (listed $0.00015). The other three charged the listed price.
  • xquik is the only actor here where platform usage is billed to the user. On the search run that was $0.0008 of compute, storage and transfer on top of $0.015 in per-tweet events: about 5% (9% on the first run, when the same job took 34 seconds instead of 5). The store shows this as a small line under the price; the run object shows it as platformUsageBillingModel: USER. On a 256 MB run it is minor. On heavier settings it would not be.
  • apidojo Unlimited’s per-query fee makes small pulls expensive and large pulls the same price as V2. Its single-tweet price is 125× the per-row price.
  • kaitoeasyapi’s padding turns “no or few results” into a paid minimum, and the padding is billed as rows.

10. What we liked and what we did not

11. Best Twitter (X) scraper on Apify, by use case

If you need
  • Keyword search at volume, full text, lowest cost: scrape.badger ($0.14 per 1,000, 18 s) or xquik ($0.16 all-in, 5 s). Both return long-form posts whole. Know that xquik’s 100 and the other five’s 100 differed on 17 ids in this run; if you need what X’s “Latest” tab shows, the five agree with each other and xquik did not.
  • A profile timeline as X shows it, retweets included: xquik, apidojo V2 or danek. xquik returns it in date order with retweets and replies flagged and the original post attached; apidojo V2 and danek need a sort. danek is cheaper and attaches the original post too; apidojo V2 has the better filter set.
  • Only an account’s original posts, no replies: no mode we ran does that now. Take a timeline actor and drop rows where the reply flag is set.
  • Single-tweet lookups: xquik, danek or scrape.badger (3–7 s). Not apidojo Unlimited ($0.05 each) and not kaitoeasyapi (15 billed rows each).
  • Long-form posts: any of the four that are not apidojo. Both apidojo actors cut at ~280 characters on every job we ran, on both dates.
  • The most filters, cleanly named: apidojo V2.
  • The smallest records: danek, at a quarter of xquik’s size, if you can live with three schemas.

There is no single winner, and we did not expect one. The six were chosen to be different, and they are. The one result we did not expect on the first run still stands on the second: the oldest and most-used actor in the category, with 98,000 lifetime users, is the one that loses most of a long-form post, on a direct lookup as well as in search.

Disclosure

apifystats publishes no X actor and has no commercial relationship with any of the six publishers. Before the first run, none of them was contacted and none was told they were being compared. Since 9 September the plan, the inputs and the scripts have been public on this page, so any publisher can read them and change their actor with the test in mind; a re-run measures whatever is live on the day, and this one did. We paid list price from our own Apify account both times. This is the first post in a series; the method will change as we learn, and we will say so when it does.

12. Raw data

Everything the actors returned, untouched, plus the run objects Apify keeps for each run (timing, memory, charged events, applied pricing) and the exact input we sent. One directory per actor. If you find a mistake in our reading of it, tell us and we will correct the page.

Method notes and limits

  • One run per job per actor, at one moment, with one query and one handle, on each of two dates eleven days apart. Between the dates the timings moved on every actor, the text, price and schema findings held for five of the six, and one actor changed its search result set and the meaning of its profile mode (section 13). A timing on this page is one sample.
  • Timings include cold start and are measured by the platform, not by us. Memory was each actor’s default (128–512 MB).
  • Prices applied to our account reflect its plan tier. Yours may differ; the run object will tell you.
  • We did not test proxies, rate limits, very large pulls, or any filter beyond sort and cap.
  • Success rates and user counts in section 1 are the store’s public statistics as captured by our daily census; we did not audit them. Definitions are on the methodology page.

13. What changed between 8 and 19 September

Same six actors, same plan, same inputs, same scripts, same account, eleven days apart. The first run is kept in full under archive/2026-09-08/. The table is computed from the two data.json files; the list below it is our reading.

ActorBuildSearch timeProfile timeLookups (image / long-form)Profile rowsCharged, 4 runs
apidojo / Tweet Scraper V20.0.1511 → 0.0.152224.7 s → 37.4 s24.3 s → 32.9 s16 / 4 s → 3 / 52 s50 → 50$0.0608 → $0.0608
kaitoeasyapi / Tweet Scraper (“cheapest”)1.0.511 → 1.0.51418.4 s → 20.1 s15.9 s → 16.5 s11 / 14 s → 16 / 16 s60 → 60$0.0418 → $0.0418
apidojo / Twitter Scraper Unlimited0.0.991 → 0.0.100224.4 s → 40.0 s23.6 s → 30.4 s14 / 4 s → 51 / 30 s50 → 50$0.1644 → $0.1628
xquik / X Tweet Scraper1.12.144 → 1.12.21734.4 s → 5.3 s7.9 s → 6.0 s2 / 2 s → 4 / 3 s50 → 50$0.0250 → $0.0245
danek / Twitter Scraper1.4.28 → 1.4.2818.3 s → 20.4 s9.0 s → 9.4 s4 / 3 s → 4 / 6 s50 → 55$0.0426 → $0.0440
scrape.badger / X Tweet Scraper1.4.20 → 1.4.2015.0 s → 18.1 s8.4 s → 16.6 s5 / 6 s → 6 / 6 s50 → 50$0.0213 → $0.0213

Left of each arrow: 8 September. Right: 19 September. Build is the actor build number the platform recorded on the search run.

  • xquik’s build number advanced by 73 (1.12.144 → 1.12.217), and two things we measure changed. Its search went from the slowest of the six (34 s) to the fastest (5 s), and stopped returning the same 100 tweets as the other five: 83 shared, 17 only it returned, 17 it left out (section 4). Its profileTweets mode went from “original posts and retweets, no replies, retweets as unflagged stubs” to the timeline as X shows it: 47 of 50 in common with apidojo V2, retweets and replies flagged, the retweeted text in full, the original attached, in date order (section 5). “Retweets are not flagged and the original post is not included” was one of our four “did not like” items for xquik on 8 September; it is gone, and so is “slowest on the search job”. Platform usage billed to the user fell from 9% to 5% of the search bill because the run is shorter.
  • apidojo’s build numbers advanced by 11 on each actor. Search got slower (25 → 37 s and 24 → 40 s). Twitter Scraper Unlimited returned and flagged the pinned post this time, which it had dropped on 8 September. The long-form cut did not move: 2 of 28 whole in search, 277 of 1,334 characters on the direct lookup, on both dates.
  • kaitoeasyapi (build number +3): the same 14 mock_tweet filler rows on a one-tweet lookup, 60 rows for a cap of 50, billed 60. Unchanged.
  • danek (no new build): 55 rows for a cap of 50 where it had returned 50 with two duplicates; billed 55. Otherwise the same.
  • scrape.badger (no new build): the same results, 3 seconds slower on search (15 → 18 s) and no longer the fastest.
  • Retrieval agreement. Search: 99 of 101 ids in all six on 8 September; 83 of 117 on 19 September, all of the difference from xquik. Profile: 14 of 101 in all six, then 31 of 81; the six agree more because xquik’s mode now returns the timeline.
  • What did not change: the cheapest and most expensive per 1,000 (scrape.badger $0.14, apidojo $0.40), the applied-versus-listed prices, apidojo Unlimited’s $0.05 single-tweet fee, the field coverage table except xquik’s new retweet flag, and the input schemas.
  • Method. One change to our scripts: mapping.py now reads xquik’s isRetweet flag, which did not exist on 8 September. Everything else ran unchanged; the copy under raw/tools/ is what ran.

14. Questions people ask about scraping Twitter (X)

Short answers from this test, for the questions that come up most in search.

Is it legal to scrape Twitter (X)?

We are not lawyers and this is not legal advice. The facts: every tweet in this test is public, and none of the six scrapers asked for an X login. X’s Terms of Service prohibit scraping without permission, which is a contract between X and its account holders. In the United States, hiQ Labs v. LinkedIn (2022) held that scraping publicly available data does not violate the Computer Fraud and Abuse Act. Tweets contain personal data, so storing or processing them can fall under GDPR or CCPA regardless of how they were collected. What you may do with the data depends on where you are and what you do with it; ask counsel for your case.

Can I scrape tweets without the X API?

Yes. That is what all six actors here do: none asked for an API key, a login or a cookie in the jobs we ran. The trade is that there is no contract with X about rate limits or continuity; the store’s public 30-day success rates for the six ran from 95.4% to 100%.

How does this compare with X API pricing?

X’s own API is priced per usage: you buy credits and each request deducts from them (docs.x.com, September 2026); the current per-request rates are on X’s pricing page. At the per-tweet prices we were charged, 10,000 tweets cost between $1.40 (scrape.badger) and $4.00 (apidojo), with no credit purchase and no subscription. The X API returns the platform’s own data under its own terms; the scrapers return what a logged-out visitor sees.

Is there a free Twitter scraper on Apify?

Apify’s free plan includes $5 of usage credit every month, and all six scrapers run on it. At the prices we were charged, $5 buys between 12,500 and 35,000 tweets a month. None of the six is free beyond that credit; a “free” Twitter scraper on the store usually means a free trial or that same platform credit.

Which Twitter scraper on Apify is the cheapest?

As charged to our account: scrape.badger $0.14 per 1,000 tweets, xquik $0.16 including the platform usage it bills to the user, kaitoeasyapi $0.22, danek $0.28, apidojo $0.40. Watch the minimums: kaitoeasyapi billed 15 rows for a single-tweet lookup, and apidojo’s Twitter Scraper Unlimited charges $0.05 for every single-tweet URL and $0.016 per search or profile query.

Which scrapers return long-form (note) tweets in full?

kaitoeasyapi, xquik, danek and scrape.badger returned a 1,334-character post whole, in search and on a direct lookup. apidojo’s Tweet Scraper V2 and Twitter Scraper Unlimited returned the first 277 characters. In our 100-tweet search sample, 28 tweets were long-form; apidojo returned two of them whole.

How do I scrape all tweets from an account?

A timeline actor (apidojo V2, danek, or xquik in profileTweets mode) pages back through the profile the way X shows it; apidojo’s own schema notes that X stops the timeline at roughly 800 posts. For older posts, run a search with date operators (from:user since:… until:…) in windows; apidojo V2, kaitoeasyapi, xquik and scrape.badger all accept those operators. Sort the output yourself: three of the four timeline actors did not return it in date order; xquik did.

Which scraper has the most filters?

apidojo’s Tweet Scraper V2, with 26 named fields: date range, language, minimum retweets/likes/replies, image/video/quote filters, verified and Blue filters, geo. kaitoeasyapi and xquik expose X’s full search-operator set as individual fields instead. danek and scrape.badger take a single query string and leave the operators to you.

Which Twitter scraper is the fastest?

On the 100-tweet search, xquik finished in 5 seconds, scrape.badger in 18, kaitoeasyapi and danek in 20, and the two apidojo actors in 37 and 40. On a single-tweet lookup apidojo V2, xquik and danek answered in 3 to 4 seconds for the image post; the long-form post took 3 seconds (xquik) to 52 (apidojo V2). Eleven days earlier xquik’s search was the slowest of the six at 34 seconds; section 13 lists what moved. All timings include the actor’s cold start.