X (Twitter) Followers Scraper - $0.09 per 1,000
Pricing
from $0.09 / 1,000 accounts
X (Twitter) Followers Scraper - $0.09 per 1,000
Asking X who follows an account gets whole profiles back, so each row already has the bio, follower and following counts, verification, location, avatar, website and join date. No API key, nothing to paste. $0.09 per 1,000.
Pricing
from $0.09 / 1,000 accounts
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
2 days ago
Last modified
Categories
Share
X (Twitter) Followers Scraper
Handles in, followers out, one row per account. Set mode to following and you get the accounts they follow instead.
Every row is a full profile: handle, display name, bio, follower and following counts, post count, verification badge and its type, location, avatar, banner, website, and the date the account joined X.
No API key, no cookie to paste, no browser.
- Followers or following, chosen with a single field. The same columns either way.
- Profile fields come from X itself at read time, so the counts are live rather than cached.
- Several handles per run, each paged independently up to your own per-handle limit.
- A handle that doesn't exist, or is protected, costs nothing. It returns an uncharged row saying so.
- Empty input returns one labelled sample row, free.
Price
$0.09 per 1,000 accounts. Plus $0.0005 per run as the platform start fee, billed per gigabyte of run memory, so exactly that on the default 1 GB.
No volume tiers, no minimum spend, no subscription.
| Accounts | Total |
|---|---|
| 100 | $0.0095 |
| 1,000 | $0.0905 |
| 10,000 | $0.9005 |
| 100,000 | $9.0005 |
What gets charged
- One
follower-scrapedevent per account row written to the dataset. Nothing else is metered per row. - Free: the sample row an empty run returns, and every diagnostic row. They all carry
"charged": false. - Accounts already returned for the same handle in the same run are dropped before they're charged.
- Handles that don't exist, are suspended or are protected return an uncharged diagnostic row.
- A run that finds nothing costs the start fee and nothing else.
- Rows never leave the dataset without a charge and are never charged without a row. The billed event is a named one, so nothing is quietly attached to
apify-default-dataset-item.
Input
{"handles": ["NASA","github"],"mode": "followers","maxItemsPerHandle": 200}
| Field | What it does |
|---|---|
handles | One or more X handles, with or without the leading @. Full profile URLs such as https://x.com/NASA work too. Up to 10 per run. |
mode | followers (default) returns the accounts that follow each handle. following returns the accounts each handle follows. |
maxItemsPerHandle | How many accounts per handle. Default 50, hard ceiling 2,000 per handle and 5,000 per run. Keep it low while testing, since you pay per row. |
enrichProfiles | On by default. Leave it on. It's what fills in follower counts, location, join date and the rest. Turn it off only if all you want is the list of handles. |
proxyUrls | Leave empty. Only for callers who want traffic to leave through proxy servers they already pay for, as http://user:pass@host:port. |
sessionCookies | Optional, and not needed for a normal run. See When no public source answers. |
Run it with empty input and you get one labelled sample row, free.
Output
One row per account. This is a real row from a real run:
{"ok": true,"charged": true,"recordType": "profile","sourceHandle": "NASA","relation": "follower","userName": "NASAHubble","name": "Hubble","url": "https://x.com/NASAHubble","description": "The official X account for the NASA Hubble Space Telescope, managed and operated by NASA's Goddard Space Flight Center.","followersCount": 8906746,"followingCount": 44,"tweetsCount": 8427,"isVerified": true,"verifiedType": "government","location": "Goddard Space Flight Center","profileImageUrl": "https://pbs.twimg.com/profile_images/3468011581/efb985f24af0a814a722457a768f3cc5_400x400.jpeg","createdAt": "2008-03-06T20:15:02.000Z","isProtected": false,"website": "http://www.nasa.gov/mission_pages/hubble/main/index.html","profileBannerUrl": "https://pbs.twimg.com/profile_banners/14091091/1669391293","listedCount": 15230,"mediaCount": 3116,"favouritesCount": 1241,"userId": "14091091","profileEnriched": true,"scrapedAt": "2026-08-16T15:48:36.774Z"}
Field notes
sourceHandleis the handle you asked about, the account whose list this row came from. Use it to split a multi-handle run.relationisfollowerwhen the row is somebody who followssourceHandle,followingwhen it's somebodysourceHandlefollows.userNameis the handle exactly as X spells it, without the @.userIdis X's numeric account id. It never changes even when the handle does, so it's the better key for anything long-lived.descriptionis the bio as written, line breaks and emoji intact.followersCountis the live count at read time, straight from X.isVerifiedis true when the account carries a checkmark of any kind.verifiedTypesays which:blue,business,governmentorcreator. Null when the account isn't verified.locationis the free-text location field on the profile. People write anything they like in it, including jokes.websiteis the link on the profile, expanded from the shortened form X displays.profileImageUrlis the avatar at 400x400 rather than the 48px thumbnail X returns by default.createdAtis the join date, in ISO 8601 UTC.isProtectedis true when the account is private.profileEnrichedis true when the profile fields were filled in from X. False means only the handle and display name were available for that row. Rare, and visible so you can filter on it.
Real rows carry "charged": true. Sample rows carry "_sample": true, diagnostic rows carry "_diagnostic": true and an errorCode. Neither is billed.
How it works
For each handle it first asks X about the handle itself. That settles in one request whether the account exists, whether it's protected, and how many entries the list even has, so a typo doesn't turn into a long billed run.
It then reads the follower or following list page by page from public, logged-out sources, following the same cursor the pages expose, until it has as many accounts as you asked for.
Every account it finds is then looked up on X directly, and that's where the profile fields come from. The counts, the location, the badge, the avatar and the join date are what X itself reports at read time.
Requests leave through a rotating pool of addresses, so a per-address rate limit is answered by moving rather than waiting.
When no public source answers
Occasionally none of the public sources answers for a handle during a run. Without a cookie of your own, that handle comes back as an uncharged BLOCKED diagnostic row and the run carries on. Re-running usually clears it.
If you pull at volume and would rather that case be covered, paste an auth_token=…; ct0=… pair from your own logged-in x.com into sessionCookies. Both values are needed. X requires the ct0 value to be echoed back in a header, so an auth_token on its own is rejected. The run then reads the list from X directly on your account and your rate limit. It's stored as a secret, and it's pointless unless you're running large jobs. Leaving it empty is the normal case.
The closing log line carries sessionState, so you can see which path a run took.
Ordering, and what "the first 200 followers" means
The list comes back in the order X keeps it, which for followers is newest first. The account that followed most recently is row one. So maxItemsPerHandle: 200 gives you the 200 most recent followers, not a random 200 and not the oldest 200. That's usually what you want for audience tracking, and it's what makes a weekly re-run cheap, because the new arrivals are all at the top.
The following list is ordered the same way, most recently followed first.
There's no way to jump to an arbitrary offset. If you need 2,000 accounts you pay for 2,000 rows and the run pages through them in order.
What people use it for
- Audience research. Pull the followers of three accounts in your niche and see who overlaps, who's verified, and how big their own audiences are.
- Lead lists. Filter on
followersCount,locationor a keyword indescriptionto get a shortlist worth reaching out to. - Competitive audience mapping. Run the same handles weekly and diff on
userIdto see exactly who arrived and who left. - Influencer vetting. Read the following list of an account and check what kind of profiles it actually follows before you pay for a placement.
- Community building. Find the accounts that follow several of your peers but not you yet.
Reading the output
- Real rows carry
"charged": trueand"recordType": "profile". One billed event each. - The sample row carries
"_sample": trueand"charged": false. There's exactly one, only when the input had no handles. - Diagnostic rows carry
"_diagnostic": true,"charged": falseand anerrorCode:NOT_FOUNDwhen a handle doesn't exist, is suspended or is protected,NO_RESULTSwhen the list is genuinely empty,BLOCKEDwhen no public source answered for that handle on that run,NETWORKfor a transport failure,TIME_BUDGETwhen time ran out. Each carries a plain-Englisherrorand thesourceHandleit belongs to.
Filter on charged == true and you have exactly the rows you paid for.
Limits
- A protected account keeps its followers and following lists private. The run returns one uncharged row saying so and moves on. There's no public way to read them.
- Hard ceilings: 2,000 accounts per handle, 5,000 rows per run, 10 handles per run.
- The list is read newest-first and can't be started from an arbitrary offset, so a deep pull of an account with millions of followers means paging through the rows in between.
- Follower and following counts are a snapshot at read time. On an active account they'll differ a minute later.
locationis free text people fill in themselves. Often a joke, a country, or empty. It isn't geocoded.- A small number of accounts come back with only the handle and display name, usually because the account was suspended or renamed between the list page and the lookup. Those rows carry
profileEnriched: falseso you can filter them out. - Email addresses and phone numbers aren't returned. X doesn't publish them and nothing here guesses them.
- Deleted, suspended and deactivated accounts don't appear in the list at all. X removes them from it, so there's nothing to report.
Questions
Do I need an X API key, a developer account or my own cookies?
No. Nothing is asked of you beyond the handles, and the normal path uses no credentials at all.
So what is sessionCookies for?
The rare run where no public source answers for a handle. Without a cookie that handle comes back as an uncharged BLOCKED row. With yours, the run reads the list from X directly on your account and your rate limit. Worth doing if you pull at volume, pointless otherwise.
Can I get the followers of a private account?
No, and neither can anything else. X keeps a protected account's lists private. You get an uncharged row saying the account is protected, and you're not billed for it.
How do I get the accounts a handle follows instead of its followers?
Set mode to following. The columns are identical, and relation changes on every row so mixed datasets stay unambiguous.
Can I run several handles at once?
Yes, up to ten per run. Each handle gets its own maxItemsPerHandle budget, and each row carries sourceHandle so you can split the dataset afterwards.
Will the run fail if something goes wrong?
No. A blocked, empty or missing handle produces an uncharged diagnostic row and the run still finishes as succeeded. A failed run would still bill the start fee, which would mean paying to be told something went wrong.
Can I schedule it?
Yes. Nothing is held between runs. Diff on userId rather than userName. Handles change, ids don't.
How fresh are the numbers in each row?
They're read at the moment the row is built, directly from X. scrapedAt records exactly when.