Home › Guides › X Profile Scraper
X (Twitter) account data: followers, real engagement and follower growth between runs
Followers are easy to buy; engagement is not. The X (Twitter) Profile Scraper turns a list of accounts into one row each — everything X states about the account (38 fields) plus three things it does not: how often it posts, how much engagement it actually gets (avgEngagementPer1kFollowers, comparable across sizes), and how its following changed since your last run. One read per account, no login, no API key, no browser.
Who it's for
- Influencer and competitor researchers who want a shortlist ranked by real engagement, not raw follower counts.
- Social teams running a weekly follower-growth table across a watchlist.
- Anyone auditing a list — a dead-account sweep that separates live accounts from abandoned ones.
- Dashboards and LLMs that need flat rows with stable field names and ISO timestamps.
What you get
| Group | Fields |
|---|---|
| Account | ID, handle, name, bio, website, location, followers, following, posts, likes given, listed count, media count, verification & type, protected flag, images, join date |
| Derived | Account age, lifetime posts per day, followers-to-following ratio |
| Activity | Posts on the embedded page, cadence, days since last post, average/median/max engagement, engagement per 1,000 followers, top post, languages, content mix, most-mentioned accounts |
| Growth | Follower change, change per day, percent change and posts added since this account was last read |
A real row from a run on 2026-10-19 (trimmed):
{
"type": "profile",
"handle": "NASA",
"followers": 92320972,
"following": 115,
"tweets": 74438,
"verified": true,
"verifiedType": "Government",
"accountAgeDays": 6879,
"tweetsPerDay": 10.82,
"postsPerDay": 3.9,
"daysSinceLastPost": 2.7,
"avgEngagement": 2914.8,
"avgEngagementPer1kFollowers": 0.032,
"activity": { "postsOnPage": 20, "pageSpanDays": 5.1, "medianEngagement": 1480, "withMediaPercent": 45 },
"growth": { "daysSincePreviousRead": 7.1, "followersChange": 18422, "followersChangePerDay": 2594.6, "postsChange": 27 }
}
How it works
The Actor reads X's own embed (syndication) backend — the service that renders embedded timelines on other people's websites. One read per account brings two things at once: the account object X states, and the account's newest page of posts. The first becomes the row's identity and counts; the second becomes the activity figures. Nothing is logged in, no cookie jar is kept and no browser is started — so a run is fast and cheap and does not break when X changes its web app.
Activity and growth cost nothing extra. The activity figures come from the same single read, and growth only needs the counts from your previous run, kept in a key-value store of your own account. Run it on a schedule and every run after the first states what changed.
Input
| Input | What it does |
|---|---|
accounts | The accounts to read: @handle, x.com/handle or numeric id — mixed in one list |
includeActivity · trackGrowth | Measure the newest embedded page (default on) · state the change since this account was last read (default on) |
minFollowers · onlyVerified · activeWithinDays | Drop accounts under a follower floor · verified only · active within N days — none of them charged |
maxAccounts · concurrency | Cost cap for the run · accounts read side by side (default 3; X refuses bursts, and a refused read is retried one at a time at the end) |
Three accounts, with activity and growth:
{ "accounts": ["@NASA", "x.com/nike", "@Microsoft"], "includeActivity": true, "trackGrowth": true }
Honest limits
- Activity comes from one page. X embeds an account's newest 20–105 posts with no paging, so cadence and engagement are measured over
pageSpanDays— days for a busy account, months for a quiet one. The field travels with the row for exactly that reason. - No follower lists, no keyword search, no full history, no email or phone — X's embed backend serves none of those, so the Actor does not claim them.
- Growth needs a previous run. The first read of an account has nothing to compare against and says so (
growth: null), never a fake zero.locationis often empty and staysnullrather than guessed. - Protected accounts are not readable, and an account X has no public record of comes back as a free status row.
- The rate budget is shared across all runs of the family, so run them one after another and leave concurrency at its default.
Pricing
Pay per result: $1 per 1,000 account rows. Status rows and accounts left out by a filter are free — you pay for rows you receive, and the activity and growth columns cost nothing extra. You also pay Apify for the small compute (one HTTP read per account, no browser). Current prices are on the actor's Pricing tab on Apify.
Rank accounts by real numbers: paste handles and get followers, engagement per 1,000 followers, posting cadence and weekly growth — exportable to JSON, CSV or Excel.
Open the X Profile Scraper →Related
This Actor reads accounts; to watch a list of accounts' newest posts on a schedule use the X Account Monitor, and for the current numbers on tweets you already have the links to use the X Tweet Details Scraper. For creators on another network, see the YouTube Channel Finder.
Frequently asked questions
Do I need an X account, login or API key?
No. The Actor reads X's public embed (syndication) backend — the service that renders embedded timelines on other sites — with no login, no cookies and no browser: one HTTP read per account.
Why is postsPerDay different from postsPerDayOnPage?
postsPerDay is the lifetime average (tweets ÷ account age); postsPerDayOnPage is the cadence on the page just read. A dormant account with a long history shows a high lifetime figure and a low current one — that gap is the signal.
How are the activity figures measured?
From the one page X embeds — the account's newest 20 to 105 posts (measured 2026-10-19), with no paging. Every row carries pageSpanDays so you know the window: days for a busy account, months for a quiet one.
Where is the growth history kept?
In a key-value store of your own Apify account (x-profile-history by default), not shared with anyone. Growth is null the first time an account is read — there is nothing to compare against, and a zero would be a lie.
What can't it do?
No follower lists, no keyword search, no full posting history, no email or phone — X's embed backend serves none of those. Protected accounts are not readable and come back as a free status row.
X (Twitter) Profile Scraper — the account record plus real activity and growth. Pay per row, no API key.
Get X account data on Apify →