# X Twitter Engagement Rate: Influencer Stats & Audit (`vant47/twitter-engagement-rate`) Actor

Get the engagement rate of any X (Twitter) account before paying for a post, e.g. crypto, fitness or tech influencers. About $0.02 per account. Verdict, size-based grade, followers, likes, replies, reposts, views and posting rate. Based on the last 4 to 5 posts. No login.

- **URL**: https://apify.com/vant47/twitter-engagement-rate.md
- **Developed by:** [fortbrand](https://apify.com/vant47) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $16.00 / 1,000 account audits

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

## X Twitter Engagement Rate: Influencer Stats & Audit

For marketers, creator managers and researchers who want to check an X (Twitter) account before paying for a post. **About $0.02 per account.** Checking 20 accounts costs about **$0.40**, plus Apify's small startup fee. No login, account cookies or outside API key is needed.

Get a verdict, engagement rates, follower counts, a reference grade, medians, posting cadence and an HTML report. This audit is **based on the last 4 to 5 posts** available to signed-out visitors. X normally returns five timeline entries; a pinned entry is separated, leaving four ordinary posts. A pin never enters the averages. This is a screening sample, not a complete history or a prediction of campaign results.

### What you get

One account row starts with the answer: its engagement as a percentage of followers, how that compares with the measured reference for its audience size, its grade and the actual sample count. A free summary row, `SUMMARY` record and `REPORT.html` accompany every run.

| Field | Meaning |
| --- | --- |
| `verdict` | Plain-English result, reference comparison and sample-size disclosure |
| `status` | `OK`, `INSUFFICIENT_DATA`, `UNAVAILABLE` or `INPUT_NOTE` |
| `username`, `profileUrl` | Canonical account handle and public profile link |
| `name` | Display name as published on X |
| `followers`, `following`, `posts` | Current follower, following and lifetime post counts |
| `verified`, `blueVerified`, `verificationType` | Public verification information; not a trust assessment |
| `postsAnalyzed` | Exact number of usable non-pinned posts in the calculation |
| `sampleDescription` | Scope: based on the last 4 to 5 posts, with actual usable count |
| `publicPostsFound`, `postsRequested` | Parsed posts and the requested maximum |
| `pinnedPostsExcluded`, `pinnedPosts` | Number of excluded pins and their separate post records |
| `engagementRateByFollowersPct` | Mean likes + replies + reposts per analyzed post, divided by current followers, times 100 |
| `engagementRateByViewsPct` | Total interactions divided by total views, using only analyzed posts with positive public views, times 100 |
| `postsWithViews` | Number of posts supporting the view-based rate |
| `averageLikes`, `averageReplies`, `averageReposts` | Average interaction counts per analyzed post |
| `medianLikes`, `medianReplies`, `medianReposts` | Median interaction counts, reducing the effect of one unusually successful post |
| `averageViews`, `medianViews` | Average and median among available view counts; null when unavailable |
| `averageQuotes`, `medianQuotes` | Separate quote-post counts where available; excluded from the engagement formula |
| `replySharePct` | Received replies as a percentage of likes + replies + reposts |
| `postingRatePerWeek` | Estimated cadence from intervals between the analyzed original posts |
| `sampleWindowDays`, `daysSinceLastPost` | Time covered by the sample and age of its newest post |
| `oldestPostAt`, `newestPostAt`, `checkedAt` | UTC timestamps for the sample and measurement |
| `sizeTier`, `normForSizePct` | Audience-size band and median engagement rate in the fixed reference sample |
| `grade`, `referenceRatio` | A-D comparison with that reference, and rate divided by reference |
| `referenceAccounts`, `referenceDate`, `referenceMethod` | Cohort size, date and limitations of the comparison |
| `analyzedPosts` | Every post included, with URL, timestamp, text and individual counts |
| `topPosts` | Up to three analyzed posts ranked by likes + replies + reposts |
| `notes` | Missing views, stale posts, capped requests and other limitations |
| `charged` | Whether this row represents a charged account audit; summary and note rows are false |

### When to use it

Shortlist crypto creators, compare fitness accounts, or check tech creators before buying a post. Agencies get a consistent comparison table; researchers get dated counts and source links.

### How to use it

1. Enter handles in **X usernames**, such as `NASA` or `@levelsio`. Alternatively, paste X or Twitter **profile URLs**. You can use both lists.
2. Leave **Posts to analyze** at 5 and review the run's maximum charge. The prefilled two-account example costs about $0.04 plus startup.
3. Start the Actor. Open the overview dataset view for verdicts, the metrics view for comparisons, or the linked HTML report. Export the dataset as JSON, CSV or Excel from Apify.

Handles and URLs are deduplicated case-insensitively. Post URLs generate free input notes. Empty input does not scrape any accounts.

### Inputs

| Input | Default | Examples and behavior |
| --- | --- | --- |
| `usernames` | None at API level; console prefill contains two accounts | `["NASA", "levelsio"]`; with or without `@` |
| `urls` | Empty | `["https://x.com/NASA", "https://twitter.com/levelsio"]` |
| `postsToAnalyze` | `5` | Requested maximum. At most five public entries are available; a pin reduces the usable count. Values above five are capped with a note. |
| `saveRawData` | `false` | Save public source pages in the run's `RAW` key-value record for verification. Adds storage. |

The API also accepts `startUrls` entries such as `{"url":"https://x.com/NASA"}` for integrations that already use that field. All lists are combined and deduplicated. A run accepts at most 1,000 input entries; split larger work into batches. There is no special free-plan cap.

```json
{
  "usernames": ["NASA", "levelsio"],
  "postsToAnalyze": 5,
  "saveRawData": false
}
```

Requests above five cannot unlock history. Invalid counts use the default with a free note. Fewer than three usable posts or no usable follower denominator produces a free `Insufficient data` row.

### How the calculations work

Follower engagement = mean(likes + received replies + reposts) / current followers \* 100. The denominator is today's follower count. Quote counts are separate and excluded. Edited-post counts include prior revision interactions.

View engagement = sum(interactions) / sum(views) \* 100, restricted to the same posts with positive public views. Missing views remain null; those posts can still contribute to follower engagement. `postsWithViews` shows the denominator coverage.

Posting cadence = `(posts analyzed - 1) / days between oldest and newest * 7`. It covers observed original-post intervals, excluding the account's reply and repost activity. `replySharePct` measures received replies as a share of interactions, not how often the account replies.

Pins are identified from X's structured pin instruction and reported separately. They never enter averages, medians, cadence or grades. Quoted posts and other authors' posts are excluded. Missing counts are not zero.

### Reference grades by audience size

The reference is our own dated convenience sample, **not a population-wide X benchmark**. On 14 October 2026, the calibration tested 142 public handles across technology, developers, fitness, crypto, media, sports, organizations and consumer brands. There were 126 usable account audits. Removing accounts whose newest sampled post was over 90 days old left 94 accounts for the reference.

| Followers | Reference accounts | Median account engagement |
| --- | ---: | ---: |
| Under 100,000 | 22 | 0.191482% |
| 100,000 to under 1 million | 36 | 0.070086% |
| 1 million to under 10 million | 20 | 0.033506% |
| 10 million or more | 16 | 0.005433% |

Medians are across account-level rates, without weighting larger accounts more heavily. This selected sample mixes niches and account types. Same-size fitness creators and news publishers may differ greatly. The reference is fixed, not recomputed from your run.

Grades compare your rate with the reference median: **A** is at least 2x; **B** is 1x to under 2x; **C** is 0.5x to under 1x; **D** is below 0.5x. They are comparison bands, not population percentiles. Cohort size and date accompany each grade.

### Pricing and spending limits

The list price is **$0.02 per useful account audit**. Bronze is $0.019, Silver $0.018, and Gold and higher tiers $0.016. Apify's startup fee remains $0.00005 per GB, with a minimum of one startup event. The default memory is below 1 GB, so the minimum startup fee applies. Platform usage is included in this Actor's pay-per-event price; no external service key is needed.

| Useful accounts | List-price account charges | Bronze account charges |
| --- | ---: | ---: |
| 2 | $0.04 | $0.038 |
| 20 | $0.40 | $0.38 |
| 100 | $2.00 | $1.90 |
| 1,000 | $20.00 | $19.00 |

Add the startup fee to each example. Failed lookups, insufficient samples, invalid inputs, duplicates, retries and summary rows do not incur an account-audit charge. A run containing only free notes can still incur Apify's startup fee.

The Actor checks the spending limit before another fetch, charges only after usable data arrives, and handles the row write and charge together. The summary reports a spending-limit stop; increase your limit or split the remaining accounts into another run.

### Real output example

From a private cloud verification on 14 October 2026. Counts change over time.

```json
{
  "verdict": "Engagement 0.0095% of followers per post, at or above reference for 10M+ followers (B); based on the last 4 to 5 posts (5 analyzed).",
  "username": "NASA",
  "followers": 92328883,
  "postsAnalyzed": 5,
  "pinnedPostsExcluded": 0,
  "engagementRateByFollowersPct": 0.009451,
  "engagementRateByViewsPct": 0.591187,
  "grade": "B",
  "normForSizePct": 0.005433
}
```

### API examples

Use your own Apify token. For large lists, use asynchronous runs. Filter `type == "ACCOUNT"` and `status == "OK"` to exclude notes and summaries.

```bash
curl -X POST \
  'https://api.apify.com/v2/acts/vant47~twitter-engagement-rate/run-sync-get-dataset-items?timeout=120' \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"usernames":["NASA","levelsio"],"postsToAnalyze":5}'
```

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("vant47/twitter-engagement-rate").call(
    run_input={"usernames": ["NASA", "levelsio"], "postsToAnalyze": 5}
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row.get("status") == "OK":
        print(row["username"], row["verdict"])
```

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('vant47/twitter-engagement-rate').call({
  usernames: ['NASA', 'levelsio'], postsToAnalyze: 5
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter(row => row.status === 'OK'));
```

### Use with AI agents (MCP)

Connect to `https://mcp.apify.com`. Ask your agent to search **Twitter engagement rate**, inspect the schema, and pass `usernames`. Example: “Compare these X tech creators before I buy a post. Include followers, views, sample size and limitations.”

Agents should preserve the sample caveat, check post ages, explain the selected reference and inspect `spendingLimitReached`. Grades are not fake-follower findings or earnings forecasts.

### Saved tasks and integrations

Five saved tasks cover crypto, fitness, tech creators, brands and space, each with two accounts. Duplicate a task and replace its handles. Exports work with spreadsheets; Apify supports schedules, Make, Zapier, n8n and webhooks. No schedule is enabled automatically.

For repeated measurements, save timestamps, post IDs and counts. New posts change the sample, so rate changes need context. The Actor does not retain history or calculate follower growth.

### Limits and FAQ

**Why four or five posts?** X shows five signed-out timeline entries. A pin leaves four ordinary posts; it is reported separately. Three usable posts can qualify, with the actual count disclosed. Fewer than three is free. Requesting more cannot unlock history.

**Protected, deleted or suspended accounts?** Unavailable accounts receive free notes. The calibration produced 16 unavailable or insufficient cases without account charges.

**Are counts exact?** Structured public numbers are used, not rounded labels. They reflect the response at measurement time, subject to X's caching. Missing values stay null. Counts may change before you visit a post.

**Does an A guarantee performance?** No. Viral content, promotions, niche differences and immature engagement can distort a short sample. Grades use the disclosed reference, not a representative X-wide population.

**Bookmarks, clicks or impressions?** Not included. Public views are not unique viewers or private analytics impressions. Quote counts are separate from the headline formula.

**Old or very recent posts?** Notes flag sampled posts under 24 hours old and accounts whose newest post is over 30 days old. The data is never presented as a complete current-month history.

**Can I verify it?** Every analyzed post includes a source URL and counts. Enable `saveRawData` for public source HTML in `RAW`. The report links to sampled posts.

**What if X changes?** Datacenter requests are retried, then residential is attempted. Unusable data receives a free note. No login, borrowed account cookies, CAPTCHA solving or paid data API is used.

**Affiliated with X?** No. This is an independent tool. Review X's terms and your intended use before collecting or distributing data.

# Actor input Schema

## `usernames` (type: `array`):

Account handles, with or without @. Example: NASA, levelsio. One paid audit per unique account with at least 3 usable posts. Based on the last 4 to 5 posts; pinned posts excluded.

## `urls` (type: `array`):

X or Twitter profile links, e.g. https://x.com/NASA. Combined with usernames and deduplicated. Post URLs are not profile URLs.

## `postsToAnalyze` (type: `integer`):

Defaults to 5. X exposes only five signed-out timeline entries, leaving 4 to 5 usable posts after removing a pin. Requests above 5 are capped with a note, never presented as deeper history. At least 3 usable posts are needed.

## `saveRawData` (type: `boolean`):

Optional: keep public source HTML in the run RAW record for checking results. Increases storage. No login or account cookies.

## Actor input object example

```json
{
  "usernames": [
    "NASA",
    "levelsio"
  ],
  "postsToAnalyze": 5,
  "saveRawData": false
}
```

# Actor output Schema

## `audits` (type: `string`):

No description

## `metrics` (type: `string`):

No description

## `summary` (type: `string`):

No description

## `report` (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 = {
    "usernames": [
        "NASA",
        "levelsio"
    ],
    "postsToAnalyze": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("vant47/twitter-engagement-rate").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 = {
    "usernames": [
        "NASA",
        "levelsio",
    ],
    "postsToAnalyze": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("vant47/twitter-engagement-rate").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 '{
  "usernames": [
    "NASA",
    "levelsio"
  ],
  "postsToAnalyze": 5
}' |
apify call vant47/twitter-engagement-rate --silent --output-dataset

```

## MCP server setup

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

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/pSRC70BadG6KRminm/builds/osE26mdZ1ne3y6tQV/openapi.json
