# Twitter Profile Scraper With Engagement Analytics (`scrapier/twitter-profile-scraper`) Actor

Twitter Profile Scraper with Engagement Analytics: Extract X profile data, bios, followers, following, posts, likes, views, and engagement metrics. Analyze creator performance, compare accounts, research audiences, monitor competitors, and build structured datasets for social media analytics.

- **URL**: https://apify.com/scrapier/twitter-profile-scraper.md
- **Developed by:** [Scrapier](https://apify.com/scrapier) (community)
- **Categories:** Automation, Lead generation, Social media
- **Stats:** 3 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### 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`, and `engagementRankPercentile` per 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.

```json
{
  "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?

1. Open Twitter Profile Scraper With Engagement Analytics on the Apify platform.
2. Enter one or more profile URLs in `profilesToTrack`, or bare usernames in `handlesToTrack` — at least one of the two is needed for the run to return data.
3. Optionally set `metricsStartDate`/`metricsEndDate`, `countNativeRetweets`, and `requirePhotoMedia` to scope which tweets get scored.
4. Start the run.
5. Read or download the results as JSON, CSV, or any format the Apify dataset export supports.

```json
{
  "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}` |

```json
{
  "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

```json
[
  {
    "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 `engagementRate` and `viralityScore` across 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`, and `engagementCount` into 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 `analyticsRollup` fields — `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

```python
import requests

TOKEN = "YOUR_APIFY_TOKEN"
ACTOR = "Scrapier~twitter-profile-scraper-with-engagement-analytics"
url = f"https://api.apify.com/v2/acts/%7BACTOR%7D/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.

# Actor input Schema

## `profilesToTrack` (type: `array`):

List of Twitter/X profile URLs to score (e.g., https://x.com/elonmusk). Required if handlesToTrack is empty. (Also accepts the base actor's `startUrls` key.)

## `handlesToTrack` (type: `array`):

List of usernames without the @ (e.g., elonmusk). Required if profilesToTrack is empty. (Also accepts the base actor's `twitterHandles` key.)

## `maxTweetsToScore` (type: `integer`):

Hard cap on total items (tweets/replies/profile snapshots) written across the whole run. Example: 50. (Also accepts the base actor's `maxItems` key.)

## `metricsStartDate` (type: `string`):

Lower bound for tweet date. Absolute date (YYYY-MM-DD) or relative value (e.g., 7 days). Empty = no lower bound. (Also accepts the base actor's `start` key.)

## `metricsEndDate` (type: `string`):

Upper bound for tweet date. Absolute date (YYYY-MM-DD) or relative value (e.g., 1 day). Empty = no upper bound. (Also accepts the base actor's `end` key.)

## `countNativeRetweets` (type: `boolean`):

When off, native retweets (full\_text starts with 'RT @') are excluded from scoring. Only effective for the last ~7-10 days. (Also accepts the base actor's `includeNativeRetweets` key.)

## `requirePhotoMedia` (type: `boolean`):

Keep only tweets that contain at least one photo. (Also accepts the base actor's `onlyImages` key.)

## `emitProfileSnapshot` (type: `boolean`):

Emit one profile-snapshot record per user, with follower/following/tweet-count stats flattened onto top-level columns (visible in the output table, not buried in a raw object). (Also accepts the base actor's `getAboutData` key.)

## `emitAnalyticsRollup` (type: `boolean`):

On by default. Emits one analyticsRollup record per profile: avgEngagementPerTweet, postingCadencePerDay, bestPostingHourUTC, bestPostingDayOfWeek, topHashtags, mediaTypeBreakdown. Always labeled basedOnCapturedTweets:N — this run's captured sample, never lifetime stats.

## `fetchEngagementReplies` (type: `boolean`):

Fetch replies to each qualifying tweet via the TweetDetail endpoint. Requires login cookies. (Also accepts the base actor's `getReplies` key.)

## `minReplyEngagement` (type: `integer`):

Only fetch replies for tweets whose reply\_count is at least this value. (Also accepts the base actor's `minReplyCount` key.)

## `loginAuthToken` (type: `string`):

Value of the `auth_token` cookie from x.com (devtools → Application → Cookies). Required only for fetchEngagementReplies. (Also accepts the base actor's `authToken` key.)

## `loginCsrfToken` (type: `string`):

Value of the `ct0` cookie from x.com. Required only for fetchEngagementReplies. (Also accepts the base actor's `csrfToken` key.)

## `proxyConfiguration` (type: `object`):

Apify proxy configuration. Recommended for reliability against rate limits.

## Actor input object example

```json
{
  "profilesToTrack": [
    "https://x.com/elonmusk"
  ],
  "emitAnalyticsRollup": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped items in the Actor's default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "profilesToTrack": [
        "https://x.com/elonmusk"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapier/twitter-profile-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "profilesToTrack": ["https://x.com/elonmusk"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapier/twitter-profile-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "profilesToTrack": [
    "https://x.com/elonmusk"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call scrapier/twitter-profile-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapier/twitter-profile-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/OevTlVmhBKUPQJeyx/builds/i1vEHrMN8lTDWZbPm/openapi.json
