Twitter List Scraper: tweets from any public X List

Twitter List Scraper reads any public X List and returns the tweets on it, each one carrying the full profile of the member who posted it.

apidojo/twitter-list-scraper

Estimated run cost

$0.00

Free Apify plan: 5 runs a month, 10 items a run. No credit card.

$0.008
per list, ~20 tweets in
$0.02
real floor, at the 50 minimum
$0.40
per 1,000 tweets
5.0 / 5
from 9 Apify reviews

Read on 21 September 2026.

Two ways in, and one number that matters

A List is named either by its URL or by the ID at the end of that URL, and the two cost the same. What actually shapes the bill is the 50-tweet minimum each list has to clear.

  • startUrls

    $0.008per list

    ~20 tweets included

    Paste the List link. Either x.com or twitter.com form works.

    x.com/i/lists/78783491

  • listIds

    $0.008per list

    ~20 tweets included

    The digits at the end of that URL. What to store if the list is going into a database.

    78783491

  • What the price table does not say

    the 50-tweet minimum

    $0.02the real floor

    Below 50 risks rate-limiting

    Every list has to fetch at least fifty. Twenty are free, so thirty are always billed. The floor is $0.02 a list, not $0.008.

    $0.008 + 30 × $0.0004

  • maxItems

    ÷ $0.0004budget to cap

    Set it every time

    The ceiling, per list. Budget divided by $0.0004 is roughly what to put here.

    1000

The listing is candid about the floor and about what to do below it: for jobs smaller than fifty tweets it points you at Twitter Scraper Unlimited instead, which prices single queries rather than lists.

Twitter List Scraper specificationsapidojo/twitter-list-scraper
Apify actorapidojo/twitter-list-scraper
InputsstartUrls · listIds · maxItems · customMapFunction. Four, and that is all
ReturnsOne record per tweet, with the author’s profile nested on each
Minimum per list50 tweets. Smaller requests may be rate-limited
Speed30 to 80 tweets a second, by either input type
ConcurrencyOne or two runs at a time, with a few minutes between large ones
Private ListsNot accessible. Authentication is not supported
Reliability97.66% of 1,908 runs succeeded in the last 30 days

One list, many lists, or the people on them

Three shapes of run cover what this actor is for: read one curated List, sweep a set of them in a single pass, or mine the author objects to get at the members behind the tweets.

How do you scrape tweets from an X List?

Paste the List URL into startUrls. The list costs $0.008 with roughly 20 tweets inside it, then $0.0004 each. Five hundred tweets from one List cost $0.20.

Input

{
  "startUrls": ["https://x.com/i/lists/78783491"],
  "maxItems": 500
}

$0.008 + 480 × $0.0004=$0.20

What comes back

The tweet record, Five engagement counters and the author’s full profile on every tweet.

{
  "type": "tweet",
  "id": "1757983181972930764",
  "url": "https://x.com/ESPNStatsInfo/status/1757983181972930764",
  "text": "Anthony Davis and Rui Hachimura are the 1st @Lakers duo…",
  "retweetCount": 58,
  "replyCount": 10,
  "likeCount": 158,
  "quoteCount": 8,
  "bookmarkCount": 7,
  "createdAt": "Thu Feb 15 04:20:26 +0000 2024",
  "lang": "en",
  "isReply": false
}

Private Lists return nothing at all

Only public Lists are readable, authentication is not supported, so a private List produces an empty dataset rather than an error. If a run comes back empty, check the List in a logged-out window before checking anything else.

How do you scrape several X Lists at once?

Put the IDs into listIds. Each list is its own $0.008 query with its own included page, so five lists bring 100 free tweets between them. Five thousand tweets across five Lists cost $2.00.

Input

{
  "listIds": ["78783491", "1657850814910590977"],
  "maxItems": 2000
}

5 × $0.008 + 4,900 × $0.0004=$2.00

What comes back

The tweet record, Identical across lists. Group on author.userName to see who dominates a set.

{
  "isRetweet": false,
  "isQuote": false,
  "media": [
    "https://pbs.twimg.com/media/GGWb69-a0AAj1iA.jpg"
  ],
  "author": {
    "userName": "ESPNStatsInfo",
    "followers": 1828908,
    "isVerified": true,
    "isBlueVerified": true
  }
}

Batching helps here, unlike its sibling

Several lists in one run is the listing’s own advice, and it costs nothing extra: the per-tweet rate is flat. That is the opposite of Twitter Scraper Unlimited, where the item price rises with the number of queries in a run.

How do you get the members of an X List?

Indirectly. There is no member roster in the output: members arrive as the authors of the tweets they posted. Every record nests a full profile, so de-duplicating on author.userName gives you the active part of the membership.

Input

{
  "startUrls": ["https://x.com/i/lists/78783491"],
  "maxItems": 1000
}

$0.008 + 980 × $0.0004=$0.40

What comes back

The author object, Seventeen fields per member, nested on every tweet they posted.

"author": {
  "type": "user",
  "userName": "ESPNStatsInfo",
  "id": "53120768",
  "name": "ESPN Stats & Info",
  "description": "Our mission is to serve fans…",
  "location": "Bristol, CT",
  "followers": 1828908,
  "following": 61,
  "protected": false,
  "createdAt": "Thu Jul 02 17:03:54 +0000 2009",
  "mediaCount": 46266,
  "statusesCount": 162931,
  "verifiedType": "business"
}

Silent members never appear

The listing advertises list-level and member-level data, but the only output it documents is a tweet record and its charge event reads "per tweet returned". A member who has not posted inside the window you pulled has no tweet, so no record. Treat this as the active membership, not the roster.

A tweet, and whoever wrote it

One shape. The listing publishes an availability guarantee for fifteen of its fields: fourteen are always present and only media is conditional.

  • 6

    The tweet

    All guaranteed present

    • id
    • url, twitterUrl
    • text
    • createdAt
    • lang
  • 5

    Engagement

    All guaranteed present

    • likeCount, retweetCount
    • replyCount
    • quoteCount
    • bookmarkCount
  • 12

    The author

    Nested on every tweet

    • userName, id, name
    • description, location
    • followers, following
    • statusesCount, mediaCount
    • isVerified, isBlueVerified
    • verifiedType, protected
  • 4

    Kind and media

    media is the one conditional field

    • isReply, isRetweet
    • isQuote
    • media[], URLs if present
    • author.profilePicture, coverPicture
Field referenceDocumented in the actor README
id · url · twitterUrlTweet ID and both link forms. All three guaranteed
textThe tweet body as posted
createdAtX’s own date string, e.g. "Thu Feb 15 04:20:26 +0000 2024"
langLanguage X detected
likeCount · retweetCountGuaranteed present on every record
replyCount · quoteCountAlso guaranteed
bookmarkCountSaves. Guaranteed, and rarer than it should be
isReply · isRetweet · isQuoteWhat kind of tweet this is
mediaArray of media URLs. The only field the listing marks conditional
author.userName · id · nameThe member’s handle, ID and display name
author.description · locationBio and profile location
author.followers · followingBoth counts. followers is guaranteed
author.statusesCount · mediaCountTotal posts, and posts carrying media
author.isVerified · isBlueVerifiedLegacy verification and X Premium, guaranteed separately
author.verifiedType"business" and similar, where X exposes it
author.protected · createdAtWhether the account is locked, and when it was made

The author block is the reason this scraper doubles as member research: every tweet carries twelve fields about whoever posted it, so one list run yields both the content and a profile for each active member without a second call.

Where a run goes wrong

Five rules, and the listing states four of them itself. The fifth is what its own price table leaves out.

  • 01

    Fifty tweets minimum, per list

    Anything smaller creates a negative margin and may trip the rate limiter. The listing’s own recommendation for smaller jobs is to use Twitter Scraper Unlimited instead, which bills per query rather than per list.

  • 02

    So the floor is $0.02, not $0.008

    Fifty tweets with twenty included leaves thirty billed. The headline $0.008 is the query fee, not what a compliant run can actually cost.

  • 03

    Private Lists are unreachable

    Authentication is not supported, so a private List returns an empty dataset rather than an error. Check visibility first when a run comes back with nothing.

  • 04

    One or two concurrent runs

    The listing asks for no more than two at a time, with a few minutes between large extractions.

  • 05

    customMapFunction must not filter

    Using it to drop records causes automatic blocking, which the listing lists twice, once under troubleshooting and once under what not to do.

Free Apify accounts get 5 runs a month, capped at 10 items each.

Flat per tweet, once you clear the floor

Every list is $0.008 with roughly 20 tweets inside it, then $0.0004 a tweet. Past the 50-tweet minimum the rate never changes, whether the run reads one list or a hundred.

What a run costsQuery fee + $0.0005 × billable items
RunMethodCalculationCost
50 tweets, the minimum1 list$0.008 + 30 × $0.0004$0.02
500 tweets1 list$0.008 + 480 × $0.0004$0.20
1,000 tweets1 list$0.008 + 980 × $0.0004$0.40
10,000 tweets1 list$0.008 + 9,980 × $0.0004$4.00
5,000 tweets5 lists5 × $0.008 + 4,900 × $0.0004$2.00
50,000 tweets20 lists20 × $0.008 + 49,600 × $0.0004$20.00
100,000 tweets100 lists100 × $0.008 + 98,000 × $0.0004$40.00

All six figures the listing publishes reproduce exactly from its two charge events, which is rarer than it should be. The first row is this page’s addition: the minimum run, which the price table does not price.

Who reads other people’s Lists?

Five kinds of work treat a curated List as a ready-made panel: lead generation, competitor intelligence, journalism, investor tracking and recruiting. Somebody already did the curation, which is the whole appeal.

  • Lead generation

    Get the members, on industry Lists

    Mine the author objects for handles, bios and follower counts from a list someone else already qualified

    $0.40 per 1,000 tweets

  • Competitor intelligence

    Sweep several, on a rival’s public Lists

    Read the Lists a competitor curates to see who they consider worth following

    $2.00 per 5 lists

  • Journalists

    Read one List, scheduled

    Follow a beat through a hand-picked panel instead of an algorithmic timeline

    $0.02 per check at the minimum

  • Investor and VC tracking

    Read one List, on a portfolio List

    Watch a portfolio or sector panel in one feed, with each poster’s reach attached

    $0.20 per 500 tweets

  • Recruiting

    Get the members, on conference Lists

    Turn a speaker or attendee List into a sourcing pipeline with bios and locations

    $4.00 per 10,000 tweets

Scripting a List pull

The actor is apidojo/twitter-list-scraper. With four inputs there is little to configure, so the work in code is on the way out: de-duplicating authors, and keeping maxItems above the fifty-tweet floor.

from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

# maxItems below 50 per list risks the rate limiter, per the listing.
run = client.actor("apidojo/twitter-list-scraper").call(run_input={
    "listIds": ["78783491", "1657850814910590977"],
    "maxItems": 2000,
})

# Members arrive as tweet authors, so de-duplicate to get the roster.
members = {}
for t in client.dataset(run.default_dataset_id).iterate_items():
    a = t["author"]
    members[a["userName"]] = a

for handle, a in sorted(members.items(), key=lambda kv: -kv[1]["followers"]):
    print(handle, a["followers"], a["isBlueVerified"], a.get("location", ""))
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const run = await client.actor('apidojo/twitter-list-scraper').call({
  startUrls: ['https://x.com/i/lists/78783491'],
  maxItems: 1000,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();

// Who carries the List: share of its tweets, by author.
const byAuthor = Object.groupBy(items, (t) => t.author.userName);
const share = Object.entries(byAuthor)
 .map(([h, ts]) => [h, ts.length, (100 * ts.length) / items.length])
 .sort((a, b) => b[1] - a[1]);
console.log(share.slice(0, 10));
curl -X POST \
  "https://api.apify.com/v2/acts/apidojo~twitter-list-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"listIds":["78783491"],"maxItems":1000}'

Results land in an Apify dataset, downloadable as CSV or readable over the API. Keep concurrent runs to one or two, which the listing asks for explicitly, and leave a few minutes between large extractions.

Twitter List Scraper FAQ

How much does it cost to scrape an X List?

A list costs $0.008 with roughly 20 tweets included, then $0.0004 a tweet. A thousand tweets come to $0.40 and ten thousand to $4.00.

Why can a list not cost less than $0.02?

Because each list has to fetch at least 50 tweets and only about 20 are included. Thirty billed tweets plus the query fee is $0.02, which is the real floor whatever the price table suggests.

Does it return the List’s member roster?

Not as a separate list. Members come back as the authors of their tweets, with twelve profile fields nested on each record. De-duplicate on author.userName to get the active membership, anyone who has not posted will not appear.

Can I scrape a private List?

No. Only public Lists are accessible, because authentication is not supported. A private List returns an empty dataset rather than an error.

Where do I find a List ID?

It is the last part of the List URL. In x.com/i/lists/78783491 the ID is 78783491, and it is what to store if the list is going into a database.

Can I scrape several Lists in one run?

Yes, and the listing recommends it. Each list carries its own query fee and its own included page, and the per-tweet rate stays flat however many you batch.

How fast is it?

The listing quotes 30 to 80 tweets a second, the same by List URL or by List ID.

What should I use for fewer than 50 tweets?

The listing points you at Twitter Scraper Unlimited, which bills per query rather than per list and has no such minimum.

Where Twitter List Scraper fits

Read one List

Two cents at the minimum, forty for a thousand tweets.

listIds: ["78783491"] · maxItems: 1000

Run this scraper free

Apidojo is not affiliated with X Corp.