# X (Twitter) Likes and Reposts Scraper | $0.12/1K | Per Account (`feedminer/x-signals-scraper`) Actor

See what an X (Twitter) account reacts to, not what it publishes. Export the posts it reposted, replied to or liked, each with the original author and full engagement metrics. The intent signal a timeline never shows, for lead scoring and account research. JSON, CSV or Excel. By FeedMiner.

- **URL**: https://apify.com/feedminer/x-signals-scraper.md
- **Developed by:** [FeedMiner](https://apify.com/feedminer) (community)
- **Categories:** Social media, Lead generation, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.10 / 1,000 post returneds

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?

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

<div style="border-left:4px solid #1D9BF0;background:#F2F9FF;padding:14px 18px;border-radius:6px">
<strong>See what an X (Twitter) account reacts to, not what it publishes.</strong> The posts it reposted, the posts it replied to, the posts it liked. Each with its own author and engagement metrics. The intent signal a timeline never shows.
</div>

🧭 **Reactions beat broadcasts.** A prospect's own timeline is marketing. What they repost at 11pm is what they actually care about, and that is what this exports.

💸 **$0.12 per 1,000 posts, down to $0.10 on the larger Apify plans.** No start fee, and a run that returns nothing costs nothing.

🔗 **Full posts, not just links.** Every row is the reposted or answered post itself, with its text, its original author and its engagement, so the export reads without a second lookup.

🧾 **Honest about the likes tab.** X made likes private by default in 2024. When a likes run comes back empty, the message says the account keeps its likes private rather than blaming your credentials.

#### Copy to your AI assistant

```
feedminer/x-signals-scraper on Apify. Exports what X (Twitter) accounts react to: reposts, replies, likes. One row per post with account (whose signal), signal (reposts|replies|likes), text, url, createdAt, engagement counts and the original author. Call ApifyClient("TOKEN").actor("feedminer/x-signals-scraper").call(run_input={...}), then client.dataset(run["defaultDatasetId"]).list_items().items. Input: handles (string[]), signals (string[] of reposts|replies|likes), maxItems (int), sessions (array, optional). Note X made third party likes private in 2024, so the likes surface can legitimately return nothing. Full spec: GET https://api.apify.com/v2/acts/feedminer~x-signals-scraper/builds/default (Bearer TOKEN) → inputSchema, actorDefinition.storages.dataset, readme. Token: https://console.apify.com/account/integrations
```

***

### <img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/hoZ24gXinDHziMQKm-actor-3hbiY2nfMGfbNdh1w-DUuuMSYQpE-IMG_9471.jpeg" width="26" height="26" style="vertical-align:-4px;border-radius:6px"/> How to scrape what an X (Twitter) account reacts to

##### Basic: what a prospect reposts

```json
{ "handles": ["paulg"], "signals": ["reposts"], "maxItems": 200 }
```

##### Who they talk to

```json
{ "handles": ["paulg"], "signals": ["replies"], "maxItems": 300 }
```

Replies show the accounts a person actually converses with, which is a relationship map their following list only hints at.

##### Both signals for a shortlist of prospects

```json
{
  "handles": ["ceo1", "ceo2", "ceo3"],
  "signals": ["reposts", "replies"],
  "maxItems": 3000
}
```

##### Try the likes tab

```json
{ "handles": ["someaccount"], "signals": ["likes"], "maxItems": 200 }
```

Some accounts still expose it. When one does not, the run says so for that account and keeps going with the rest.

***

### Input parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `handles` | array |  | Accounts to read, as handles or profile URLs |
| `signals` | array | `['reposts']` | Reposts and replies are the reliable ones. X made the likes tab private in 2024, so likes often come back empty even with an account |
| `maxItems` | integer | `1000` | Stop once this many posts have been collected |

**Advanced**

| Parameter | Type | Default | Description |
|---|---|---|---|
| `sessions` | array |  | Optional. The Actor works without one. X accounts of your own, for anyone who would rather the run used accounts they control |
| `debugMode` | boolean | `false` | Verbose logs for support |

#### Nothing to connect

Paste handles and press Start. There is no account to create, no cookie to copy and nothing to keep alive on your side.

If you would rather the run worked from accounts you own, the optional `sessions` field takes them. Several can be given at once and the work spreads across them.

#### About the likes tab

X made the likes of an account private by default in 2024. A likes run can therefore come back empty for an account that simply keeps them private, which is not a failure and not a credential problem. The run says which account produced nothing and why. Reposts and replies are unaffected.

***

### What data can you extract?

| Field | Type | Description |
|---|---|---|
| `account` | string | Whose signal this is, the handle you asked for |
| `signal` | string | `reposts`, `replies` or `likes` |
| `text` | string | The post text |
| `url` | string | Direct link to the post |
| `createdAt` | string | Publication date, RFC 3339 |
| `lang` | string | Language X detected |
| `likeCount` `retweetCount` `replyCount` `quoteCount` `viewCount` | integer | Engagement on the post |
| `isReply` `isQuote` `isRetweet` | boolean | What kind of post this is |
| `inReplyToUsername` | string | Who is being answered, on a reply |
| `author` | object | The original author: handle, name, bio, followers, verification |
| `hashtags` `mentions` `links` `media` | array | Entities in the post |

***

### Pricing: Pay Per Event (PPE)

| Event | Price |
|---|---|
| Post returned | $0.00012 |

That is **$0.12 per 1,000 posts**, with no start fee and no charge for a run that returns nothing. The price steps down on its own for the larger Apify plans, to $0.11 and then $0.10 per 1,000.

***

##### What a run costs

| | |
|---|---|
| One prospect's reposts, 200 posts | $0.024 |
| A hundred prospects, 20,000 posts | $2.40 |

##### Free tier

The Apify free plan includes $5 of usage every month, which is roughly 41,000 posts here. No card required.

### Advanced usage

**Qualify a lead list.** Feed a hundred prospect handles, pull their reposts, and count how many amplified a competitor. That column ranks the list better than firmographics.

**Map a relationship graph.** `replies` plus `inReplyToUsername` gives the accounts a person actually engages with, which is where warm introductions come from.

**Track a topic through people.** The posts a set of accounts repost, grouped by the original author, shows who the category listens to.

**Time it.** `createdAt` on the reacted post plus the account's own posting hours tells you when a prospect is on X, which is when your outreach lands.

**Watch a shift.** Run the same handles monthly and compare which authors they amplify. A change in who someone reposts is often the first sign of a change in what they buy.

***

### Integrate X reaction data into your stack

**Python**

```python
from apify_client import ApifyClient
from collections import Counter

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("feedminer/x-signals-scraper").call(run_input={
    "handles": ["ceo1", "ceo2", "ceo3"],
    "signals": ["reposts"],
    "maxItems": 2000,
})

rows = client.dataset(run["defaultDatasetId"]).list_items().items
print(Counter(r["author"]["userName"] for r in rows).most_common(10))
```

**JavaScript**

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('feedminer/x-signals-scraper').call({
    handles: ['paulg'],
    signals: ['replies'],
    maxItems: 300,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const talksTo = new Set(items.map((i) => i.inReplyToUsername).filter(Boolean));
```

**No code**

Send rows to Google Sheets, Airtable, Slack, Zapier, Make or n8n from the Integrations tab of the run.

***

### Performance

| Measure | Value |
|---|---|
| Parallelism | One worker per account supplied, up to eight |
| Partial results | Kept and delivered when a limit is reached |

***

### FAQ

**Do I need an X account?**
No. Paste handles and press Start. The optional `sessions` field is there for anyone who would rather run on accounts they own.

**Why did the likes come back empty?**
Because that account keeps its likes private, which X now does by default. The run tells you which account, and reposts and replies still work.

**Is my account at risk?**
The run reads at browsing pace, one page at a time, and steps back as soon as X pushes back. Use a secondary account, as you would with any third party tool.

**How far back does it go?**
As deep as X paginates the timeline, newest first, up to your `maxItems`.

**Do I get the original author of a repost?**
Yes, `author` is the author of the reposted post, and `account` is the one who reposted it.

**Can I tell a quote from a plain repost?**
Yes, `isQuote` and `isRetweet` are on every row.

**Can I run this on hundreds of handles?**
Yes. Give several accounts in `sessions` so the work spreads, and raise `maxItems` to match.

**What if a handle does not exist?**
It is reported and skipped, and everything else in the run is delivered.

***

### Support

An account that returns nothing, a signal you need, a shape that does not fit your pipeline: write from the actor page.

***

### Legal compliance

This actor reads timelines that X publishes on public profiles. It does not access private accounts, protected posts or direct messages. Personal data in the output is subject to GDPR, CCPA and similar regimes: collect what you have a lawful basis to collect, keep it only as long as you need it, and honour deletion requests.

***

**FeedMiner** · Fast, honestly priced scrapers, kept alive when platforms change.

[X Tweet Scraper](https://apify.com/feedminer/x-tweet-scraper) · [X Profile Scraper](https://apify.com/feedminer/x-profile-scraper) · [X Follower Scraper](https://apify.com/feedminer/x-follower-scraper) · [X Advanced Search Scraper](https://apify.com/feedminer/x-advanced-search-scraper) · [X Media Scraper](https://apify.com/feedminer/x-media-scraper) · [X Mentions Monitor](https://apify.com/feedminer/x-mentions-scraper) · [X Engagement Scraper](https://apify.com/feedminer/x-engagement-scraper) · X Likes and Reposts Scraper · [X Trends Scraper](https://apify.com/feedminer/x-trends-scraper) · [All FeedMiner Actors](https://apify.com/feedminer)

# Actor input Schema

## `handles` (type: `array`):

Accounts to read, as handles or profile URLs.

## `signals` (type: `array`):

Reposts and replies are the reliable ones. X made the likes tab private in 2024, so likes often come back empty even with an account.

## `maxItems` (type: `integer`):

Stop once this many posts have been collected.

## `sessions` (type: `array`):

Optional. The Actor works without one. X accounts of your own, for anyone who would rather the run used accounts they control.

## `debugMode` (type: `boolean`):

Verbose logs for support.

## Actor input object example

```json
{
  "handles": [
    "apify"
  ],
  "signals": [
    "reposts"
  ],
  "maxItems": 1000,
  "sessions": [
    {
      "label": "account-1",
      "authToken": "",
      "ct0": ""
    }
  ],
  "debugMode": false
}
```

# Actor output Schema

## `posts` (type: `string`):

No description

# 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 = {
    "handles": [
        "apify"
    ],
    "maxItems": 1000,
    "sessions": [
        {
            "label": "account-1",
            "authToken": "",
            "ct0": ""
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("feedminer/x-signals-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 = {
    "handles": ["apify"],
    "maxItems": 1000,
    "sessions": [{
            "label": "account-1",
            "authToken": "",
            "ct0": "",
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("feedminer/x-signals-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 '{
  "handles": [
    "apify"
  ],
  "maxItems": 1000,
  "sessions": [
    {
      "label": "account-1",
      "authToken": "",
      "ct0": ""
    }
  ]
}' |
apify call feedminer/x-signals-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,feedminer/x-signals-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/K5Y167lbmGJp1eZah/builds/kRWymMD2ZFi2BdQR4/openapi.json
