# X (Twitter) Retweeters Scraper - Who Reposted a Post (`dami_studio/twitter-retweeters-scraper`) Actor

See who reposted (retweeted) an X (Twitter) post. Paste post links or ids and get one row per account: handle, name, bio, follower and following counts, posts, verification, location, website and join date, plus X's own repost count. $0.14 per 1,000 accounts.

- **URL**: https://apify.com/dami_studio/twitter-retweeters-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Social media, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.13 / 1,000 retweeters

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

**Paste links to X posts and get the accounts that reposted each one, as full profiles**: bio,
follower and following counts, post count, verification, location, website and join date, one row
per account. Every row also says which post it came from and how many reposts X counts on it.

The awkward part: X decides how much of a post's repost list it hands over, and the run stops where
X's list stops. Each row carries X's own count, so you can see straight away whether you got
everyone.

| | |
|---|---|
| **Input** | X post links, or just the post ids |
| **Output** | One full profile per account that reposted: handle, name, bio, followers, following, posts, verification type, location, website, join date, and the post's own repost count |
| **Ceiling** | 1,000 accounts per post, 50 posts and 5,000 accounts per run |
| **Account needed** | None from you |
| **Price** | $0.14 per 1,000 accounts, flat on every plan. The free plan's $5 a month covers about 35,000 |

### 🔍 What X (Twitter) Retweeters Scraper does

Each post gets a quick check first: does X still have it, and how many reposts does it count? A post
that was deleted, or that nobody reposted, ends there with a free labelled row, and its list is never
read.

Then the list itself is read page by page, 20 accounts at a time, until it reaches the number you
asked for or X's list runs out. An account shows up once per post, however many times X repeats it.
`position` is the account's place in the list as the run read it.

Reposts only. A quote post is a different list on X and is not in here.

### 📋 What data you get from each reposting account

| What you get | Field |
|---|---|
| The post this account reposted, and X's repost count on it | `tweetId`, `tweetUrl`, `tweetRetweetCount` |
| The account's place in X's list | `position` |
| X's numeric id, the handle, the display name and the profile link | `userId`, `userName`, `name`, `url` |
| The bio | `description` |
| Followers, following, posts, media posts and likes given | `followersCount`, `followingCount`, `tweetsCount`, `mediaCount`, `likesCount` |
| Whether there is a tick, and which kind | `isVerified`, `verifiedType` |
| Protected or not | `isProtected` |
| Location, website and join date | `location`, `website`, `createdAt` |
| The 400px avatar | `profileImageUrl` |
| When the row was read | `scrapedAt` |

### ▶️ How to scrape the retweeters of an X post

1. Open [X (Twitter) Retweeters Scraper](https://apify.com/dami_studio/twitter-retweeters-scraper)
   and click **Try for free**.
2. Paste post links into **Post links or IDs**, one per line.
3. Set **Max accounts per post**.
4. Click **Start**.
5. Download the dataset as JSON, CSV or Excel, or pull it from the Apify API.

Want to see the columns first? Start it with no links. You get one labelled sample row, and it is not
charged.

### 💰 How much does it cost to scrape X retweeters?

**$0.14 per 1,000 accounts.** Flat on every Apify plan, no volume tiers. On the free plan, the $5
Apify gives you each month covers about 35,000 accounts.

You pay for accounts delivered and nothing else. The sample row, every diagnostic row, a repeat of
an account already delivered for the same post, and accounts X lists but will not show are all free.
`maxItemsPerTweet` times the number of posts is the most a run can deliver, so keep it small while you
try things out.

### 📥 What you give it

```json
{
  "tweetUrls": [
    "https://x.com/NASA/status/2105417506991091764",
    "2106124556205252700"
  ],
  "maxItemsPerTweet": 200
}
```

| Field | Default | What it is |
|---|---|---|
| `tweetUrls` | none | Up to 50 posts, one per line. Links from x.com or twitter.com work, including ones with `/photo/1` or `?s=20` on the end, and so does the bare number. The form opens with one NASA post filled in. |
| `maxItemsPerTweet` | `100` | How many accounts to take from each post, 1 to 1,000. You pay per account, so this is your budget per post. |
| `sessionCookies` | none | Optional. Your own X account as `auth_token=...; ct0=...`, both halves. With it, the run reads with your account. Marked secret. |
| `proxyConfiguration` | none | Optional, and the form fills in Apify's default. Only change it to send the run through servers of your own. |

Anything in `tweetUrls` that is not a post link or id is skipped and listed in one free `BAD_INPUT`
row. If it looks like a pasted cookie, the row says so without repeating it.

### 📤 What you get back

One row, trimmed. Here @NASA is one of the accounts that reposted a post by @NASASpox:

```json
{
  "recordType": "retweeter",
  "tweetId": "2106124556205252700",
  "tweetUrl": "https://x.com/NASASpox/status/2106124556205252700",
  "tweetRetweetCount": 54,
  "userId": "11348282",
  "userName": "NASA",
  "name": "NASA",
  "url": "https://x.com/NASA",
  "description": "Making the seemingly impossible, possible.",
  "followersCount": 92378917,
  "followingCount": 115,
  "tweetsCount": 74372,
  "mediaCount": 28176,
  "likesCount": 17013,
  "isVerified": true,
  "verifiedType": "government",
  "isProtected": false,
  "location": "Pale Blue Dot",
  "website": "http://www.nasa.gov/",
  "profileImageUrl": "https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB_400x400.jpg",
  "createdAt": "2007-12-19T20:20:32.000Z"
}
```

| Field | How to read it |
|---|---|
| `tweetRetweetCount` | How many reposts X counted on that post when the run read it. Compare it with your row count. |
| `position` | The account's place in the list as the run read it, starting at 1. |
| `userId` | X's numeric id. It survives a handle change. |
| `verifiedType` | `blue`, `business` or `government`, and `null` with no tick. |
| `website` | Taken out of the `t.co` wrapper, so it is the real address. `null` when there is none. |
| `location` | Whatever the person typed as location, and `null` if blank. |
| `mediaCount`, `likesCount`, `verifiedType`, `isProtected`, `website` | Some rows have these five as `null` and the rest of the row as usual. There `null` means unknown, not zero or false. `isVerified` is always filled, so use it for the tick. |

### 🧾 Reading the output

Three kinds of row can land in your dataset.

| Row | How to spot it | Billed |
|---|---|---|
| An account | `recordType: "retweeter"` | yes |
| The sample row | `recordType: "sample"`, `_sample: true` | no |
| A post that could not be read | `recordType: "diagnostic"`, `_diagnostic: true`, an `errorCode` | no |

Filter on `recordType == "retweeter"` and you have your data. Free rows carry `charged: false`.

| Code | What it means |
|---|---|
| `NOT_FOUND` | X has no such post, or its account is private or suspended. |
| `NO_RESULTS` | X counts no reposts on the post, or listed nobody. |
| `RATE_LIMITED` | X asked the run to slow down. The row says when to try that post again. |
| `SESSION_REFUSED` | X turned down the cookie you gave. |
| `BLOCKED` | X did not hand over the list this time. |
| `NETWORK` | The connection failed while reading that post. |
| `BAD_INPUT` | Entries in `tweetUrls` that are not post links or ids. |
| `CHARGE_LIMIT`, `TIME_LIMIT`, `RUN_CAP` | The run stopped at your spending limit, its time limit or the run's cap. |
| `UNEXPECTED_ERROR` | Something broke inside the run. It is not charged. |

A post that stopped partway keeps the accounts it already delivered, and the row says how many. The
Output tab has a second view, **Posts that could not be read**, with the columns that explain a free
row: the code, what happened and what to do next.

### 💡 What people use it for

- You ran a "repost to enter" giveaway and want the entrants with their follower counts and join
  dates, so the throwaway accounts are easy to spot.
- A launch post took off and you want to know who carried it, sorted by `followersCount`.
- A post on your topic got traction, and the accounts that reposted it are a ready-made list of
  people who care about that subject.
- Dozens of brand-new accounts with a handful of followers reposting the same post is a pattern worth
  seeing in a spreadsheet; `createdAt` and `followersCount` show it.

From a viral post to what its biggest reposters say, in three steps:

1. Run this actor on the post's link.
2. Sort the rows by `followersCount` and copy the top `userName` values.
3. Put them into [Tweet Scraper](https://apify.com/dami_studio/tweet-scraper) as `twitterHandles` to
   read what each of those accounts posts.

### 🚧 What it does not do

- **No likes.** Since 2024 X shows who liked a post only to its author.
- **No quote posts.** Those are a separate list on X.
- **No repost times.** X's list does not say when each account reposted.
- **Only what X hands over.** On a big post the list can end before X's own count; the row count
  against `tweetRetweetCount` shows how far it got. Accounts X will not show are skipped, uncharged.
- **No emails or phone numbers.** Only what X puts on a public profile.
- **Limits:** 50 posts, 1,000 accounts per post and 5,000 accounts per run.

### 🧭 Which X scraper do you need?

| If you want | Use |
|---|---|
| Who reposted a post | This one |
| The accounts that follow a handle, or that it follows | [X (Twitter) Followers Scraper](https://apify.com/dami_studio/twitter-followers-scraper) |
| Tweets matching a keyword or an advanced search | [Twitter (X) Search Scraper](https://apify.com/dami_studio/twitter-search-scraper) |
| A profile's timeline, or single tweets by link | [Tweet Scraper](https://apify.com/dami_studio/tweet-scraper) |
| Follower counts, bio and verification for handles you already have | [Twitter Profile Scraper](https://apify.com/dami_studio/twitter-user-scraper) |
| Everything posted into a curated X list | [Twitter (X) List Scraper](https://apify.com/dami_studio/twitter-list-scraper) |

### ❓ Questions people ask

#### Do I need an X account or an API key to see who reposted a post?

No. The cookie field is optional and a normal run does not need it.

#### Why did I get fewer accounts than the repost count?

X decides how much of the list to show. Some accounts come back as "not available" instead of a
profile; those are skipped and not charged.

#### Can I get the accounts that liked a post?

No. X stopped showing that list to anyone but the post's author in 2024.

#### Does it post, like or follow anything?

No. It only reads.

#### Can I call it from code or connect it to an AI assistant?

Yes. The [API tab](https://apify.com/dami_studio/twitter-retweeters-scraper/api/python) has
ready-made code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP
client, connect `https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/twitter-retweeters-scraper`.
Either way the run happens on your Apify account at the same price.

#### Is scraping X legal?

This reads public profiles and public repost lists, 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](https://blog.apify.com/is-web-scraping-legal/) is a
good starting point, and we are not lawyers.

### 🆘 If something breaks

Open the **Issues** tab on the actor page. Include the post links you used and the run ID, and paste
any `errorCode` you got back, since that usually says what happened straight away.

# Actor input Schema

## `tweetUrls` (type: `array`):

The X posts whose reposters you want, one per line. A link such as https://x.com/NASA/status/2105417506991091764 works, from x.com or twitter.com, and so does the number at the end of it on its own. Up to 50 posts in one run.

## `maxItemsPerTweet` (type: `integer`):

Each post stops after this many accounts. Left empty, it is 100. Every account is one charged row, so this also caps what one post can cost you.

## `sessionCookies` (type: `array`):

Optional. Put your own X account's cookie here and the run reads with your account. In Chrome, signed in to x.com: press F12, open Application, then Cookies, then https://x.com, and copy the values of auth_token and ct0. Enter them as one line in a list, like \["auth_token=1a2b3c...; ct0=4d5e6f..."]. Use an account you own and may automate; a spare account is safer than your main one. The value is stored encrypted.

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

Optional. Leave this alone unless the run has to go out through your own proxy servers. Your own servers are used exactly as given.

## Actor input object example

```json
{
  "tweetUrls": [
    "https://x.com/NASA/status/2105417506991091764"
  ],
  "maxItemsPerTweet": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

The accounts that reposted each post, in the 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 = {
    "tweetUrls": [
        "https://x.com/NASA/status/2105417506991091764"
    ],
    "maxItemsPerTweet": 100,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/twitter-retweeters-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 = {
    "tweetUrls": ["https://x.com/NASA/status/2105417506991091764"],
    "maxItemsPerTweet": 100,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/twitter-retweeters-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 '{
  "tweetUrls": [
    "https://x.com/NASA/status/2105417506991091764"
  ],
  "maxItemsPerTweet": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call dami_studio/twitter-retweeters-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/twitter-retweeters-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/NKsneMc7kB4D9Gsg5/builds/kKNtovtHC7nfdHncx/openapi.json
