X (Twitter) Tweet Details Scraper — URL to Full Record
Pricing
from $0.30 / 1,000 tweets
X (Twitter) Tweet Details Scraper — URL to Full Record
Paste tweet addresses or ids; get each tweet's current likes, replies, reposts and quotes, its text, media, links and flags, and its author's full account record (followers, bio, website, verification). Reads tweets of any age. No login, no API key.
Pricing
from $0.30 / 1,000 tweets
Rating
0.0
(0)
Developer
Berkan Kaplan
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
X (Twitter) Tweet Details Scraper — URL to Full Record 𝕏
Paste tweet addresses or ids; get each tweet's current numbers, its text, media and links — and the full account record of whoever posted it. Reads tweets of any age, including ones from 2006. No login, no API key, no browser: charged per row.
- 🔢 All four engagement counts — likes, replies, reposts, quotes — plus the engagement total, engagement per 1,000 followers of the author and engagement per hour. Every row says in
countsFromwhere its counts came from, because X states only two of the four on a single tweet - 👤 The author's whole record on every row — followers, following, posts, bio, location, website, verification and its type, join date. One read per author, not per tweet, and those reads are not charged to you
- 🕰️ Any age. The tweet endpoint answered id
20(21 March 2006) — history an account timeline cannot reach - 🖼️ Media, links and context — photos and videos with direct URLs and sizes, expanded links, hashtags, mentions, language, the quoted tweet, the tweet it replies to, edit and sensitive flags
- 🤖 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 tweets on other people's websites. For each line you give it asks that service for the tweet, and then, once per author, reads the author's newest embedded page. That second read is what turns a thin answer into a full record: X states a tweet's like count and reply count but not its repost or quote count, and only eight fields about its author (measured 2026-10-19). The author's page states all four counts and the 38-field account.
Use it when you need: the current numbers on tweets you already know; UGC or campaign measurement from a list of links; the account behind a viral post; a check of whether tweets are still up.
Use something else when: you need keyword or hashtag search, reply texts or view counts — X's embed backend serves none of those, so this Actor does not claim them. To watch accounts rather than single tweets, use X (Twitter) Account Monitor; for account records, X (Twitter) Profile Scraper.
Quick start (API)
curl -X POST "https://api.apify.com/v2/acts/foxlabs~x-tweet-details-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{ "tweets": ["https://x.com/jack/status/20", "https://x.com/NASA/status/2111180963661435219"], "enrichAuthor": true }'
Prefer no code? Open the Input tab, paste your tweet links one per line, and click Start.
Getting started (3 steps)
- Paste the links.
https://x.com/NASA/status/2111180963661435219,twitter.com/..., a/photo/1suffix or a bare id (20) — all work, mixed in one list. Duplicate lines are read once and charged once. - Leave author enrichment on. It is what gives you the repost and quote counts and the author's record, and it costs one read per author, not per tweet.
- Turn on
includeAuthorRowsif you also want one row per author, the way the X Profile Scraper delivers them.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
tweets | array | — | Tweet addresses or numeric ids, one per line. Required. |
enrichAuthor | boolean | true | Reads each author's newest page once: adds the repost and quote counts for tweets on that page and the author's full record to every row. Not charged. |
includeAuthorRows | boolean | false | One extra row per author whose page was read. Charged as an author row. |
postedWithinDays | integer | 0 | Only tweets from the last N days (0 = no limit). |
minEngagement | integer | 0 | Only tweets with at least this much engagement. |
maxTweets | integer | 0 | Cost cap for the whole run (0 = every line). |
concurrency | integer | 8 | Tweets read side by side. |
proxyConfiguration | object | Apify Proxy (datacenter) | Everything is asked for by numeric id, which X answers from datacenter addresses — no residential proxy needed. |
Output
One row per tweet (plus one per author with includeAuthorRows). Download as JSON, CSV, Excel or read it from the API.
{"type": "tweet","input": "https://x.com/jack/status/20","id": "20","url": "https://x.com/jack/status/20","text": "just setting up my twttr","createdAt": "2006-03-21T20:50:14.000Z","language": "en","likes": 309218,"replies": 18099,"reposts": 124610,"quotes": 7322,"engagement": 459249,"engagementPer1kFollowers": 36.638,"countsFrom": "author-page","countsComplete": true,"conversationCount": 18099,"media": [],"mediaTypes": [],"hasVideo": false,"hashtags": [],"mentions": [],"links": [],"isEdited": false,"authorId": "12","authorHandle": "jack","authorName": "jack","authorFollowers": 12534906,"authorFollowing": 4620,"authorPosts": 29365,"authorBio": "no state is the best state","authorVerified": true,"authorCreatedAt": "2006-03-21T20:50:14.000Z","authorEnriched": true,"scrapedAt": "2026-10-19T12:26:11.512Z"}
Tweet fields
| Field | Type | Description |
|---|---|---|
input | string | The line of your input this row came from |
id / url | string | Tweet id and its address on x.com |
text | string | The tweet's text as X states it |
createdAt / ageHours | — | ISO 8601 UTC, and hours since it went up |
likes / replies | integer | Always X's own numbers (the tweet endpoint states both) |
reposts / quotes | integer | X's numbers when the tweet is on its author's newest page; null otherwise — never 0 |
countsFrom | string | author-page (all four counts are X's) or tweet-endpoint (likes and replies only) |
countsComplete | boolean | Whether all four counts are filled |
engagement | integer | The counts that are stated, added up |
engagementPer1kFollowers | number | engagement / author followers × 1,000 — comparable across accounts of different sizes |
engagementPerHour | number | How fast it is travelling |
media[] / mediaCount / mediaTypes / hasVideo | — | Photos and videos: type, direct URL, width, height |
hashtags[] / mentions[] / links[] | array | As X states them (links are the expanded addresses) |
language / sensitive / isEdited / isStaleEdit / editCount | — | Language code and the flags X states; null when it states none |
conversationId / inReplyToTweetId / inReplyToHandle | string | The thread, and the tweet this one answers |
quotedTweetId / quotedTweetText | string | The tweet it quotes, when X embeds one |
authorId / authorHandle / authorName / authorFollowers / authorFollowing / authorPosts / authorListedIn / authorBio / authorLocation / authorWebsite / authorVerified / authorVerifiedType / authorCreatedAt / authorProfileImage | — | The author's record, flattened onto the row so a tweet list is a table an analyst can sort. Filled when enrichAuthor is on (authorEnriched says so) |
scrapedAt | string | When this row was read |
A line that cannot be delivered is written as a free type: "status" row with the reason — not a tweet address or id, a tweet X has no public record of (deleted, protected or suspended), an id X does not recognise, or a tweet the run could not read. Status rows are never charged.
Use cases
- Campaign and UGC measurement. A list of links from a brief or a report becomes a table with current numbers and the author behind each post.
- Influencer proof.
engagementPer1kFollowersnext toauthorFollowersshows whether a post actually travelled for the size of its account. - Crisis and reputation watch. Re-run the same list and see how the numbers moved; a deleted tweet comes back as a free status row saying so.
- Research and journalism. Any tweet still public, however old, with its exact timestamp, media and links.
- Feeding a dashboard or an LLM. Flat rows, stable field names, ISO timestamps,
nullwhere X said nothing.
Integration
MCP / AI agents: ask for this Actor by name — foxlabs/x-tweet-details-scraper — 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-tweet-details-scraper').call({tweets: ['https://x.com/NASA/status/2111180963661435219', 'https://x.com/jack/status/20'],enrichAuthor: true,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.map((row) => `${row.authorHandle}: ${row.engagement} (${row.countsFrom})`));
Python
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("foxlabs/x-tweet-details-scraper").call(run_input={"tweets": ["https://x.com/jack/status/20"],"enrichAuthor": True,})for row in client.dataset(run.default_dataset_id).iterate_items():if row["type"] == "tweet":print(row["authorHandle"], row["likes"], row["reposts"], row["countsFrom"])
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): webhook or schedule → HTTP request to the Actor API with your link list → handle the JSON dataset → push to a sheet, CRM or dashboard.
Pricing
Pay-per-event: $0.30 per 1,000 delivered tweets ($0.0003 each) and $1 per 1,000 author rows ($0.001 each, only with includeAuthorRows). Status rows and tweets left out by a filter are free — you pay for rows you receive. The author pages the enrichment reads are not charged: they are our cost, not your row.
| What you ask for | Rows | Approx. cost |
|---|---|---|
| 300 campaign tweets with author records | 300 tweets | ~$0.09 |
| 10,000 tweets, one pass | 10,000 tweets | ~$3.00 |
| 1,000 tweets re-checked daily for a week | 7,000 tweets | ~$2.10 |
You also pay Apify for the compute the run uses, which is small: one read per tweet plus one per author, 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-19):
- No repost or quote count for an old tweet. X states neither on a single tweet; they come from the author's newest page, so a tweet older than that page has them
null.countsFromandcountsCompletesay so on every row instead of filling in zeros. Likes and replies are always X's own. - No view counts. X states none on an embedded tweet.
- No reply texts. The reply count yes; X's conversation endpoint answers 404.
- No search. No keyword, hashtag or list timelines — this Actor works from links you already have.
- Deleted, protected and suspended tweets are not readable and come back as free status rows.
- The rate budget is shared. X's embed backend limits how fast one account may read, across all of its runs — two runs of this family started at the same time will refuse each other's reads (measured 2026-10-19). Run them one after another, and leave the speed setting at its default; a read X refuses is tried again at the end of the run, one at a time.
FAQ
Do I need an X account, login or API key? No. This reads X's public embed service.
Why are reposts and quotes sometimes null? Because X does not state them on a single tweet. They come from the author's newest embedded page; if the tweet is older than that page, nobody can read them this way, and an invented 0 would be worse than an honest null.
What does author enrichment cost me? Nothing per tweet: one read per author per run, and those reads are not charged. 500 tweets from 20 accounts means 520 reads and 500 charged rows.
How old a tweet can it read? Any public one. Measured: id 20 from March 2006.
Can I give the same tweet twice? Yes — duplicate lines are read once and charged once.
How fresh are the numbers? Every run reads live; scrapedAt says when. Re-running the same list is the intended way to track movement.
Troubleshooting
| What you see | What it means |
|---|---|
X has no public tweet with id … | Deleted, protected, suspended or never public. Free row. |
X does not recognise "…" as a tweet id | The number is not a tweet id (X answers 400). Check the address you pasted. Free row. |
Not a tweet: give its address … | The line is neither a tweet address nor a numeric id. Free row. |
… tweets were not on their author's newest page | Those rows have likes and replies from X and null reposts and quotes. Expected for older tweets. |
… author pages could not be read | The enrichment read failed for that author; its tweets still carry likes and replies. |
Run ends FAILED with did not answer the opening check | X did not answer us at all. Nothing was read or charged; try again. |
Is it legal to scrape this data?
This Actor reads a public embed service with no login and collects what X itself publishes on public tweets and 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-19
- First release. Tweet addresses or bare ids, de-duplicated; likes, replies, reposts and quotes with
countsFromsaying which the source stated; author enrichment once per author with the 38-field account record on every row; media, links, hashtags, mentions, quoted and replied-to tweets, edit flags; optional author rows; filters for age and engagement; free status rows for deleted, unrecognised and malformed lines.
Part of the foXLabs data platform — public-data company, contact, social, procurement and AI-search intelligence scrapers.