# X (Twitter) Mentions Monitor | $0.12/1K | Only What Is New (`feedminer/x-mentions-scraper`) Actor

Watch what X (Twitter) says about your brand and get only what is new. Every mention with its author, engagement metrics and link, plus a delta mode that remembers where the last run stopped, so a scheduled watch never returns or bills the same mention twice. JSON, CSV or Excel. By FeedMiner.

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

## Pricing

from $0.10 / 1,000 mention 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>Watch what X (Twitter) says about your brand, and get only what is new.</strong> Every mention with its author, engagement metrics and link, plus a delta mode that remembers where the last run stopped. Built to be scheduled.
</div>

🔁 **It remembers.** The actor keeps the last post it saw for each brand. Tomorrow's run returns the twelve new mentions, not the same three hundred you already read and already paid for.

💸 **$0.12 per 1,000 mentions, down to $0.10 on the larger Apify plans.** The most visible tweet scraper on the store bills $0.40 per 1,000 for the same rows. No start fee.

🏷️ **Handles and phrases, handled differently.** `@airfrance` is watched as a mention. `Air France` is matched as a phrase, so you do not get every post about air.

🔇 **A noise floor.** A minimum like count and a language filter cut the bot chatter before it reaches your dataset, and before it is billed.

#### Copy to your AI assistant

```
feedminer/x-mentions-scraper on Apify. Watches X (Twitter) for brand mentions and returns only what appeared since the previous run. One row per mention with brand, text, author, engagement counts (likes, reposts, replies, quotes, views), createdAt and url. Call ApifyClient("TOKEN").actor("feedminer/x-mentions-scraper").call(run_input={...}), then client.dataset(run["defaultDatasetId"]).list_items().items. Input: brands (string[] of handles or phrases), onlyNewSinceLastRun (bool, default true), language (string), minLikes (int), maxItems (int), sessions (array, optional). State is kept in a key-value store named feedminer-x-mentions-state in your Apify account, created by the first run, record MENTIONS_STATE. Full spec: GET https://api.apify.com/v2/acts/feedminer~x-mentions-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 monitor a brand on X (Twitter)

##### Basic: one brand, everything new since last time

```json
{ "brands": ["@apify"], "onlyNewSinceLastRun": true, "maxItems": 500 }
```

##### A brand name that is two words

```json
{ "brands": ["Air France"], "language": "fr", "maxItems": 1000 }
```

The phrase is matched whole, so posts about air travel in general stay out.

##### A brand, its product and its handle in one watch

```json
{ "brands": ["@stripe", "Stripe Billing", "stripe.com"], "maxItems": 2000 }
```

Each brand keeps its own memory, so adding a fourth term next month does not replay the first three.

##### Only mentions with traction

```json
{ "brands": ["@apify"], "minLikes": 5, "language": "en", "maxItems": 300 }
```

##### A full sweep, ignoring the memory

```json
{ "brands": ["@apify"], "onlyNewSinceLastRun": false, "maxItems": 2000 }
```

Use this the first time, to build a baseline, then leave the delta on.

***

### Input parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `brands` | array |  | A name, a phrase or an X handle. Handles are watched as mentions, phrases are matched whole |
| `onlyNewSinceLastRun` | boolean | `true` | Return only the mentions that appeared since the previous run of this actor. Turn it off to sweep the whole window again |
| `maxItems` | integer | `1000` | Stop once this many mentions have been collected |

**Filter mentions**

| Parameter | Type | Default | Description |
|---|---|---|---|
| `language` | select |  | Keeps only posts X detected in this language |
| `minLikes` | integer | `0` | Ignore mentions below this many likes, to cut the noise |

**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 |

#### Coming from another brand monitor

`username`, `usernames` and `handles` are read as accounts to watch, and become mention searches. `keywords`, `terms` and `searchTerms` are read as phrases.

#### How the memory works

After each run the actor stores the newest post id it saw, per brand, in a key-value store named `feedminer-x-mentions-state` in your Apify account, created by the first run and reused by every later one. The next run asks X for what came after that id and drops anything older that slips through. A brand that produced nothing keeps its previous mark, so a quiet week does not replay your whole history on the following run.

Turn `onlyNewSinceLastRun` off whenever you want a full sweep again. The memory is not lost, it is ignored for that run.

#### Nothing to connect

Name the brands and press Start. The watch covers all of X, with no account to create and no cookie to copy on your side.

If you would rather the run worked from accounts you own, the optional `sessions` field takes them.

***

### What data can you extract from a brand mention?

| Field | Type | Description |
|---|---|---|
| `brand` | string | Which of your watched terms this mention matched |
| `text` | string | Mention text |
| `url` | string | Direct link to the post |
| `createdAt` | string | Publication date, RFC 3339 |
| `lang` | string | Language X detected |
| `likeCount` `retweetCount` `replyCount` `quoteCount` `bookmarkCount` | integer | Engagement |
| `viewCount` | integer | Views |
| `isReply` `isQuote` `isRetweet` | boolean | What kind of post this is |
| `conversationId` | string | Thread this mention belongs to |
| `author` | object | Handle, name, bio, followers, verification, join date |
| `hashtags` `mentions` `links` `media` | array | Entities in the post |

***

### Pricing: Pay Per Event (PPE)

| Event | Price |
|---|---|
| Mention returned | $0.00012 |

That is **$0.12 per 1,000 mentions**, with no start fee. A run that finds nothing new costs nothing, which is the normal outcome of a watch that runs every hour. 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

| | |
|---|---|
| A daily brand watch, 100 new mentions a day, 3,000 rows in a month | $0.36 |
| A 5,000 mention backlog sweep | $0.60 |

##### Free tier

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

### Advanced usage

**Schedule it, that is the point.** Apify Schedules run it hourly or daily. With the delta on, each run returns the new mentions only, and the cost follows the noise rather than the archive.

**Send it somewhere.** From the Integrations tab, push each run's dataset to Slack, an email, a Google Sheet or a webhook, and you have a brand alert without writing a service.

**Watch a competitor the same way.** Nothing here is specific to your own brand. Two competitors and your own name in one watch gives you share of voice, run after run.

**Sort by reach, not by volume.** `viewCount` and the author's follower count are on every row, so the one post that matters this week is a sort away.

**Start with a sweep.** Run once with the delta off to capture the current state, then leave it on. Otherwise the first scheduled run returns a large backlog.

***

### Integrate X brand mentions into your stack

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("feedminer/x-mentions-scraper").call(run_input={
    "brands": ["@apify", "Apify"],
    "onlyNewSinceLastRun": True,
    "minLikes": 2,
    "maxItems": 500,
})

new = client.dataset(run["defaultDatasetId"]).list_items().items
loud = [m for m in new if m["viewCount"] > 10000]
print(len(new), "new mentions,", len(loud), "with real reach")
```

**JavaScript**

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('feedminer/x-mentions-scraper').call({
    brands: ['@stripe'],
    onlyNewSinceLastRun: true,
    maxItems: 300,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const negative = items.filter((m) => /down|broken|outage/i.test(m.text));
```

**No code**

Connect the run to Slack, Gmail, Google Sheets, Zapier, Make or n8n from the Integrations tab, and the watch becomes an alert.

***

### Performance

| Measure | Value |
|---|---|
| Parallelism | One worker per brand, up to six |
| Memory between runs | One post id per brand, in the key-value store `feedminer-x-mentions-state` of your account |
| Partial results | Kept and delivered when a limit is reached |

***

### FAQ

**How does it know what is new?**
It stores the newest post id it returned for each brand and asks X for what came after it. X ids grow with time, so the comparison is exact, not a date guess.

**What if I add a brand later?**
It starts from scratch for that brand only. The others keep their memory.

**Can I get the backlog back?**
Yes, run once with `onlyNewSinceLastRun` set to false.

**Do I need an X account?**
No. The run brings its own. When none is free at that moment, the watch reaches the public Communities index only, and the run says so.

**Does it catch mentions that do not use my handle?**
Yes, that is what phrases are for. Watch `@yourbrand` and `Your Brand` together.

**How often should I run it?**
Hourly for a crisis watch, daily for a normal one. There is no minimum interval on the actor's side.

**Will I be billed twice for the same mention?**
Not with the delta on. A mention is returned once, and the memory moves forward.

**Can I filter out retweets?**
Every row carries `isRetweet`, so filtering them in your pipeline is one condition. The watch itself keeps them, because a repost is often the reach.

***

### Support

A mention you expected and did not get, a term that matches too much, an alert you want to wire: write from the actor page.

***

### Legal compliance

This actor reads public posts on X. 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 · [X Engagement Scraper](https://apify.com/feedminer/x-engagement-scraper) · [X Likes and Reposts Scraper](https://apify.com/feedminer/x-signals-scraper) · [X Trends Scraper](https://apify.com/feedminer/x-trends-scraper) · [All FeedMiner Actors](https://apify.com/feedminer)

# Actor input Schema

## `brands` (type: `array`):

A name, a phrase or an X handle. Handles are watched as mentions, phrases are matched whole.

## `onlyNewSinceLastRun` (type: `boolean`):

Return only the mentions that appeared since the previous run of this actor. Turn it off to sweep the whole window again.

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

Stop once this many mentions have been collected.

## `language` (type: `string`):

Keeps only posts X detected in this language.

## `minLikes` (type: `integer`):

Ignore mentions below this many likes, to cut the noise.

## `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
{
  "brands": [
    "@apify"
  ],
  "onlyNewSinceLastRun": true,
  "maxItems": 1000,
  "minLikes": 0,
  "sessions": [
    {
      "label": "account-1",
      "authToken": "",
      "ct0": ""
    }
  ],
  "debugMode": false
}
```

# Actor output Schema

## `mentions` (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 = {
    "brands": [
        "@apify"
    ],
    "maxItems": 1000,
    "minLikes": 0,
    "sessions": [
        {
            "label": "account-1",
            "authToken": "",
            "ct0": ""
        }
    ]
};

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

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

```

## MCP server setup

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