X(twitter) User Profile & Tweets Scraper avatar

X(twitter) User Profile & Tweets Scraper

Pricing

from $3.99 / 1,000 results

Go to Apify Store
X(twitter) User Profile & Tweets Scraper

X(twitter) User Profile & Tweets Scraper

Scrapes tweets and profile data from Twitter X, capturing usernames, bios, tweet text, media, timestamps, metrics, follower counts, and profile URLs. Ideal for trend tracking, research, influencer insights, and large-scale Twitter X data extraction

Pricing

from $3.99 / 1,000 results

Rating

1.0

(1)

Developer

Scrapio

Scrapio

Maintained by Community

Actor stats

1

Bookmarked

60

Total users

29

Monthly active users

6 days ago

Last modified

Share

X (Twitter) Scraper โ€” Profiles, Posts and Follower Lists as JSON

This X (Twitter) scraper returns three things from any public profile: the account itself, its recent posts, and โ€” once you supply your own x.com session cookies โ€” the actual follower and following rosters, not just the counters X shows on a profile page. Every row lands as typed JSON tagged by rowType: profile, tweet, follower, following. Unlike scraping frameworks that return raw HTML, this Actor returns ready-to-use fields โ€” no parsing, no regex, no HTML walking. The guide below documents every field the Actor writes, the real X-imposed limits behind them, and how teams run it for audience mapping, monitoring and AI pipelines.


๐Ÿงญ What Does This X (Twitter) Scraper Do?

It resolves an X profile from a URL, @handle or numeric user ID, reads that account's own timeline, and โ€” with your session cookies โ€” pages through the account's follower and following lists using X's own cursor. No X account is needed for the profile and post data; it runs on a keyless guest session. The follower and following rosters are gated by X itself to logged-in clients, so those two lists only run once you add your own authToken and ct0 cookies.

  • Resolves https://x.com/name, @name, a bare handle, or a numeric user ID to one account
  • Reads up to 100 recent posts per profile, sorted newest, oldest, or most-liked
  • Recovers the pinned post and flags it, without over-counting the post cap
  • Pages the follower roster and the following roster independently, each with its own cap (0โ€“5000)
  • Screens roster accounts by minimum follower count, blue-verification, and protected/locked status while paging
  • Reports what happened per profile: pages fetched, accounts screened out, whether a roster was truncated, and X's own rate-limit counters
  • Attaches Apify Residential Proxy to every outbound request by default

โšก Features & Capabilities

This Actor's capabilities split into three groups: what it reads from X, how its output compares to the base scraper it extends, and where it stops.

Core features

  • Profile resolution across four input shapes (startUrls) โ€” profile URL, @handle, bare handle, numeric user ID
  • Post/timeline scraping with sortOrder (newest, oldest, popular) applied before the maxTweets cutoff, and withReplies to filter the profile's own replies out of the timeline
  • Follower and following rosters emitted as their own dataset rows (rowType: "follower" / "following"), each carrying rosterRank, followerToFollowingRatio, accountAgeDays, and the account's own bio/location/website/verification fields
  • Roster quality screens โ€” minFollowerCount, onlyVerifiedFollowers, excludeProtectedAccounts โ€” applied while paging, so a screened run still fills the cap with accounts that passed
  • Per-run accounting on the profile row โ€” postsCollected, followersCollected, followersScreenedOut, followersPagesFetched, followersTruncated, rosterSkippedReason, rateLimitRemaining, rateLimitHits โ€” so a thin result is explained, not silent
  • Live GraphQL query-ID discovery for the follower/following operations, harvested from X's own web bundle at run time, because those IDs rotate and a hardcoded one answers HTTP 404

How this Actor compares to the base scraper it extends

This Actor is built on top of Twitter (X.com) Tweets & Profiles Scraper โ€” its transport, timeline walker and post-row builder are imported verbatim (src/base_main.py is that actor's own src/main.py), so every post field is produced by that actor's own code, unchanged. This Actor only adds the roster layer on top.

FeatureThis ActorBase Twitter (X.com) Tweets & Profiles Scraper
Post and profile fieldsโœ… Identical โ€” same builder codeโœ… Same fields
Follower / following rostersโœ… Cursor-paged, capped 0โ€“5,000 per listโŒ Not returned
Roster quality screensโœ… Min-follower floor, verified-only, exclude-protectedโ€”
sortOrder on postsโœ… Applied before the capDeclared in that actor's schema but not read by its own code
Requires an X loginOnly for the two roster switchesNo
Per-run rate-limit reportingโœ… rateLimitRemaining / rateLimitHits on the profile rowNot exposed

If your use case is feeding structured audience data to an LLM or a CRM, the roster rows are the decision-maker โ€” a follower/following list assembled by hand from the public UI does not scale past a few dozen accounts.

When another tool might suit you better

If all you need is a profile's own posts and bio โ€” no audience data at all โ€” the plain base scraper is the simpler tool: one less input section, and no need to ever touch x.com session cookies. This Actor is also not the right tool for keyword or hashtag search (targets that look like a search phrase are skipped with a warning) or for reading a poll attached to a single post โ€” X's poll data lives on a post, not a profile, and isn't part of this Actor's output at all.

This Actor within the Scrapio X (Twitter) data stack

This Actor covers profiles, posts, and follower/following rosters. For poll results on individual X posts โ€” options, vote counts, and whether voting is still open โ€” use Twitter X Tweets Scraper Scraper With Poll Results, also published under the Scrapio account.


Why do developers and data teams scrape X (Twitter)?

๐Ÿข Growth and influencer marketing teams

A growth team feeds startUrls a shortlist of creator or competitor accounts and reads back totalFollowers, totalFollowing, followerToFollowingRatio and the follower roster itself โ€” the actual accounts, not just the count โ€” with onlyVerifiedFollowers or minFollowerCount to strip empty accounts before anyone reviews the list. The output lands as one dataset per run, ready to filter in a spreadsheet or push into a CRM for outreach targeting.

๐Ÿ“Š AI training data and RAG indexing

description (bio) and text (post body) are the high-information text fields here โ€” bios are short, dense identity statements, and post text is the platform's native content unit. For RAG enrichment, indexing description alongside professionalCategory and verifiedType gives an agent enough context to answer "who is this account" without a follow-up lookup. For training data, the structured fields โ€” totalFollowers, totalFollowing, accountAgeDays, verified โ€” return as typed primitives (booleans, integers, ISO timestamps) with no string-to-number cleanup needed.

๐Ÿ“ฑ Competitive and market intelligence

Point the Actor at a competitor's account with getFollowers/getFollowing on and rosterSortBy: "followersDesc" to see who follows them, ranked. Run it on a schedule and diff totalFollowers, postsCollected and the roster composition between runs to catch a competitor's audience or posting cadence shifting.

๐Ÿ”ฌ Research and academic use

Public-account bios, follow relationships and post metadata (likes, retweets, views) support social-network and platform-behavior research at the scale a manual review can't reach. This Actor reads only publicly accessible profiles and posts โ€” it does not access private accounts or content behind a login wall other than what X itself shows to a follower/following list viewer.

๐ŸŽฅ Product and SaaS development

Audience-analytics dashboards, influencer-discovery tools and lead-enrichment products can run this Actor on a schedule and store the profile and roster rows as the backing dataset, using sourceUserId to key each roster row back to the profile it came from.


๐Ÿš Input Parameters

Every parameter below is read directly from .actor/actor.json, in schema order.

ParameterRequiredTypeDefaultDescription
startUrlsYesarray of strings["https://x.com/apify"]Target X profiles. Profile URL, @handle, bare handle, or numeric user ID โ€” all four forms resolve to the same account. Keyword searches are not supported.
getFollowersNobooleantrueCollect the follower roster. Needs authToken + ct0.
getFollowingNobooleantrueCollect the following roster. Needs authToken + ct0.
maxFollowersNointeger (0โ€“5000)50Follower cap per profile โ€” stops after this many accounts that pass the screens below. 0 turns the follower roster off.
maxFollowingNointeger (0โ€“5000)50Following cap per profile, same rule.
minFollowerCountNointeger (0โ€“100,000,000)0Drops roster accounts below this follower count. 0 keeps everyone.
onlyVerifiedFollowersNobooleanfalseKeep only blue-verified accounts in the rosters.
excludeProtectedAccountsNobooleanfalseDrop protected (locked) accounts from the rosters.
rosterSortByNoenum"listOrder"Roster row order: listOrder (X's own order), followersDesc, followersAsc, followingDesc, postsDesc.
authTokenNostring (secret)โ€”Your x.com auth_token cookie. Required for the follower and following rosters only.
ct0Nostring (secret)โ€”Your x.com ct0 cookie, from the same session as authToken. Sent as a cookie and as the x-csrf-token header.
maxTweetsNointeger (0โ€“100)10Maximum posts per profile. 0 skips posts and returns the profile row plus rosters only.
sortOrderNoenum"newest"Post order: newest, oldest, popular (most-liked). Applied before the maxTweets cutoff.
withRepliesNobooleantrueKeep the profile's own replies in the post rows.
includeUserInfoNobooleantrueAttach the nested user object and flat author columns to every post and roster row.
proxyConfigurationNoobject{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}Apify Proxy, attached to every outbound request.

Example input

{
"startUrls": ["https://x.com/apify", "@elonmusk", "3510729917"],
"getFollowers": true,
"getFollowing": true,
"maxFollowers": 200,
"maxFollowing": 200,
"minFollowerCount": 100,
"onlyVerifiedFollowers": false,
"excludeProtectedAccounts": true,
"rosterSortBy": "followersDesc",
"authToken": "your_x_auth_token_cookie_value",
"ct0": "your_x_ct0_cookie_value",
"maxTweets": 25,
"sortOrder": "newest",
"withReplies": true,
"includeUserInfo": true,
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}

Supported URL types and input formats

  • Profile URL โ€” https://x.com/apify or https://twitter.com/apify
  • Handle, with or without @ โ€” @apify or apify
  • Numeric user ID โ€” 3510729917
  • Not supported โ€” a keyword, hashtag, or single-post URL (.../status/...). Any of these is skipped with a log warning rather than producing an empty or wrong row.

๐Ÿ“ฆ Output Format

Every run writes newline-delimited JSON rows to the Actor's dataset, one row per profile, per post, and per roster account, all sharing the same rowType tag and the shared account columns (handle, profileUrl, avatar, description, location, website, joinDate, verifiedType, protected, totalFollowers, totalFollowing, totalTweets, totalMediaCount, totalLikes, bannerUrl, professionalCategory). The dataset exposes four preset views on the Apify platform: All rows, Follower / following roster, Posts, and Profile rows โ€” what each run actually collected. Results can be exported from the Console or the API as JSON, CSV, Excel, XML, or RSS.

Output for a profile row

{
"rowType": "profile",
"sourceUsername": "@apify",
"sourceUserId": "3510729917",
"sourceProfileUrl": "https://x.com/apify",
"username": "@apify",
"fullname": "Apify",
"verified": true,
"url": "https://x.com/apify",
"userId": "3510729917",
"followerToFollowingRatio": 42.7,
"accountAgeDays": 3210,
"postsCollected": 25,
"pinnedPostsRecovered": 1,
"followersFetched": true,
"followingFetched": true,
"followersCollected": 200,
"followingCollected": 180,
"followersScreenedOut": 34,
"followingScreenedOut": 5,
"followersPagesFetched": 4,
"followingPagesFetched": 4,
"followersTruncated": false,
"followingTruncated": true,
"unavailableAccountsSkipped": 2,
"rosterSkippedReason": null,
"rateLimitRemaining": 187,
"rateLimitHits": 0,
"handle": "apify",
"profileUrl": "https://x.com/apify",
"avatar": "https://pbs.twimg.com/profile_images/0000000000/apify.jpg",
"description": "Full-stack web scraping and browser automation platform.",
"location": "Prague, Czech Republic",
"website": "https://apify.com",
"websiteShortlink": "https://t.co/abcdef1234",
"joinDate": "Wed Sep 20 12:29:32 +0000 2017",
"joinDateIso": "2017-09-20T12:29:32Z",
"verifiedType": "Business",
"protected": false,
"totalFollowers": 8540,
"totalFollowing": 200,
"totalTweets": 4210,
"totalMediaCount": 812,
"totalLikes": 1523,
"bannerUrl": "https://pbs.twimg.com/profile_banners/0000000000/1600",
"professionalCategory": "Software company",
"user": {
"avatar": "https://pbs.twimg.com/profile_images/0000000000/apify.jpg",
"username": "apify",
"userFullName": "Apify",
"description": "Full-stack web scraping and browser automation platform.",
"location": "Prague, Czech Republic",
"website": "https://apify.com",
"joinDate": "Wed Sep 20 12:29:32 +0000 2017",
"verified": true,
"totalLikes": 1523,
"totalTweets": 4210,
"totalFollowing": 200,
"totalFollowers": 8540,
"url": "https://t.co/abcdef1234",
"userId": "3510729917",
"totalMediaCount": 812
}
}

Output for a post (tweet) row

{
"id": "1888888888888888888",
"url": "https://x.com/apify/status/1888888888888888888",
"verified": true,
"username": "@apify",
"fullname": "Apify",
"timestamp": "Mon Aug 03 09:15:00 +0000 2026",
"text": "New in the Store: scrape any X profile's follower list, not just the count.",
"links": ["https://apify.com/change-log"],
"isPinned": false,
"isQuote": false,
"isRetweet": false,
"isReply": false,
"likes": 412,
"replies": 18,
"retweets": 63,
"quotes": 5,
"views": 51200,
"user": {
"avatar": "https://pbs.twimg.com/profile_images/0000000000/apify.jpg",
"username": "apify",
"userFullName": "Apify",
"description": "Full-stack web scraping and browser automation platform.",
"location": "Prague, Czech Republic",
"website": "https://apify.com",
"joinDate": "Wed Sep 20 12:29:32 +0000 2017",
"verified": true,
"totalLikes": 1523,
"totalTweets": 4210,
"totalFollowing": 200,
"totalFollowers": 8540,
"url": "https://t.co/abcdef1234",
"userId": "3510729917",
"totalMediaCount": 812
},
"media": [],
"tweetUserId": "3510729917",
"retweetedFrom": null,
"originalTweetId": null,
"rowType": "tweet",
"sourceUsername": "@apify",
"sourceUserId": "3510729917",
"sourceProfileUrl": "https://x.com/apify",
"handle": "apify",
"profileUrl": "https://x.com/apify",
"timestampIso": "2026-08-03T09:15:00Z",
"userId": "3510729917",
"avatar": "https://pbs.twimg.com/profile_images/0000000000/apify.jpg",
"description": "Full-stack web scraping and browser automation platform.",
"location": "Prague, Czech Republic",
"website": "https://apify.com",
"websiteShortlink": "https://t.co/abcdef1234",
"joinDate": "Wed Sep 20 12:29:32 +0000 2017",
"joinDateIso": "2017-09-20T12:29:32Z",
"totalFollowers": 8540,
"totalFollowing": 200,
"totalTweets": 4210,
"totalMediaCount": 812,
"totalLikes": 1523,
"followerToFollowingRatio": 42.7,
"accountAgeDays": 3210
}

Output for a follower / following roster row

{
"rowType": "follower",
"sourceUsername": "@apify",
"sourceUserId": "3510729917",
"sourceProfileUrl": "https://x.com/apify",
"rosterRank": 1,
"username": "@datascout99",
"fullname": "Data Scout",
"verified": false,
"url": "https://x.com/datascout99",
"userId": "9081726354",
"followerToFollowingRatio": 0.6,
"accountAgeDays": 980,
"handle": "datascout99",
"profileUrl": "https://x.com/datascout99",
"avatar": "https://pbs.twimg.com/profile_images/0000000001/scout.jpg",
"description": "Building small tools for data people.",
"location": null,
"website": null,
"websiteShortlink": null,
"joinDate": "Tue Dec 04 03:11:09 +0000 2023",
"joinDateIso": "2023-12-04T03:11:09Z",
"verifiedType": null,
"protected": false,
"totalFollowers": 312,
"totalFollowing": 520,
"totalTweets": 891,
"totalMediaCount": 40,
"totalLikes": 2200,
"bannerUrl": null,
"professionalCategory": null,
"user": {
"avatar": "https://pbs.twimg.com/profile_images/0000000001/scout.jpg",
"username": "datascout99",
"userFullName": "Data Scout",
"description": "Building small tools for data people.",
"location": null,
"website": null,
"joinDate": "Tue Dec 04 03:11:09 +0000 2023",
"verified": false,
"totalLikes": 2200,
"totalTweets": 891,
"totalFollowing": 520,
"totalFollowers": 312,
"url": null,
"userId": "9081726354",
"totalMediaCount": 40
}
}

A following row carries the exact same shape, with rowType: "following".

Schema stability and export options

Field names are stable across runs and do not change when X updates its own front end โ€” this Actor reads X's internal GraphQL API directly rather than parsing rendered HTML, so a visual redesign on x.com does not affect the output shape. Where X drops a field for a given account (a private location, no bio, no verified type), the key is present with a null value rather than omitted or guessed. Results can be downloaded from the Apify Console or fetched through the Apify API/apify-client as JSON, CSV, Excel, XML or RSS, and pushed to any downstream system via the Apify integrations (webhooks, Zapier, Make, or direct API polling).


๐Ÿ’ก This X (Twitter) Scraper's Strategy Guide

๐ŸŽฏ Strategy 1: Real-time audience enrichment

Trigger a run from your app whenever a lead or contact record includes an X handle. Feed that handle into startUrls with getFollowers/getFollowing off and maxTweets at a small value like 5, then read back totalFollowers, verified, professionalCategory and the most recent text values from the tweet rows, and write them onto the lead record. Because the profile route needs no login, this path never touches your authToken/ct0 cookies.

๐ŸŽฏ Strategy 2: Scheduled follower monitoring

Set up an Apify schedule to re-run the same startUrls list weekly with rosterSortBy: "followersDesc". Diff each run's follower rows against the previous run's on userId to see who is new or gone, and diff the profile row's totalFollowers to catch the headline number moving. Alert on the accounts that appeared or disappeared, not on the raw count.

๐ŸŽฏ Strategy 3: Bulk audience dataset build

Pass a long startUrls list of target accounts in one run, with maxFollowers/maxFollowing set to the size roster you need and the two roster screens tuned to your quality bar. Export the resulting dataset โ€” profile rows and roster rows together, joined on sourceUserId โ€” to CSV or straight into a database via the Apify API for downstream analysis.

Strategy comparison at a glance

StrategyBest forRun patternOutput format
Real-time enrichmentCRM/lead enrichment on demandTriggered single-target runJSON row appended to your record
Scheduled monitoringTracking a competitor's or your own audience over timeApify schedule, same targets, diffed on userId/totalFollowersJSON dataset per run, diffed externally
Bulk dataset buildResearch or training datasetsOne run, many targets, roster caps tuned upfrontDataset export to CSV or database

ScraperWhat it extracts
Twitter X Tweets Scraper Scraper With Poll Results (Scrapio)Public X posts and the poll on each one โ€” options, vote counts, open/closed status
Reddit Subreddit Members Scraper With User Profiles (Scrapio)Active participants in a subreddit with a Reddit profile card โ€” post/comment karma, account age
TikTok Data Scraper: Comments, Replies & AI Sentiment (Scrapio)TikTok profiles, videos, followers and comments, with commenter-audience columns
LinkedIn Profile Posts Scraper With Engagement Analytics (Scrapio)LinkedIn profile posts with derived engagement rate, cadence and rank

How to integrate this X (Twitter) Scraper with your stack

This Actor works with any language or tool that can make an HTTP request โ€” it runs on the Apify platform, and you drive it with the Apify API or an official client library.

Python

from apify_client import ApifyClient
import csv
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run_input = {
"startUrls": ["https://x.com/apify", "@elonmusk"],
"getFollowers": True,
"getFollowing": False,
"maxFollowers": 200,
"maxTweets": 10,
"sortOrder": "newest",
"authToken": "<YOUR_X_AUTH_TOKEN_COOKIE>",
"ct0": "<YOUR_X_CT0_COOKIE>",
}
run = client.actor("scrapio/x-twitter-user-profile-and-tweets-scraper-with-follower-lists").call(
run_input=run_input
)
rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())
with open("x_export.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=sorted({k for row in rows for k in row}))
writer.writeheader()
for row in rows:
writer.writerow(row)
print(f"Exported {len(rows)} rows across {len({r['sourceUsername'] for r in rows})} profiles.")

Node.js

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('scrapio/x-twitter-user-profile-and-tweets-scraper-with-follower-lists').call({
startUrls: ['https://x.com/apify'],
getFollowers: true,
getFollowing: true,
maxFollowers: 100,
maxTweets: 10,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const followers = items.filter((row) => row.rowType === 'follower');
console.log(`${followers.length} follower rows collected.`);

Async and scheduled pipelines

For large target lists, start the run with the Apify API's async endpoint and poll run.status, or use an Apify webhook to get notified on ACTOR.RUN.SUCCEEDED instead of holding a connection open. For recurring audience monitoring, an Apify schedule re-runs the same input on a cron-style interval without any code on your side.


๐ŸŽฏ Who Needs This X (Twitter) Scraper? (Use Cases & Industries)

๐Ÿข Growth and influencer marketing teams

Build a shortlist of creator accounts, pull each one's follower roster with onlyVerifiedFollowers on, and hand the resulting handle list to outreach โ€” totalFollowers and professionalCategory on each roster row tell you which accounts are worth prioritizing before anyone opens a browser tab.

๐Ÿ“Š Growth and product analysts

Track totalFollowers, totalTweets and postsCollected for your own account and a set of competitors on a recurring schedule, and chart the trend externally โ€” the Actor's job is the per-run snapshot, not the trend line.

๐Ÿ“ฑ Competitive intelligence teams

Run the Actor against a competitor's account with the following roster on to see which accounts they follow โ€” often other brands, partners or influencers they're courting โ€” a signal not visible from the profile page alone.

๐Ÿ”ฌ Researchers

Public bios, follow relationships and post metadata support social-network and platform-behavior studies at a scale manual browsing can't reach; this Actor only reads what X shows to any logged-in viewer of a profile's follower/following list, never anything behind a private wall.

๐ŸŽฅ Product and SaaS builders

Audience-analytics and lead-enrichment products can run this Actor as a backend job, storing the profile and roster rows as the dataset behind a dashboard, keyed on sourceUserId.


Scraping publicly accessible data is generally lawful in the United States: in hiQ Labs, Inc. v. LinkedIn Corp., 938 F.3d 985 (9th Cir. 2019), the Ninth Circuit held that scraping data a website makes publicly available does not violate the Computer Fraud and Abuse Act. That precedent concerns public-data access, not X's own Terms of Service โ€” X's terms restrict automated data collection, and violating them is a contract/civil-law risk between you and X, not a criminal one.

This Actor also returns personal data โ€” names, handles, bios, locations and follow relationships tied to identifiable people โ€” so data protection law can apply depending on who you are and whose data you store. If you or your users are in the EU/EEA or California, GDPR and CCPA-style obligations around lawful basis, storage, and data-subject rights can attach to what you do with that data after collection; this Actor does not determine your lawful basis for you.

This Actor returns only publicly accessible data. What you do with that data is your responsibility โ€” consult legal counsel for commercial applications involving personal data.


โ“ Frequently asked questions

Does this X Scraper work without an X account?

Yes, for profiles and posts. Profile resolution and the post timeline run on a keyless guest session โ€” no login needed. The follower and following rosters are the exception: X serves those two lists only to a logged-in client, so they need your own authToken and ct0 cookies. Without them the run still succeeds and still returns the profile row and posts; the profile row reports rosterSkippedReason: "auth_required".

How does this Actor handle X's anti-scraping measures?

It uses Chrome TLS impersonation (curl_cffi) rather than a browser, discovers X's GraphQL query IDs live from X's own JS bundle each run (a hardcoded ID rotates and goes stale), self-heals when X adds a required feature flag mid-run, and backs off once on an HTTP 429 before retrying. Apify Residential Proxy is attached to every request by default because X answers datacenter IP ranges inconsistently.

Can I run this Actor at scale without getting blocked?

There is no uptime or success-rate guarantee โ€” this depends on X's own rate-limit bucket, which the Actor reports back via rateLimitRemaining and rateLimitHits on the profile row rather than hiding it. When the bucket runs out mid-roster, the run stops that roster, marks it followersTruncated: true (or the following equivalent), and moves on โ€” it does not fail the whole run.

How fresh is the data this Actor returns?

Live. Every run fetches directly from X's own GraphQL API at request time; nothing is cached or served from a prior run.

Is scraping a follower list a Terms of Service violation?

Possibly, depending on your use โ€” see "Is it legal to scrape X (Twitter)?" above. Scraping public data is not itself illegal under U.S. case law, but automated collection can conflict with X's own Terms of Service, which is a civil matter between you and X, not a law-enforcement one.

Which fields work best for AI training and RAG indexing?

For RAG, index description (the account bio) and text (post body) โ€” they're the dense, natural-language fields. For training data, totalFollowers, totalFollowing, accountAgeDays, verified and followerToFollowingRatio return as typed booleans, integers and pre-computed ratios, so no string parsing or unit normalization is needed before use.

Does the roster comply with GDPR or CCPA?

This Actor returns only what X already publishes to any logged-in viewer of a follower or following list โ€” it adds no data beyond that. Because the rows are personal data, the lawful basis for storing and using them sits with you, not with the Actor; consult counsel if you plan to use roster data for a commercial purpose involving EU or California residents.

Does this Actor work with Claude, ChatGPT, and other AI agent tools?

Yes, as an HTTP endpoint โ€” any agent framework that can call the Apify API can start a run and read back the dataset. Every row is typed JSON, so an agent can consume profile, tweet and roster rows directly into its context window without a parsing step.

What happens if a target account is protected, suspended, or doesn't exist?

If a handle doesn't resolve to a real account, the target is skipped with a logged reason and produces no row at all โ€” never a blank or guessed one. Accounts that appear inside a roster but are suspended or deactivated arrive from X as empty stubs; they're skipped from the roster and counted in unavailableAccountsSkipped on the profile row rather than pushed as incomplete rows.

How does this Actor compare to other X (Twitter) scrapers?

Against the base Twitter (X.com) Tweets & Profiles Scraper it's built on, this Actor adds the follower/following rosters, roster quality screens, and per-run rate-limit reporting โ€” the base returns profile and post data only. Against a hypothetical tool built on X's own official API, the tradeoff runs the other way: this Actor needs no developer application or paid API tier, but it depends on your own logged-in session cookies for the roster feature, and on X's GraphQL surface staying reachable the way it's implemented today.


โ„น๏ธ Disclaimer

This X (Twitter) Scraper extracts only publicly available data from X (Twitter) โ€” the same profile, post, and follower/following information visible to any logged-in viewer of a public account. This tool is intended for lawful use cases only. Users are responsible for complying with X's terms of service and applicable data protection laws in their jurisdiction.