# X (Twitter) Post Performance & Growth Monitor (`arjun_code/x-twitter-post-performance-monitor`) Actor

Track likes, retweets, replies, bookmarks, and views for up to 50 public X posts. Compare every scheduled check with previous and baseline values, keep performance history, and send optional Slack, Discord, or webhook alerts for sudden changes and one-time milestones. No X login or API key required.

- **URL**: https://apify.com/arjun_code/x-twitter-post-performance-monitor.md
- **Developed by:** [Arjun AI](https://apify.com/arjun_code) (community)
- **Categories:** Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 post performance checks

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

Track how individual X / Twitter posts perform after publication. This Actor checks up to 50 public posts per run, saves a baseline, measures engagement growth on later checks, and can alert your team when activity changes or a post crosses an important milestone.

Use it for **campaign reporting, creator analytics, viral-post tracking, newsroom monitoring, and competitor benchmarking**. You do not need an X login, cookies, an API key, or proxy configuration.

### What you get

- Current likes, retweets, quotes, replies, bookmarks, and views.
- Change since the previous successful check.
- Total growth since the first baseline check.
- Observed hourly growth rate calculated from the exact time between checks.
- A persistent history that works with 10-minute, 30-minute, hourly, daily, or custom schedules.
- Optional Slack, Discord, or generic webhook alerts.
- One-time alerts for view, like, retweet, quote, and reply milestones.
- Structured Dataset output for JSON, CSV, Excel, API, Make, Zapier, n8n, and other integrations.

### Quick start

1. Paste one or more public X post URLs or numeric post IDs into **Post URLs or IDs**.
2. Run the Actor once. This creates the baseline, so the first result has the status `baseline_created`.
3. Select **Save input to a new task**, open that Task, and add a schedule. Every later run of the same Task compares the latest metrics with its previous successful check.

That is enough for normal monitoring. Keep **History group** set to `default` unless you deliberately need separate histories inside the same Task.

### Who should use this X post analytics monitor?

- **Social media teams** measuring campaign and announcement performance.
- **Creators and agencies** tracking sponsored posts and audience response.
- **Marketing analysts** comparing engagement velocity across several posts.
- **Newsrooms and researchers** watching how public posts spread over time.
- **Community managers** receiving alerts when replies or retweets accelerate.

### Input

The simplest input contains only the posts you want to monitor:

```json
{
  "tweets": [
    "https://x.com/NASA/status/2095890073031966734",
    "2095890073031966734"
  ]
}
```

Equivalent links and IDs are normalized and checked only once. You can monitor up to 50 unique posts in one run.

| Input | What it does | Recommended use |
| --- | --- | --- |
| `tweets` | Public X post links or numeric IDs to monitor. | Required. Enter one per line. |
| `monitorId` | Separates independent histories inside one Task or across direct API runs. | Keep `default` for normal use. |
| `notificationWebhookUrl` | Sends alerts to Slack, Discord, or another HTTP endpoint. | Leave blank if Dataset results are enough. |
| `minimumLikesChange` | Alerts when likes move by at least this amount between checks. | Optional. |
| `minimumRetweetsChange` | Alerts when retweets move by at least this amount between checks. | Optional. |
| `minimumQuotesChange` | Alerts when quotes move by at least this amount between checks. | Optional. |
| `minimumRepliesChange` | Alerts when replies move by at least this amount between checks. | Optional. |
| `minimumBookmarksChange` | Alerts when bookmarks move by at least this amount between checks. | Optional. |
| `minimumViewsChange` | Alerts when views move by at least this amount between checks. | Optional. |
| `viewMilestones`, `likeMilestones`, `retweetMilestones`, `quoteMilestones`, `replyMilestones` | Sends a one-time alert when the total first reaches each configured value. | Optional; enter one total per line. |

### Schedule recurring checks

The Actor does not require an hourly schedule. It uses the exact timestamps of two successful checks, so any interval works.

1. Complete the first baseline run.
2. Save the input as an Apify Task.
3. Add the interval that matches your campaign, such as every 10 minutes for a launch, every 30 minutes for active monitoring, or daily for long-term reporting.
4. Keep running the same Task. Changing its schedule does not reset history.

The current run is stored in the default Dataset. Every successful snapshot is also appended to the named Dataset `x-post-performance-history-v1`. The result field `history.scope_key` identifies the history belonging to the same Task and history group.

### Change alerts and milestone alerts

#### Alert when engagement changes quickly

Set a webhook URL and one or more change thresholds:

```json
{
  "tweets": ["https://x.com/NASA/status/2095890073031966734"],
  "notificationWebhookUrl": "https://example.com/your-webhook",
  "minimumLikesChange": 100,
  "minimumRetweetsChange": 20,
  "minimumViewsChange": 10000
}
```

Thresholds compare the current check with the previous successful check. Both increases and decreases can trigger an alert. If a webhook is provided without individual thresholds or milestones, any changed metric triggers it. Baseline and unchanged runs stay quiet.

#### Alert once when a post reaches a total

Milestones are useful for goals such as 100,000 views or 10,000 likes:

```json
{
  "tweets": ["https://x.com/NASA/status/2095890073031966734"],
  "notificationWebhookUrl": "https://example.com/your-webhook",
  "viewMilestones": ["100000", "500000", "1000000"],
  "likeMilestones": ["1000", "5000", "10000"]
}
```

Each milestone is sent only once within the same Task and history group. The first baseline check does not send milestone notifications.

### Output

The first successful check returns `baseline_created`. Later checks return `changed` or `no_change`. Unavailable and invalid posts are returned as clear status rows instead of hiding the problem.

```json
{
  "status": "changed",
  "message": "Likes +25; Retweets +6; Views +1400.",
  "checked_at": "2026-10-12T10:00:00.000Z",
  "previous_checked_at": "2026-10-12T09:00:00.000Z",
  "elapsed_seconds": 3600,
  "changed_metrics": ["likes", "retweets", "views"],
  "post": {
    "id": "2095890073031966734",
    "url": "https://x.com/NASA/status/2095890073031966734",
    "text": "Post text from X",
    "created_at": "2026-09-04T12:00:00Z"
  },
  "author": {
    "username": "NASA",
    "name": "NASA",
    "profile_url": "https://x.com/NASA"
  },
  "metrics": {
    "likes": {"previous": 120, "current": 145, "change": 25, "rate_per_hour": 25},
    "retweets": {"previous": 18, "current": 24, "change": 6, "rate_per_hour": 6},
    "views": {"previous": 5000, "current": 6400, "change": 1400, "rate_per_hour": 1400}
  },
  "since_baseline": {
    "likes_change": 1250,
    "retweets_change": 380,
    "views_change": 95600
  },
  "alert": {
    "triggered": true,
    "threshold_reached": true,
    "triggered_metrics": ["likes", "retweets", "views"],
    "milestone_reached": false,
    "reached_milestones": []
  }
}
```

`rate_per_hour` is the observed change normalized to one hour. It is not a forecast and does not require the Actor to run hourly. X may return `null` for a metric it does not expose for a particular post.

### Run with the Apify API

```bash
curl -X POST "https://api.apify.com/v2/actors/arjun_code~x-twitter-post-performance-monitor/runs" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"tweets":["https://x.com/NASA/status/2095890073031966734"],"monitorId":"campaign"}'
```

Use the same `monitorId` for recurring direct API runs that should share one performance history.

### Pricing

This Actor uses pay-per-event pricing. A small **Actor Start** event is charged once per run, and one **Post performance check** event is charged for each public post that is successfully checked and saved.

Invalid inputs, unavailable posts, and failed checks do not trigger the post-check event. Diagnostic status rows are not charged as Dataset items. See the Actor's **Pricing** tab for the current per-check price and subscription discounts; it is the source of truth if prices change later. You can also set **Maximum cost per run** in Apify Run options.

### Related X / Twitter Actors

- [X (Twitter) Media Downloader](https://apify.com/arjun_code/x-twitter-media-downloader) — get post details and download public media.
- [X (Twitter) Replies Scraper](https://apify.com/arjun_code/x-twitter-replies-scraper) — export replies and conversation context.
- [X (Twitter) Retweeters Scraper](https://apify.com/arjun_code/x-twitter-retweeters-scraper) — collect retweeters and quote-post authors.

### FAQ

#### Does the first run show growth?

No. The first successful run creates the baseline. Growth appears from the second successful run of the same Task and history group.

#### Must the Task run every hour?

No. Use any schedule. The Actor calculates the exact interval and normalizes the observed rate to one hour.

#### Can I monitor several posts together?

Yes. One run accepts up to 50 unique public post URLs or IDs and returns one row per checked post.

#### Are failed checks saved as the new baseline?

No. An unavailable post or failed request does not replace the last successful snapshot.

#### Does the Actor need my X account?

No. It collects publicly available post data without your X login, cookies, API key, or proxy settings.

### Support

If a run does not behave as expected, open an issue on the Actor page and include the Apify run ID, the non-secret input, and what you expected to happen. Do not include webhook URLs, API tokens, cookies, passwords, or other credentials.

This independent Actor is not affiliated with, endorsed by, or sponsored by X Corp.

# Actor input Schema

## `tweets` (type: `array`):

Enter one post per line. Links and numeric post IDs are both accepted, and duplicates are checked once. The first successful run creates the baseline; later runs of the same Task calculate what changed.

## `monitorId` (type: `string`):

Leave this as default for normal use. Change it only when the same Task must keep separate histories for the same post, or when direct API runs need a stable history group.

## `notificationWebhookUrl` (type: `string`):

Paste a Slack Incoming Webhook, Discord webhook, or another HTTP POST endpoint. Leave it empty if you only want results in the Dataset.

## `minimumLikesChange` (type: `integer`):

Send an alert when likes increase or decrease by at least this amount between two successful checks. Leave blank to ignore likes.

## `minimumRetweetsChange` (type: `integer`):

Send an alert when retweets increase or decrease by at least this amount between two successful checks. Leave blank to ignore retweets.

## `minimumQuotesChange` (type: `integer`):

Send an alert when quotes increase or decrease by at least this amount between two successful checks. Leave blank to ignore quotes.

## `minimumRepliesChange` (type: `integer`):

Send an alert when replies increase or decrease by at least this amount between two successful checks. Leave blank to ignore replies.

## `minimumBookmarksChange` (type: `integer`):

Send an alert when bookmarks increase or decrease by at least this amount between two successful checks. Leave blank to ignore bookmarks.

## `minimumViewsChange` (type: `integer`):

Send an alert when views increase or decrease by at least this amount between two successful checks. Leave blank to ignore views.

## `viewMilestones` (type: `array`):

Total view counts to alert on once, for example 100000, 500000, and 1000000. Enter one number per line.

## `likeMilestones` (type: `array`):

Total like counts to alert on once, for example 1000, 5000, and 10000. Enter one number per line.

## `retweetMilestones` (type: `array`):

Total retweet counts to alert on once. Enter one number per line.

## `quoteMilestones` (type: `array`):

Total quote counts to alert on once. Enter one number per line.

## `replyMilestones` (type: `array`):

Total reply counts to alert on once. Enter one number per line.

## Actor input object example

```json
{
  "tweets": [
    "https://x.com/NASA/status/2095890073031966734"
  ],
  "monitorId": "default"
}
```

# Actor output Schema

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

Current engagement metrics, changes since the previous successful check, cumulative growth since the first check, alert-threshold status, and post context stored 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 = {
    "tweets": [
        "https://x.com/NASA/status/2095890073031966734"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("arjun_code/x-twitter-post-performance-monitor").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 = { "tweets": ["https://x.com/NASA/status/2095890073031966734"] }

# Run the Actor and wait for it to finish
run = client.actor("arjun_code/x-twitter-post-performance-monitor").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 '{
  "tweets": [
    "https://x.com/NASA/status/2095890073031966734"
  ]
}' |
apify call arjun_code/x-twitter-post-performance-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,arjun_code/x-twitter-post-performance-monitor"
        }
    }
}
```

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/JhvqiaeuetTBfecRN/builds/WBkMsriemXwLeQLxm/openapi.json
