Twitter (X) List Scraper - Full Tweets, Views & Authors avatar

Twitter (X) List Scraper - Full Tweets, Views & Authors

Pricing

Pay per event

Go to Apify Store
Twitter (X) List Scraper - Full Tweets, Views & Authors

Twitter (X) List Scraper - Full Tweets, Views & Authors

Turn any curated X list into a clean data feed. Scrapes every tweet in a list timeline with full untruncated text, likes, retweets, replies, quotes, bookmarks and views, plus hashtags, mentions, media and the author profile. $0.40 per 1,000 tweets plus a $0.001 run-start fee.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

16 hours ago

Last modified

Share

⚡ Twitter (X) List Scraper — Tweets from Any X List

Pull every tweet from any X (Twitter) List timeline. Point it at a list id or URL and get back the full tweet text plus every engagement metric — likes, retweets, replies, quotes, bookmarks and views — with author, media, hashtags and mentions. Export to JSON, CSV or Excel, call it from the API, or have results delivered straight to Notion. $0.40 per 1,000 tweets plus a $0.001 run-start fee — pay only for tweets actually returned.

X gates List timelines behind a login — there is no keyless path to them. The Actor carries a built-in session, so a run needs nothing from you but a list id. That session is shared, so at heavy concurrent load you can add your own cookie in sessionCookies for a rate limit nobody else draws on.

Why this scraper wins

  • 💸 Cheapest on the market, with no per-query surcharge$0.40 / 1,000 tweets plus $0.001 per run start, billed per tweet actually returned. Nothing extra per list queried, no monthly plan, no volume tier. Empty or failed runs cost only the $0.001 start fee.
  • 🔁 Runs out of the box — no cookie to go and find, no API key to register. Add your own cookies if you want to and the run rotates them, backs off on a 429, and drops a session that has stopped working instead of failing the run.
  • 🧹 Clean, flat output — one tidy record per tweet, ready for spreadsheets, dashboards or LLM pipelines. No raw nested GraphQL soup.
  • 🔂 Auto-dedupe — the same tweet is never returned (or charged) twice in a run, even across multiple lists.
  • 🛡️ Rotating datacenter proxy by default — large IP pool, nothing billed per gigabyte. Bring your own residential/ISP proxy servers in the Proxy field (Custom proxies) if you want them; they are used exactly as given.
  • 📬 Built-in delivery — optionally push every run straight into Notion via Apify connectors, with zero extra code.
  • 🚦 Honest errors — if X blocks, rate-limits or a list is inaccessible, you get a clear diagnostic row (BLOCKED, NO_RESULTS, …) instead of silent emptiness.

What you can scrape

ModeInputNotes
List by idlistIds (the number in x.com/i/lists/<id>)Scrape one or many lists in a single run
List by URLstartUrls (https://x.com/i/lists/<id>)List id is parsed out of the URL automatically

The login is handled for you

A List timeline is only served to a signed-in session. That is an allow-list on X's side, not a fingerprint or an address problem, and no proxy changes it. The Actor therefore carries a built-in session and you do not have to set anything up.

The built-in session is shared, and X counts its limits per account rather than per caller. At heavy concurrent load it will throttle, and a run can then come back short or with a BLOCKED diagnostic row saying so. That is the honest trade for zero setup. If you are pulling at volume, or you would rather your throughput did not depend on how busy the Actor is, put your own cookie in sessionCookies and the run uses only yours.

How to get your own cookie (1 minute):

  1. Log in to x.com in your browser (a throwaway account is fine, and a sensible choice).
  2. Press F12Application tab → Cookieshttps://x.com.
  3. Copy the values of auth_token and ct0.
  4. Paste into sessionCookies as auth_token=XXXX; ct0=YYYY — one account per line; several lines are rotated, and one going quiet does not stop the run.

If no session is usable at all, the run still succeeds: it returns one clearly labelled _sample tweet so you can see the exact output shape, and no per-tweet fee is charged for it — that run costs the $0.001 start fee and nothing else.

Input

  • listIds — X list ids (e.g. 34179516). One or many.
  • startUrls — or paste full list URLs (https://x.com/i/lists/34179516); the id is extracted for you.
  • sessionCookies (optional) — runs work without it. Supply one or more of your own account cookies, format auth_token=XXXX; ct0=YYYY, one per line, for a rate limit no other run shares; the Actor rotates across them on a rate-limit. Stored as a secret.
  • maxItems — cap the number of tweets (default 100, max 5000). You pay per tweet.
  • proxyConfiguration — Rotating datacenter addresses by default. Per-gigabyte metered proxy tiers are not offered and are swapped for rotating datacenter addresses automatically, so a run can never quietly run up a bandwidth bill; to use residential addresses, paste your own proxy servers under Custom proxies and they are used verbatim.
  • notionConnector / notionParentId — optional, deliver results to a Notion data source.

Input field names follow the conventions used across similar Actors, so pointing an existing workflow at this one is usually a drop-in change.

Example input

{
"startUrls": ["https://x.com/i/lists/34179516"],
"listIds": ["1234567890123456789"],
"maxItems": 250,
"proxyConfiguration": { "useApifyProxy": true }
}

Output (one record per tweet)

{
"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",
"verified": true
}
}

Pricing

$0.40 per 1,000 tweets ($0.0004 each), plus $0.001 each time a run starts — the cheapest way to scrape X list timelines on the market, with no extra fee per list queried.

What bills and what does not:

EventPriceWhen it fires
Run start$0.001Once per run, whatever the outcome
Tweet scraped$0.0004Once per real tweet pushed to the dataset
  • Sample rows are free. The labelled _sample tweet is never charged.
  • Diagnostics are free. BLOCKED, NO_RESULTS and similar rows are not billed.
  • Duplicates are free. Auto-dedupe means the same tweet is never returned — or charged — twice in a run, even across several lists.
  • Failed and empty runs cost the $0.001 start fee and nothing else.

Flat rate throughout: no volume tiers, no plan gates, and you are only charged for tweets actually returned.

Limitations — read before you buy

  • List timelines require a logged-in session, and the built-in one is shared. X limits per account, not per caller, so at heavy concurrent load runs throttle and can come back short. Supply your own cookie in sessionCookies for a limit nobody else draws on.
  • Sessions wear out. A session that is rate-limited or challenged is dropped for the rest of the run and the next one is used. When nothing usable is left, the run returns the labelled sample row instead of real tweets, uncharged, rather than failing.
  • Private and deleted lists are not accessible. If the session reading the list cannot see it, you get a diagnostic row explaining that, not data.
  • maxItems caps at 5,000 tweets per run. Very long list timelines are paginated; for a full historical sweep, split the work across runs.
  • Some fields can be null. viewCount is absent on older tweets, bookmarkCount is not always exposed, and media URLs expire after a while — download anything you need to keep.
  • Rate limits are X's, not ours. On a 429 the Actor paces itself and rotates to the next session rather than hammering the endpoint; a 429 never retires a session, because a throttled account is a healthy one going too fast. If everything is throttled at once, the run ends with a BLOCKED diagnostic row rather than silently returning a partial list.
  • Tweet text is returned as-is, including the original language; no translation or sentiment scoring is performed.

FAQ

Do I need account cookies? No. Runs work as they are. X does require a logged-in session to view a List timeline — there is no keyless route — but the Actor brings one.

Then why is sessionCookies there? Because the built-in session is shared and X limits per account. Supplying your own gives you a rate limit no other run touches, which is what you want for sustained volume. Add several of your own and the Actor rotates between them.

Where do I find the list id? It's the number in the list URL: x.com/i/lists/3417951634179516. You can also just paste the full URL in startUrls.

Which proxy? The Actor rotates through Apify's datacenter pool by default (large pool, no per-gigabyte charge). If you already own residential or static-ISP proxy servers, paste them under Custom proxies and they are used verbatim. Note that the limit which actually bites on a List timeline is per ACCOUNT, not per address, so rotating addresses alone does not raise it.

It returned a diagnostic row — why? That's the Actor telling you exactly what happened (e.g. BLOCKED, NO_RESULTS) instead of failing silently. Each one carries a sessionState field: ok means the session was fine and the list itself was the problem, exhausted means nothing was left to read the list with, and a re-run — or your own cookie — clears it.