X (Twitter) Account Monitor — Posts & Engagement avatar

X (Twitter) Account Monitor — Posts & Engagement

Pricing

from $0.06 / 1,000 posts

Go to Apify Store
X (Twitter) Account Monitor — Posts & Engagement

X (Twitter) Account Monitor — Posts & Engagement

Watch a list of X accounts: each one's newest posts with likes, reposts, replies and quotes, the engagement per 1,000 followers, and the account's own row (followers, posts per day, age). Only-new mode pays for what appeared since the last run. No login, no API key.

Pricing

from $0.06 / 1,000 posts

Rating

0.0

(0)

Developer

Berkan Kaplan

Berkan Kaplan

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

18 hours ago

Last modified

Categories

Share

X (Twitter) Account Monitor — Posts, Engagement & Profiles 𝕏

Give it a list of X accounts; get their newest posts with the numbers that matter — likes, reposts, replies, quotes — plus each account's own row. Built for watching accounts over time: competitors, clients, portfolio companies, journalists, your own brand. No login, no API key, no browser: one read per account, charged per row.

  • 📊 The four engagement counts on every post — likes, reposts, replies, quotes — plus what we compute from them: engagement total, engagement per 1,000 followers (comparable across accounts of different sizes) and engagement per hour since the post went up
  • 👤 The account itself — followers, following, posts, listed count, bio, website, location, verification, account age, posts per day, followers-to-following ratio
  • 🔁 Only-new mode — keeps a list of what it has already delivered, so an hourly watchlist pays only for posts that appeared since the last run
  • 🧾 Honest about its limits — X's embed backend hands out an account's newest page only (23–105 posts, no paging) and no keyword search. This Actor says so in the run's message instead of pretending otherwise
  • 🤖 Agent-ready — MCP, and pay-per-event so an AI agent can run it and settle the bill itself

What does this Actor do?

It reads X's own embed (syndication) backend — the service that renders embedded timelines and tweets on other people's websites. For each account you name it fetches that account's newest page of posts, turns every post into a flat row, and adds one row for the account itself. Nothing is logged in, no cookie jar is kept, and no browser is started, which is why a run is fast and cheap and why it does not break when X changes its web app.

Use it when you need: a watchlist of accounts checked on a schedule; engagement benchmarking across accounts; a client or competitor report; the current numbers on posts you already know.

Use something else when: you need keyword or hashtag search, follower lists, reply texts, or an account's history beyond its newest page — X's embed backend does not serve those, so this Actor does not claim them. The Input tab says the same thing where it matters.

Quick start (API)

Watch three accounts, five newest posts each:

curl -X POST "https://api.apify.com/v2/acts/foxlabs~x-account-monitor/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "accounts": ["@NASA", "x.com/nike", "11348282"], "maxPostsPerAccount": 5 }'

Prefer no code? Open the Input tab, paste your accounts one per line, and click Start.

Getting started (3 steps)

  1. Paste the accounts. A handle (@nasa), a profile address (x.com/nasa) or the account's numeric id (11348282) — all three work, mixed in one list.
  2. Pick how many posts per account (default 25). X hands out one page per account, so anything above ~105 simply takes everything that page holds.
  3. Turn on "Only posts new since the last run" if this is a watchlist you will run on a schedule. The first run delivers the page; later runs deliver only what appeared since.

Input

FieldTypeDefaultWhat it does
accountsarray—The accounts to read: @handle, x.com/handle or numeric id. Required.
maxPostsPerAccountinteger25Newest posts per account (1–110). With only-new mode on, this counts the posts looked at, so the run never pages backwards into history.
includeProfileRowbooleantrueOne extra row per account with the account's own fields.
onlyNewPostsbooleanfalseDeliver only posts not delivered before (keeps a list in your own key-value store).
listNamestringdefaultWhich list only-new mode uses. One list per watchlist.
skipRepliesbooleanfalseLeave out posts that start with a mention.
postedWithinDaysinteger0Only posts from the last N days (0 = no limit).
minEngagementinteger0Only posts with at least this many likes + reposts + replies + quotes.
maxPostsinteger0Cost cap across all accounts (0 = only the per-account limit).
concurrencyinteger8Accounts read side by side.
rememberAccountIdsbooleantrueKeeps each handle's numeric id after the first read, so later runs take the cheap road.
proxyConfigurationobjectApify Proxy (datacenter)Datacenter addresses answer every read made by numeric id. Handle lookups go through residential addresses, because a handle lookup from a datacenter address is rate-limited.

Output

One row per post, one row per account. Download as JSON, CSV, Excel or read it from the API.

{
"type": "tweet",
"id": "2109382322516799677",
"url": "https://x.com/Nike/status/2109382322516799677",
"text": "Zheng Qinwen claims her first WTA 1000 title in Beijing. A winner's name, etched on home soil.",
"createdAt": "2026-10-11T20:35:10.000Z",
"language": "en",
"likes": 6398,
"reposts": 527,
"replies": 92,
"quotes": 63,
"engagement": 7080,
"engagementPer1kFollowers": 0.745,
"engagementPerHour": 42.24,
"ageHours": 167.6,
"isReply": false,
"media": [{ "type": "photo", "url": "https://pbs.twimg.com/media/HUYHTdWXQAAFWCq.jpg", "width": 2160, "height": 2700 }],
"mediaTypes": ["photo"],
"hashtags": [],
"mentions": [],
"links": [],
"authorHandle": "Nike",
"authorFollowers": 9504725,
"authorVerified": true,
"scrapedAt": "2026-10-18T20:13:06.871Z"
}

Post fields

FieldTypeDescription
id / urlstringPost id and its address on x.com
textstringThe post's text as X states it
createdAtstringISO 8601, UTC
likes / reposts / replies / quotesintegerThe four counts X states on an embedded post
engagementintegerThe four counts added up
engagementPer1kFollowersnumberengagement / followers × 1,000 — the figure that compares a small account with a large one
engagementPerHournumberengagement / hours since posted — how fast it is travelling
ageHoursnumberHours since it went up
isReplybooleanThe post starts with a mention
conversationIdstringThe thread it belongs to
languagestringLanguage code X assigned
media[] / mediaCount / mediaTypesarray / integer / arrayPhotos and videos: type, direct URL, width, height
hashtags[] / mentions[] / links[]arrayAs X states them (links are the expanded addresses)
sensitive / editedbooleanFlags X states; null when it states none
authorHandle / authorName / authorId / authorFollowers / authorVerified—The author, flattened onto the row so an export needs no join
scrapedAtstringWhen this row was read

Account fields (type: "profile")

handle, name, bio, location, website, followers, following, tweets, likesGiven, listedIn, mediaPosted, verified, verifiedType, protected, profileImage, bannerImage, createdAt, accountAgeDays, tweetsPerDay, followersPerFollowing, withheldInCountries.

A line that cannot be delivered is written as a free type: "status" row with the reason — a line that is not an X account, an account X has no public record of, an account with nothing to embed, or an account the run could not read. Status rows are never charged.

Use cases

  • Competitive watch. A list of competitor accounts, run hourly with only-new mode: you pay for new posts and see their engagement next to yours.
  • Engagement benchmarking. engagementPer1kFollowers makes a 9,000-follower account and a 90-million-follower account comparable in the same table.
  • Client and campaign reporting. Post text, time, media and the four counts — the columns a report needs, in CSV.
  • Feeding a dashboard or an LLM. Flat rows, stable field names, ISO timestamps.
  • Keeping an eye on your own brand. Your account plus the accounts that matter to you, on a schedule.

Integration

MCP / AI agents: ask for this Actor by name — foxlabs/x-account-monitor — on the Apify MCP server. It is pay-per-event, so an agent can run it and settle the bill per row.

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('foxlabs/x-account-monitor').call({
accounts: ['@NASA', '@nike'],
maxPostsPerAccount: 10,
onlyNewPosts: true,
listName: 'brands',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((row) => row.type === 'tweet').map((row) => `${row.authorHandle}: ${row.engagement}`));

Python

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("foxlabs/x-account-monitor").call(run_input={
"accounts": ["@NASA", "@nike"],
"maxPostsPerAccount": 10,
})
for row in client.dataset(run.default_dataset_id).iterate_items():
if row["type"] == "tweet":
print(row["authorHandle"], row["likes"], row["url"])

Written for apify-client 3 for Python, where call() returns a run object; with version 1 or 2 read run["defaultDatasetId"].

Automation (n8n / Zapier / Make): schedule or webhook → HTTP request to the Actor API with your account list → handle the JSON dataset → push to a sheet, CRM or dashboard.

Pricing

Pay-per-event: $0.06 per 1,000 delivered posts ($0.00006 each) and $1 per 1,000 account rows ($0.001 each). Status rows and posts left out by a filter are free — you pay for rows you receive.

What you ask forRowsApprox. cost
100 accounts × 25 newest posts, with account rows2,500 posts + 100 accounts~$0.25
1,000 accounts watched hourly, only-new mode, ~2 new posts each per hour~2,000 posts/hour~$0.12/hour
One account, 100 newest posts100 posts~$0.006

You also pay Apify for the compute the run uses, which is small: one HTTP read per account, no browser. Apify's free tier includes $5/month of credits.

Limits — what this Actor cannot do

These are not omissions; they are what X's embed backend serves (measured 2026-10-18):

  • No paging. An account's newest page only: 23–105 posts depending on the account. maxId, cursor and friends return the same page, so there is no way to walk history.
  • No search. No keyword, hashtag, list or moment timelines.
  • No reply texts. A post's reply count yes, the replies themselves no.
  • No follower lists.
  • No view counts. X does not state the view count on an embedded post.
  • Protected accounts are not readable, and an account X has no public record of comes back as a free status row.

If you need search or history, use an Actor built for it — ours is built to watch accounts cheaply and reliably.

FAQ

Do I need an X account, login or API key? No. This reads X's public embed service.

How fresh is the data? Every run reads live; scrapedAt says when.

Why do I get 23 posts for one account and 105 for another? That is how many X embeds for that account. The cap you set is an upper bound, not a promise.

Can I watch 1,000 accounts? Yes — one read per account, eight at a time by default. Use only-new mode so you pay for new posts only.

What does a handle cost extra? One lookup on a residential address the first time (a handle lookup from a datacenter address is rate-limited by X). The id is then remembered in your own key-value store and later runs take the cheap road. Give numeric ids and no lookup is ever needed.

Why is a post missing? It is older than the newest page, it was left out by a filter, or it is already in your only-new list.

Troubleshooting

What you seeWhat it means
X's embed backend is rate-limiting handle lookups from this addressThe residential lookup for that handle did not get through. Run again, or give the account's numeric id.
X embedded nothing for @…No public account with that name, or it is suspended or protected. Free row.
… was read but X embedded no post for itThe account exists and has nothing embeddable (only replies, or protected posts). Free row.
Nothing new: … already in the listOnly-new mode working: no new posts since the last run. Nothing charged.
Run ends FAILED with did not answer the opening checkX did not answer us at all. Nothing was read or charged; try again.

This Actor reads a public embed service with no login and collects what X itself publishes on public profiles. It stores no private data and no credentials. Always check your own use against X's Terms of Service and the data-protection rules that apply to you, especially if you keep personal data or use it for monitoring individuals.

Support & contact

Found a defect or need a field that is missing? Open an issue on the Actor's Issues tab with the run id — every run keeps a SOURCE_REPORT record with what it saw, read, delivered and left out, which makes a report quick to answer.

Changelog

0.1 — 2026-10-18

  • First release. Accounts by handle, profile address or numeric id; the newest page of posts with likes, reposts, replies, quotes and the engagement figures we compute; one row per account; only-new mode with its own list; filters for replies, age and engagement; handle → id remembered between runs; free status rows for every line that cannot be delivered.

Part of the foXLabs data platform — public-data company, contact, social, procurement and AI-search intelligence scrapers.