Twitter Profile Scraper - Followers and Bio, No API Key
Pricing
from $0.14 / 1,000 profile returneds
Twitter Profile Scraper - Followers and Bio, No API Key
Scrape X (Twitter) profiles by handle. You get one row per handle: followers, following, post count, name, bio and verification. It works without an API key or login. It reads profiles only, not search results. $0.14/1k profiles.
Pricing
from $0.14 / 1,000 profile returneds
Rating
5.0
(1)
Developer
Dami's Studio
Maintained by CommunityActor stats
1
Bookmarked
46
Total users
13
Monthly active users
19 hours ago
Last modified
Categories
Share
Twitter Profile Scraper: follower counts, bio and verification for any public handle
Give it a list of X handles and you get one flat row per account: followers, following, post count, display name, bio and both verification flags. No API key, no login, nothing to sign up for.
The awkward part, said up front: this returns the profile only, not the tweets on it. And a field
the account never filled in, like a location, comes back null.
| Input | Usernames, or x.com/handle links |
| Output | One row per profile |
| Ceiling | No cap. One row per unique handle you send |
| Account needed | None from you |
| Price | $0.14 per 1,000 profiles, flat on every plan |
👤 What Twitter Profile Scraper does
You hand it handles, it hands back the profile record behind each one. The @ is optional, and a
profile link works just as well since the handle is read straight out of it.
The same account listed twice comes back once and is charged once, and that includes the same
handle written with different capitals: NASA and nasa are one account.
A handle that does not exist, or that has been suspended, gets an uncharged row saying so and the run carries on down the list. A protected account returns the shell X shows the public, which is the name, the handle and the counts, and that row is a real result.
The field names are X's own rather than the labels in the app, because those are the names you will need if these rows go anywhere else:
| Field | What it is |
|---|---|
friendsCount | How many accounts this one follows. X has called it that for years. |
statusesCount | Total posts, including replies and retweets. |
description | The bio text. |
verified vs isBlueVerified | The old legacy tick and the paid one. They are not the same thing and an account can have either. |
📥 What you give it
{"twitterHandles": ["nasa", "apify", "elonmusk"]}
| Field | Default | What it is |
|---|---|---|
twitterHandles | none | Usernames, with or without @. The form opens with nasa and elonmusk filled in as an example, which is a starting point rather than a default. |
startUrls | none | Or paste profile links like https://x.com/nasa. Mix them with twitterHandles freely. |
sessionCookies | none | Optional and not needed for a normal run. Your own X account, as auth_token=XXXX; ct0=YYYY, one per line, and the run uses it only when it needs one. Use a throwaway account: the value sits in the run input, which anyone who can open the run can read. |
proxyConfiguration | Apify's default | Leave it alone. It is there for people who need the run to leave through servers they already pay for. |
notionConnector, notionParentId | none | Optional. Write each profile into a Notion database as well as the dataset. |
There is no limit on how many handles you can send, and no pause between them, so a very long list is bounded by the run timeout rather than by a cap. Split a list of tens of thousands across runs.
📤 What you get back
A real row from a real run, with an emoji in the bio cut short:
{"ok": true,"charged": true,"url": "https://x.com/NASA","id": "11348282","userName": "NASA","name": "NASA","description": "Making the seemingly impossible, possible. ...","followersCount": 92373823,"friendsCount": 117,"statusesCount": 74312,"verified": true,"isBlueVerified": true,"location": "Pale Blue Dot","profileImageUrl": "https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB_normal.jpg","createdAt": "Wed Dec 19 20:20:32 +0000 2007"}
| Field | What it is |
|---|---|
id | X's numeric account id. It survives a handle change, so it is the one to key on. |
userName, name | The handle, and the display name shown above it. |
followersCount, friendsCount, statusesCount | Followers, following and total posts, as X reported them at read time. |
verified, isBlueVerified | Both tick types, as booleans. |
url | The canonical profile link, using X's own capitalisation of the handle. |
location, profileImageUrl, createdAt | Where the account says it is, its avatar and when it joined, in X's own date format. location is null when the account never set one. |
The avatar link is X's small version. Swap _normal for _400x400 in the address for a larger one.
🧾 Reading the output
Two kinds of row can land in your dataset.
| Row | How to spot it | Billed |
|---|---|---|
| A profile | ok: true and an id | yes |
| A diagnostic | ok: false and an errorCode | no |
Filter on ok == true and you have your data. The charged field separates real rows from
diagnostics, and is not a receipt.
NOT_FOUND means the handle does not exist or the account is gone, so check the spelling.
BLOCKED means the profile could not be read on this run, which is worth trying again rather than
treating as an answer.
One quirk of the Overview table: it shows userName, name, followersCount, statusesCount,
verified and url, so the bio, the following count and the paid tick are not in it at all. Open
the row itself or download the JSON and everything is there.
▶️ How to run it
- Open Twitter Profile Scraper and click Try for free.
- Type handles into Usernames, one per line, or paste links into Profile URLs.
- Click Start.
- Download the dataset as JSON, CSV or Excel, or pull it from the Apify API.
💰 How much does it cost?
$0.14 per 1,000 profiles. Flat on every Apify plan, no volume tiers.
You pay per row that carries a profile. Diagnostic rows, and the second copy of a handle you listed twice, are not charged.
💡 What people use it for
- Refreshing follower counts across a creator or prospect list on a schedule, then diffing week to week.
- Checking a shortlist before an outreach round, so nobody writes to a dead or suspended handle.
- Turning a spreadsheet column of handles into a table with real numbers beside it.
- Grabbing X account ids, which survive a handle change and make a better join key than the handle.
🚧 What it does not do
- No tweets, no replies, no follower lists. This is the profile record. The siblings below cover the rest.
- No search. You need the handles already. It will not find accounts by topic or keyword.
- A protected account gives you the public shell only, and that row is a real result.
- Counts are a snapshot at the moment the row was read, not a history.
- No pacing control and no cap on the list, so a very large batch is limited by the run timeout.
🧭 Which X scraper do you need?
| If you want | Use |
|---|---|
| Follower counts and bios for handles you already have | This one |
| Tweets matching a keyword or an advanced query | Twitter (X) Search Scraper |
| Specific tweets, or a profile's timeline | Tweet Scraper |
| Who follows an account | X Followers Scraper |
| Everything posted into a curated X list | Twitter List Scraper |
❓ Questions people ask
Do I need an X account or an API key? No. The cookie field is a fallback and most runs never touch it.
Can I get the account's tweets too? Not from here. Tweet Scraper reads timelines.
Why is location empty on some accounts? Because those accounts never set one. X leaves it
blank, and so does the row.
What happens to a handle that does not exist? You get an uncharged row marked ok: false with
NOT_FOUND, and the run moves on to the next handle instead of stopping.
Is scraping X legal? This reads public profiles only, never private accounts or messages. Results can still contain personal data, which GDPR and similar laws cover, so have a reason for collecting it. Apify's write-up on the legality of web scraping is a good starting point, and we are not lawyers.
Can I run it on a schedule? Yes. Use Apify's scheduler, or start it from the API and read the dataset when it finishes.
🆘 If something breaks
Open the Issues tab on the actor page. Include the handles you used and the run ID, and paste
any errorCode you got back, since that usually says what happened straight away.