X (Twitter) Latest Posts Monitor avatar

X (Twitter) Latest Posts Monitor

Pricing

$0.50 / 1,000 profile reads

Go to Apify Store
X (Twitter) Latest Posts Monitor

X (Twitter) Latest Posts Monitor

Check any public X (Twitter) profile for its latest posts: full text, links, engagement counts, media and author. No login, no cookies, no API key — nothing to get suspended or rate-limited. Built for polling many accounts often rather than deep history: 5 latest posts per profile. Unofficial.

Pricing

$0.50 / 1,000 profile reads

Rating

0.0

(0)

Developer

Simple Actors

Simple Actors

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

Check any public X (Twitter) profile for what it has posted lately — full text, permanent link, publish date, likes, reposts, views, photos and video, newest first. 49 fields per post plus a 33-field author record.

No login, no cookies, no API key, no account of yours involved. It reads what X already renders for logged-out visitors, so there is no session to keep alive, no account to get suspended, and nothing to re-authenticate when it breaks — because there is nothing to break. A run is one request per profile and finishes in about five seconds.

$0.50 per 1,000 profiles read — Apify platform usage included, nothing else to pay. The charge is per profile and does not depend on how many posts come back, so a full read and a check that finds one new post cost the same. A profile that cannot be read — suspended, protected, or no such account — is never charged.

Read this before you start: 5 posts per profile. That is X's limit for a logged-out reader, not a setting, and no option raises it. This is built to check many accounts often — if you need one account's deep history, this is the wrong tool and you will be disappointed.

Unofficial. Not affiliated with, endorsed by, or sponsored by X Corp.

What you can do with it

  • Watch accounts for new posts — run it on a schedule across as many profiles as you like and diff on id. This is what it is for.
  • Follow announcements — agencies, transit operators, emergency services, sports teams and newsrooms post breaking updates to X first.
  • Track engagement — likes, replies, reposts, quotes, bookmarks and views on every post, so you can see which ones travelled.
  • Collect media — photos and videos with direct URLs, dimensions and alt text.
  • Feed a dashboard or an alert — full post text and links, ready to route.

How to use it

Paste one or more accounts:

{
"startUrls": [{ "url": "https://x.com/NASA" }]
}

A profile URL, a twitter.com URL or a link to one of their posts all work — the account is taken from whichever you give.

If what you have is handles rather than links, put them in handles instead. Both lists are read as one, so a mixed source is fine:

{
"startUrls": [
{ "url": "https://x.com/NASA" },
{ "url": "https://twitter.com/WHO" }
],
"handles": ["espn", "@natgeo"]
}

They are two inputs rather than one because Apify checks the URL list is really URLs before the run starts, so a bare handle cannot travel in it.

What you get

One dataset item per post, newest first. A shortened example:

{
"type": "tweet",
"id": "2090877991228264814",
"url": "https://x.com/NASA/status/2090877991228264814",
"text": "Launching soon, our newest space telescope @NASARoman is equipped with tools to help it spot and study exoplanets orbiting distant stars.\n\nLearn about these tools and how they work in our newest NASA's Curious Universe podcast on Roman: https://t.co/nCZCpF1MIO",
"likeCount": 878,
"replyCount": 65,
"retweetCount": 138,
"quoteCount": 6,
"bookmarkCount": 39,
"viewCount": 411170,
"createdAt": "Fri Aug 21 19:05:34 +0000 2026",
"createdAtIso": "2026-08-21T19:05:34.000Z",
"timestamp": 1787339134000,
"isReply": false,
"isQuote": false,
"isPinned": false,
"isLongForm": false,
"mentions": ["NASARoman"],
"urls": ["https://go.nasa.gov/45FxOK8"],
"media": [
{
"type": "video",
"mediaUrl": "https://pbs.twimg.com/media/HQRKc2lWgAAtNGa.png",
"videoUrl": "https://video.twimg.com/amplify_video/.../7INz5crAEofwRbWp.mp4",
"durationMillis": 28361,
"width": 720,
"height": 406
}
],
"quote": null,
"author": {
"userName": "NASA",
"name": "NASA",
"id": "11348282",
"followers": 92346035,
"following": 118,
"isBlueVerified": true,
"verifiedType": "Government",
"description": "Making the seemingly impossible, possible. ✨",
"location": "Pale Blue Dot",
"profilePicture": "https://pbs.twimg.com/profile_images/...jpg"
},
"profileUrl": "https://x.com/NASA",
"scrapedAt": "2026-08-22T04:17:01.155Z"
}

The field names are the ones already used by widely-used X post datasets, so code written against those reads this output unchanged.

Dates

Every post carries the same instant three ways, because different tools want different things:

FieldExampleFor
createdAtFri Aug 21 19:05:34 +0000 2026X's own format, for existing parsers
createdAtIso2026-08-21T19:05:34.000ZSorting, filtering, spreadsheets
timestamp1787339134000Arithmetic, milliseconds since the epoch

Long posts are returned in full

A post past the classic length limit is stored by X twice: a visible copy cut off mid-sentence, and the whole thing separately. This returns the whole thing and sets isLongForm so you know it happened.

Quote posts

When a post quotes another, quote carries the quoted post in the same shape — its own text, author and engagement counts. The quoting post's own counts stay on the top level, so the two are never mixed up. Quoting stops one level deep.

One count X does not give out

If the author restricted who may reply, X does not disclose that post's reply count to a logged-out reader — it reports zero. Passing that on would be wrong, so replyCount is null on those posts and whoCanReply says why ("Community" or "ByInvitation"). Every other count is real.

This is worth knowing if you compare a result against the site while logged in: X shows you the reply count there because you are signed in, and this cannot see it. Likes, reposts, quotes, bookmarks and views are unaffected.

Also on every post

whoCanReply when the author narrowed replies, isEdited with the full editHistoryIds (every version the post has had, oldest first), communityNote when one is attached, socialContext for why X surfaced the post, inReplyToId, displayTextRange, and isArticle.

The author record includes both label systems X uses — affiliateLabel for the organisation an account belongs to, and identityLabel with its badge artwork and link for business and government accounts — plus a full-size avatar URL alongside the thumbnail.

Pinned posts

A pinned post is included and flagged isPinned. X returns it first regardless of its age, and it can be years older than the rest — so items are sorted by publication date, not by the order X sends them.

When a post links somewhere, card carries the preview X built for it: title, description, domain, and a preview image with dimensions. Everything X supplied is kept under card.bindings, so card types this does not name — live broadcasts, polls — are still readable.

Media

media holds photos and videos with dimensions, duration, alt text and any title or description. videoUrl is the best-quality MP4, videoVariants lists every rendition with its bitrate if you want a smaller file, and streamUrl is the HLS playlist for adaptive playback in a player.

The flat urls, mentions, hashtags and cashtags arrays cover the common case. entities carries the same things in full: for each link, the t.co as it appears in the post text, the address it expands to, and the short form X displays — plus the character positions, so you can substitute links back into the text. Mentions carry the account ID as well as the handle.

On a long post these come from the same copy of the text you get in text, so the positions always line up and nothing in the tail is missed.

Media URLs are signed by X and expire within hours. Download them promptly; do not store them as long-term links. The post's url is the stable one.

What an empty result means

An empty dataset means the account was read and has posted nothing in the window you asked for. It never means "we could not look".

An account that cannot be read is reported as its own row carrying error and errorDescription, so one bad account in a batch never costs you the rest:

errorMeaning
not_foundNo such account
not_availableSuspended, withheld in this region, or otherwise restricted
protectedPosts are visible only to approved followers, so a login would be needed
window_too_wideonlyPostsNewerThan reaches further back than this run can see — see below
read_failedX did not serve a readable page after several attempts

If every account in a run fails, the run itself fails, so a scheduled job cannot mistake a bad run for a quiet day.

What it costs

$0.50 per 1,000 profiles read. One profile read is one charge, so asking for five profiles in one run costs five. There is no per-post fee and no per-run fee.

Because the charge is per profile, what you pay per post depends on how many posts a read returns:

Posts returned by a readWorks out at
5 — a full read$0.10 per 1,000 posts
3$0.17 per 1,000 posts
1 — a poll that found one new post$0.50 per 1,000 posts

So the price rewards full reads and costs the same on a quiet one. If you are polling with onlyPostsNewerThan and most checks come back empty, budget by profiles checked rather than by posts collected — that is the number you are actually billed on.

Two more consequences worth knowing:

  • Take all five posts. Fewer posts cost you no less, because the price is for reading the profile, not for what comes back.
  • Batch your profiles. Sending twenty profiles in one run costs exactly the same as twenty separate runs, but finishes far faster and in a single call.

A profile that cannot be read is never charged, so a list containing a few dead accounts costs only for the live ones.

Settings

SettingDefaultWhat it does
startUrlsAccounts to read, as links: profile URL, twitter.com URL, or a link to one of their posts.
handlesAccounts to read, as handles: NASA, @NASA or nasa. Combined with startUrls.
maxPosts5How many of the latest posts per account. 5 is the ceiling — see Limits.
onlyPostsNewerThanKeep only posts after a point: "20 hours", "last 3 days", or 2026-08-01.
includeRawfalseAttach X's untouched post record under raw. Makes items much larger.
proxyDatacenterApify Proxy settings. Switch to residential only if accounts start coming back unreadable.

onlyPostsNewerThan will refuse rather than mislead

A run sees an account's latest posts and no further back. If your window reaches past them, some posts inside it were never fetched — and returning what was found would read as "this is everything since then".

So the run fails in that case instead, telling you how far back it could actually see. That is what lets an empty result mean "nothing new" and nothing else. A pinned post does not count towards that reach, since it can be years old and would otherwise make any window look covered.

If you hit this, use a shorter window or run more often.

Limits

Five posts per account, per run. This is X's limit, not a setting we chose. X renders five posts to a logged-out reader, then ends the timeline and withholds the cursor that would ask for the next page. maxPosts is capped at 5 and values above it are rejected at input validation rather than silently under-delivered.

If you need an account's deep history, this is the wrong tool — it is built for freshness, not depth. For monitoring, five posts per run is normally plenty: run it more often rather than asking for more.

Original posts only. The logged-out profile timeline carries an account's own posts, including its replies and quote posts, but not its reposts of others.

No search, and no other tabs. X serves nothing to a logged-out reader for search results, the Media tab or the Highlights tab, so this reads profiles only.

Protected accounts cannot be read. They need an approved follower's login, which this deliberately does not have.

lang and source are always null. X does not include them in what it renders to logged-out readers. The fields are present so existing code does not break on their absence.

Call it from the API

curl -s "https://api.apify.com/v2/acts/simple.actors~x-profile-posts/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"startUrls":[{"url":"https://x.com/NASA"}]}'

Note

This reads publicly visible posts only — the same ones anyone can see without logging in. It does not log in, does not use cookies, and cannot reach protected accounts, direct messages, or anything else behind a login.