Twitter Profile Scraper With Engagement Analytics
Pricing
Pay per usage
Twitter Profile Scraper With Engagement Analytics
Scrape detailed user data from X (Twitter) with the Twitter Profile Scraper. Extract bios, follower counts, following, tweets, media, verification status, and engagement stats from any public profile. Perfect for influencer analysis, research, and monitoring. Fast, accurate, and scalable.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Scrapier
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
0
Monthly active users
19 hours ago
Last modified
Categories
Share
Twitter Profile Scraper — Tweets, Engagement Rate and Virality Score
Twitter Profile Scraper With Engagement Analytics pulls tweets, replies, and profile stats from any public Twitter/X profile URL or handle, then scores every tweet for engagement rate, virality velocity, and percentile rank against that profile's other captured tweets — plus a profile-level rollup of posting cadence, best posting hour and day, top hashtags, and media mix. Every response is structured JSON, ready to feed straight into an LLM, a spreadsheet, or a monitoring pipeline. No Twitter/X login is required to run it.
What is Twitter Profile Scraper With Engagement Analytics?
Twitter Profile Scraper With Engagement Analytics is a profile-and-tweet scraper that takes a list of Twitter/X profile URLs or handles and returns each profile's tweets already scored for engagement rate, virality score, and rank — computed entirely from fields the scraper already fetches, with zero extra requests. No Twitter/X account is required for tweets, profile stats, or the analytics rollup; login cookies (auth_token and ct0) are only needed if you turn on reply fetching. Results are written to an Apify dataset as normalized JSON rows, one per tweet, reply, profile snapshot, or rollup record.
- Track any number of public profiles by URL or bare handle in one run
- Computes
engagementRate,viralityScore, andengagementRankPercentileper tweet, no extra API calls - Rolls up each profile into posting cadence, best posting hour/day, top hashtags, and media-type mix
- Filters tweets by date range, native retweets, and photo-only content
- Optional profile snapshot record with follower/following/bio stats flattened to top-level columns
- Optional reply engagement fetching, gated behind your own login cookies
What data can you get with Twitter Profile Scraper With Engagement Analytics?
The actor writes four kinds of dataset rows, distinguished by their type field: tweets, replies, profile snapshots, and analytics rollups.
| Result Type | Extracted Fields | Primary Use Case |
|---|---|---|
Tweet (type: "tweet") | id_str, full_text, created_at, tweetUrl, screen_name, favorite_count, retweet_count, reply_count, quote_count, bookmark_count, views_count, possibly_sensitive, engagementCount, engagementRate, viralityScore, engagementRankPercentile, user, user_id_str, conversation_id_str, entities, extended_entities, lang, is_quote_status, favorited, retweeted, bookmarked, display_text_range, scrapedAt | Per-tweet performance analysis and ranking |
Reply (type: "reply") | Same fields as Tweet, plus isReply: true, parentTweetId; engagementRankPercentile is null since replies aren't ranked against the parent profile's tweet pool | Conversation and reply-engagement analysis |
Profile Snapshot (type: "profileSnapshot") | screen_name, followersCount, followingCount, tweetsCount, favouritesCount, listedCount, accountCreatedAt, verified, isBlueVerified, location, bio, profileImageUrl, profileBannerUrl, user (raw object) | Account-level growth and identity tracking |
Analytics Rollup (type: "analyticsRollup") | screen_name, basedOnCapturedTweets, avgEngagementPerTweet, postingCadencePerDay, bestPostingHourUTC, bestPostingDayOfWeek, topHashtags, mediaTypeBreakdown, scrapedAt | Posting-strategy and content-mix research |
Engagement, virality and ranking analytics
This is the layer other tweet scrapers skip: raw favorite_count/retweet_count/reply_count/quote_count are real, but they don't tell you whether a tweet performed well for that account or for its age. This actor computes three additional fields per tweet, purely from data it has already fetched: engagementRate (engagementCount ÷ followers_count × 100, so accounts of different sizes are comparable), viralityScore (engagementCount ÷ tweet-age-in-hours, a velocity signal that surfaces tweets gaining traction fast rather than tweets that are simply old), and engagementRankPercentile (this tweet's percentile rank among the tweets captured for that profile in this run). A profile-level analyticsRollup record adds posting cadence, best posting hour/day, top hashtags, and media mix — always labeled basedOnCapturedTweets so it reads as a run-sample statistic, never a lifetime claim.
{"id_str": "1519480761749016577","engagementCount": 5220762,"engagementRate": 2280.9,"viralityScore": 41552.1,"engagementRankPercentile": 96.0}
Profile Snapshot
Turning on emitProfileSnapshot adds one extra row per profile with follower count, following count, tweet count, favourites count, listed count, account creation date, verification status, bio, and profile image/banner URLs — flattened onto top-level dataset columns instead of buried in a nested user object. It's the fastest way to pull current account-size stats (followersCount, tweetsCount) alongside the tweet-level analytics, without a second run against a dedicated profile-info actor.
How does Twitter Profile Scraper With Engagement Analytics differ from the official X (Twitter) API?
The official X API returns raw public_metrics counts per tweet; this actor returns those same counts plus computed engagement rate, virality score, and percentile rank, with no developer account required for that layer.
| Feature | X API (Official) | This Actor |
|---|---|---|
| Access requirement | Developer account, app registration, and API keys | Profile URL or handle — no account needed for tweets/profile/analytics |
| Pricing structure | Paid access tiers (Free/Basic/Pro) with monthly read/post caps, in place since the 2023 pricing overhaul | Billed per Apify run; no platform-imposed subscription tier |
| Computed engagement analytics | Raw public_metrics (like/retweet/reply/quote counts) only | Adds engagementRate, viralityScore, engagementRankPercentile, and a profile-level rollup |
| Output shape | Tweet, user, and metrics objects joined via expansions parameters | Already flattened into one row per tweet |
| Reply access | Requires elevated access and separate conversation endpoints | Built in via fetchEngagementReplies, gated by your own login cookies |
| Setup complexity | OAuth, endpoint versioning, developer portal approval | Add a profile URL/handle and run |
The official API is the right choice when you're building a product with X's contractual backing and need guaranteed terms of service. This actor is the faster path when you need engagement analytics on public profiles without a developer approval process.
How to scrape X (Twitter) with Twitter Profile Scraper With Engagement Analytics?
- Open Twitter Profile Scraper With Engagement Analytics on the Apify platform.
- Enter one or more profile URLs in
profilesToTrack, or bare usernames inhandlesToTrack— at least one of the two is needed for the run to return data. - Optionally set
metricsStartDate/metricsEndDate,countNativeRetweets, andrequirePhotoMediato scope which tweets get scored. - Start the run.
- Read or download the results as JSON, CSV, or any format the Apify dataset export supports.
{"profilesToTrack": ["https://x.com/elonmusk"],"maxTweetsToScore": 50,"emitAnalyticsRollup": true}
How to score multiple profiles in one run
Add multiple entries to profilesToTrack and/or handlesToTrack — the actor works through them one at a time, in the order given, and every profile shares a single maxTweetsToScore budget for the whole run: once that cap is reached, remaining profiles are skipped. Mixing URLs and handles in the same run is supported.
⬇️ Input
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
profilesToTrack | No | array | Profile URLs to score. Required if handlesToTrack is empty. (Also accepts startUrls.) | ["https://x.com/elonmusk"] |
handlesToTrack | No | array | Usernames without @. Required if profilesToTrack is empty. (Also accepts twitterHandles.) | ["elonmusk"] |
maxTweetsToScore | No | integer | Hard cap on total items (tweets/replies/profile snapshots) written across the whole run. (Also accepts maxItems.) | 50 |
metricsStartDate | No | string | Lower bound for tweet date — absolute (YYYY-MM-DD) or relative (e.g. 7 days). Empty = no lower bound. (Also accepts start.) | 7 days |
metricsEndDate | No | string | Upper bound for tweet date — absolute or relative. Empty = no upper bound. (Also accepts end.) | 1 day |
countNativeRetweets | No | boolean | When off, native retweets (full_text starting with RT @) are excluded from scoring. Only effective for the last ~7-10 days. (Also accepts includeNativeRetweets.) | false |
requirePhotoMedia | No | boolean | Keep only tweets containing at least one photo. (Also accepts onlyImages.) | false |
emitProfileSnapshot | No | boolean | Emit one profile-snapshot record per user with stats flattened to top-level columns. (Also accepts getAboutData.) | true |
emitAnalyticsRollup | No | boolean | Default true. Emits one analyticsRollup record per profile. | true |
fetchEngagementReplies | No | boolean | Fetch replies via the TweetDetail endpoint. Requires login cookies. (Also accepts getReplies.) | false |
minReplyEngagement | No | integer | Only fetch replies for tweets whose reply_count is at least this value. (Also accepts minReplyCount.) | 5 |
loginAuthToken | No | string | Value of the auth_token cookie from x.com. Required only for fetchEngagementReplies. (Also accepts authToken.) | "" |
loginCsrfToken | No | string | Value of the ct0 cookie from x.com. Required only for fetchEngagementReplies. (Also accepts csrfToken.) | "" |
proxyConfiguration | No | object | Apify Proxy configuration. Recommended for reliability against rate limits. | {"useApifyProxy": false} |
{"profilesToTrack": ["https://x.com/elonmusk"],"handlesToTrack": ["openai"],"maxTweetsToScore": 100,"metricsStartDate": "7 days","countNativeRetweets": false,"emitProfileSnapshot": true,"emitAnalyticsRollup": true,"fetchEngagementReplies": false,"proxyConfiguration": { "useApifyProxy": true }}
No parameter is schema-required, but the run produces nothing without at least one entry in profilesToTrack or handlesToTrack. The more common pitfall: turning on fetchEngagementReplies without also supplying both loginAuthToken and loginCsrfToken doesn't error — the actor logs a notice and silently skips reply fetching for the whole run.
⬆️ Output
Results are written to the Apify dataset as normalized JSON rows in real time, one row per tweet, reply, profile snapshot, or analytics rollup, exportable as JSON, CSV, Excel, or any other format the Apify dataset export supports.
Scraped results
[{"id_str": "1519480761749016577","type": "tweet","isChild": false,"full_text": "Next I'm buying Coca-Cola to put the cocaine back in","created_at": "Thu Apr 28 00:56:58 +0000 2022","tweetUrl": "https://x.com/elonmusk/status/1519480761749016577","screen_name": "elonmusk","favorite_count": 4289223,"retweet_count": 594435,"reply_count": 170050,"quote_count": 167104,"views_count": 128340213,"possibly_sensitive": false,"engagementCount": 5220762,"engagementRate": 2280.9,"viralityScore": 41552.1,"engagementRankPercentile": 96.0,"scrapedAt": "2026-07-25T12:00:00Z"},{"id_str": "1519481009238016578","type": "reply","isChild": true,"isReply": true,"parentTweetId": "1519480761749016577","full_text": "This aged well.","created_at": "Thu Apr 28 01:10:04 +0000 2022","screen_name": "some_user","favorite_count": 812,"retweet_count": 40,"reply_count": 6,"quote_count": 1,"engagementCount": 859,"engagementRate": 4.3,"viralityScore": 6.9,"engagementRankPercentile": null,"scrapedAt": "2026-07-25T12:00:00Z"},{"type": "profileSnapshot","isChild": false,"screen_name": "elonmusk","followersCount": 221000000,"followingCount": 900,"tweetsCount": 45000,"favouritesCount": 78000,"listedCount": 155000,"accountCreatedAt": "Tue Jun 02 20:12:29 +0000 2009","verified": true,"isBlueVerified": true,"location": "Austin, Texas","bio": "Mars, Cars, Chips, Rockets, AI, X","scrapedAt": "2026-07-25T12:00:00Z"},{"type": "analyticsRollup","screen_name": "elonmusk","basedOnCapturedTweets": 50,"avgEngagementPerTweet": 812345.2,"postingCadencePerDay": 6.4,"bestPostingHourUTC": 14,"bestPostingDayOfWeek": "Wednesday","topHashtags": [{ "tag": "ai", "count": 4 }],"mediaTypeBreakdown": { "photo": 12, "video": 5, "gif": 1, "none": 32 },"scrapedAt": "2026-07-25T12:00:00Z"}]
How can I use the data extracted with Twitter Profile Scraper With Engagement Analytics?
- Growth and competitor tracking: compare
engagementRateandviralityScoreacross your account and competitors' accounts, sized-adjusted rather than raw like counts, to see who's actually performing better per follower. - Social listening: feed
full_text,entities, andengagementCountinto a monitoring pipeline to catch spikes in engagement on a tracked profile the moment they're captured in a run. - AI engineers and LLM developers: have an agent query a profile, receive structured JSON with pre-computed engagement metrics, and pass it as grounded context instead of asking the model to estimate performance from raw counts.
- Research and content strategy: use the
analyticsRollupfields —bestPostingHourUTC,bestPostingDayOfWeek,topHashtags,mediaTypeBreakdown— to study posting patterns behind high-performing accounts.
How do you monitor engagement analytics over time?
Engagement monitoring means running the same profile list on a recurring schedule and diffing the analytics fields between runs, rather than reading a single snapshot. Each run recomputes engagementRate, viralityScore, and engagementRankPercentile from whatever tweets are captured in that run, and the analyticsRollup record's basedOnCapturedTweets always states the exact sample size behind avgEngagementPerTweet, postingCadencePerDay, bestPostingHourUTC, and bestPostingDayOfWeek — so a change between runs is a real change in that sample, not noise from a shifting baseline.
The fields worth diffing run-over-run are engagementRate and viralityScore per tweet (is a tweet still gaining engagement relative to its age, or has it plateaued), engagementRankPercentile (is a new tweet outperforming the rest of the profile's recent output), and the rollup's bestPostingHourUTC/bestPostingDayOfWeek/topHashtags (has the account's best-performing posting pattern shifted). A practical workflow: schedule a run across your tracked profiles every few hours or daily, store each run's analyticsRollup row, compare it to the previous run's, and alert when avgEngagementPerTweet or bestPostingHourUTC moves outside your expected range.
Use Apify's built-in Scheduler to trigger runs on a recurring cadence, and pair it with a dataset webhook or downstream script to fetch the new results and perform the comparison after each run. Because every row carries scrapedAt, you can also keep every historical run's dataset and reconstruct the full trend line for a profile instead of only comparing the two most recent runs.
Integrate Twitter Profile Scraper With Engagement Analytics and automate your workflow
Twitter Profile Scraper With Engagement Analytics works with any language or tool that can send an HTTP request, using the standard Apify API.
REST API with Python
import requestsTOKEN = "YOUR_APIFY_TOKEN"ACTOR = "Scrapier~twitter-profile-scraper-with-engagement-analytics"url = f"https://api.apify.com/v2/acts/{ACTOR}/run-sync-get-dataset-items?token={TOKEN}"payload = {"profilesToTrack": ["https://x.com/elonmusk"],"maxTweetsToScore": 50,"emitAnalyticsRollup": True,}resp = requests.post(url, json=payload, timeout=180)rows = resp.json()tweets = [r for r in rows if r.get("type") == "tweet"]print(f"Scored {len(tweets)} tweets")
Scheduled monitoring and delivery
Use Apify's Scheduler to run this actor on a recurring cadence against a fixed profile list, and configure a dataset webhook to push new results (or trigger a downstream job) as soon as each run finishes — there is no polling required beyond what the webhook already delivers.
Is it legal to scrape X (Twitter) profiles?
Yes — scraping publicly visible Twitter/X profile and tweet data is generally permitted; this actor returns only what any logged-out visitor to a public profile can already see. Profile data (bio, follower counts, tweet content, account creation date) is personal data under GDPR and CCPA when it relates to an identifiable person, so storing or reusing it in bulk — especially for EU or California residents — should follow those frameworks' rules on lawful basis, retention, and data-subject rights. Scraping for one-off research or monitoring carries a different risk profile than scraping for bulk AI training or resale, and X's own Terms of Service govern acceptable use of its platform regardless of jurisdiction. Consult your legal team for commercial use cases involving bulk data storage.
Frequently asked questions
How is engagement analytics actually calculated?
engagementRate is engagementCount ÷ followers_count × 100, where engagementCount sums likes, retweets, replies, and quotes — it's null when follower count is unavailable, never faked as zero. viralityScore is engagementCount ÷ tweet-age-in-hours, a velocity signal. engagementRankPercentile ranks a tweet against the other tweets captured for that profile in the same run. All three are computed from fields already fetched — no extra requests.
Do I need Twitter/X login cookies to use this actor?
No, not for tweets, profile snapshots, or analytics — those work fully logged out. Login cookies (loginAuthToken/loginCsrfToken) are only required if you enable fetchEngagementReplies.
How many tweets does it return per profile?
Up to maxTweetsToScore total items across the whole run (tweets, replies, and profile snapshots combined) — there's no separate per-profile default in the schema; if you don't set it, the actor defaults to 100 for the run.
Can I filter by date range?
Yes — metricsStartDate and metricsEndDate accept either an absolute YYYY-MM-DD date or a relative value like 7 days, bounding which tweets get scored and pushed.
Does engagementRankPercentile reflect a tweet's lifetime rank?
No — only its rank among the tweets captured for that profile in the current run, bounded by maxTweetsToScore and any date filters. The analyticsRollup record's basedOnCapturedTweets field states the exact sample size so it's never mistaken for lifetime stats.
How do I monitor a profile's engagement over time?
Schedule a recurring run across your tracked profiles, store each run's tweet and analyticsRollup rows, and diff engagementRate, viralityScore, and bestPostingHourUTC/bestPostingDayOfWeek against the previous run to catch shifts in performance or posting pattern.
Does it handle X's anti-bot measures?
It discovers X's current GraphQL query IDs and bearer token directly from the site's own client JavaScript at run time rather than hardcoding them, and falls back to a guest token when no login cookies are supplied, so it keeps working as X rotates its internal configuration.
Does this actor work with Claude, ChatGPT, and AI agent frameworks?
Yes — it's callable as a standard HTTP endpoint from any agent framework, so an agent can request a profile's tweets with pre-computed engagement metrics and ground its answer in that structured JSON instead of estimating performance from memory.
Can I score multiple profiles without managing proxies or credentials?
Yes for profiles, tweets, and analytics — the actor handles endpoint discovery and guest-token sessions itself; you only need to supply a proxyConfiguration if you want Apify Proxy for reliability, and login cookies only if you turn on reply fetching.
Your feedback
Found a bug or missing a field? Let us know through the actor's Issues tab on the Apify Store so we can take a look. Feedback on which engagement or analytics fields would be useful to add is also welcome.