Twitter (X) List Scraper - Full Tweets, Views & Authors
Pricing
Pay per event
Twitter (X) List Scraper - Full Tweets, Views & Authors
X's list timelines are served only to a signed-in session, and this Actor brings its own. One row per tweet: full text, likes, retweets, replies, quotes, bookmarks, views, hashtags, media and the author. No login needed from you. $0.40 per 1,000 tweets.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Twitter (X) List Scraper
Give it an X list id and it walks that list's timeline and writes one row per tweet: the full
untruncated text, likeCount, retweetCount, replyCount, quoteCount, bookmarkCount,
viewCount, createdAt, lang, hashtags, mentions, urls, media, and an author object
with the handle, display name, follower count and verification flags.
Lists are the timeline worth scraping because somebody already did the filtering. A well-kept list is a hand-picked set of accounts on one subject, which beats a keyword search that drags in every spam reply using the word.
About the login, up front
X only serves list timelines to a signed-in session. There is no guest route to them. The
ListLatestTweetsTimeline operation isn't registered on X's guest host at all, and no proxy
changes that.
So the Actor carries an account session of its own. You don't need to log in or find a cookie.
But be clear about what that means: something is logged in, it's shared across everyone running
the Actor, and X counts rate limits per account rather than per caller. Under heavy concurrent use
it throttles, and your run can come back short with a BLOCKED row explaining why.
If your throughput shouldn't depend on how busy the Actor is, put your own cookie in
sessionCookies and the run uses only yours. Log in to x.com (a throwaway account is fine), press
F12, open Application → Cookies → https://x.com, copy auth_token and ct0, and paste them as
auth_token=XXXX; ct0=YYYY. One line per account. Several lines get rotated, and one going quiet
doesn't stop the run. Nothing you paste there is ever printed to the run log. It does sit in the
run's saved input like every other field, which is the reason to use a throwaway account and not
your real one.
Input
{"startUrls": ["https://x.com/i/lists/34179516"],"maxItems": 250}
| Field | What it does |
|---|---|
listIds | The number in x.com/i/lists/<id>. One or many. |
startUrls | Or paste the full list URLs; the id is read out of them. |
maxItems | Tweets per run. Default 100, ceiling 5,000. You pay per tweet. |
sessionCookies | Optional. Your own auth_token=...; ct0=... lines, for a rate limit nobody else draws on. |
proxyConfiguration | Rotating Apify datacenter addresses by default. |
notionConnector / notionParentId | Optional. Push the rows into a Notion data source. |
Run it with no list at all and you get one labelled _sample tweet, uncharged, so you can see the
shape before you spend anything.
Metered Apify proxy groups (Residential, Google SERP) are not selectable here. If you pick one it is swapped for datacenter addresses and the log says so, so a run can't quietly run up a per-gigabyte bandwidth bill. Your own proxy servers, pasted under Custom proxies, are used exactly as given.
A row
{"id": "1789000000000000000","url": "https://x.com/nasa/status/1789000000000000000","text": "We're going back to the Moon.","createdAt": "Mon May 13 14:02:11 +0000 2024","lang": "en","replyCount": 312,"retweetCount": 1840,"likeCount": 21500,"quoteCount": 96,"bookmarkCount": 410,"viewCount": 1230000,"isReply": false,"isRetweet": false,"isQuote": false,"conversationId": "1789000000000000000","hashtags": ["Artemis"],"mentions": [],"urls": [],"media": [{ "type": "photo", "url": "https://pbs.twimg.com/media/xxx.jpg" }],"author": {"id": "11348282","userName": "NASA","name": "NASA","followersCount": 96000000,"verified": true}}
Billing
$0.40 per 1,000 tweets ($0.0004 each), plus $0.001 each time a run starts. Same rate on the free plan as on any paid one. No volume tiers, no per-list fee.
| Event | Price | Fires |
|---|---|---|
| Actor start | $0.001 | Once per run, whatever happens |
| Tweet scraped | $0.0004 | Once per real tweet written to the dataset |
The _sample row isn't charged. Diagnostic rows aren't charged. Tweets are deduplicated by id
within a run, including across several lists, so you never pay twice for the same one. A run that
comes back empty costs the $0.001 start fee and nothing else.
Limits
The built-in session is shared. X limits per account, so at busy moments runs throttle and can
return fewer tweets than you asked for. Your own cookie in sessionCookies fixes that.
Sessions wear out. A 429 is treated as a healthy account going too fast: the run backs off
and rotates to another session rather than retiring that one. A real 401, or a body that says
logged out, evicts the session. When nothing usable is left the run returns the labelled sample row
instead of failing, and charges nothing for it.
Private and deleted lists aren't readable. If the session can't see the list, you get a diagnostic row that says so.
maxItems caps at 5,000 per run. For a full sweep of a very long timeline, split it across
runs.
Some fields come back null. viewCount is missing on older tweets and bookmarkCount isn't
always exposed. Media URLs expire, so download anything you want to keep.
Text is returned as X published it, in the original language. Nothing is translated or scored.
FAQ
Do I need cookies? No. Runs work as-is.
Then why is sessionCookies there? Because the built-in session is shared and X limits per
account. Your own cookie gives you a limit no other run touches.
Where's the list id? The number in the URL: x.com/i/lists/34179516 → 34179516. Or paste the
whole URL into startUrls.
Will a different proxy raise the rate limit? No. The limit that bites on a list timeline is per account, not per address.
Why did I get a diagnostic row? So you know what happened instead of getting silence. Check
sessionState: ok means the session was fine and the list was the problem, exhausted means
nothing was left to read it with. A re-run, or your own cookie, clears the second one.