Pricing
from $0.15 / 1,000 results
X (Twitter) Post Detail Scraper
Get full detail for any public X (Twitter) tweet by ID or URL. Returns text, media (photos/videos), engagement counts (likes/retweets/replies/views), entities (hashtags/URLs/mentions), and author info. HTTP-only, no login.
Pricing
from $0.15 / 1,000 results
Rating
0.0
(0)
Developer
Actor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Fetch the full detail of any public X (Twitter) tweet by URL or status ID โ text, media, engagement counters, author, timestamp, mentions, and hashtags โ in clean structured JSON.
Why use this actor
- No account / no login required โ paste a tweet URL or status ID and get the data back.
- No API key needed โ X's official API is paid and rate-limited; this actor returns the same data the public web app shows.
- Full tweet text โ including long-form (premium) tweets over 280 characters, returned in
full_text. - Media URLs โ every photo size and video bitrate variant is included in
extended_entities.media. - Engagement counters โ like, retweet, reply, quote, bookmark, and view counts in one shot.
- Author snapshot โ handle, display name, followers, profile image, verified status captured at scrape time.
- Bulk input โ pass a mix of URLs and status IDs in one run; one clean dataset row per tweet.
- Stable JSON output suitable for pipelines, spreadsheets, and databases โ every row carries
_input,_source,_scrapedAtenvelope fields so you can join results back to your input list.
How it works
- You provide a list of tweet URLs (
https://twitter.com/jack/status/20,https://x.com/jack/status/20) or bare status IDs (20). - The actor fetches each tweet the same way X's web app does, then assembles a flat JSON record with full text, media, counters, and author.
- Results stream into your dataset, ready to download as JSON, CSV, or Excel.
You do not need to manage scrapers, browsers, or rotating IPs โ all handled internally. If the primary path is unavailable for an older tweet, the actor automatically falls back to a secondary source so you still get a result.
Input
{"tweets":["https://twitter.com/jack/status/20","1445078208190291973"],"proxyConfiguration":{"useApifyProxy":true,"apifyProxyGroups":["DATACENTER"]}}
| Field | Type | Description |
|---|---|---|
tweets | array | List of tweet URLs or status IDs. Accepts twitter.com/<user>/status/<id>, x.com/<user>/status/<id>, mobile URLs, and bare numeric IDs. Mix freely. |
proxyConfiguration | object | Apify Proxy settings. Datacenter proxy works for most cases; switch to residential for very large jobs. |
Output
Input: https://twitter.com/jack/status/20
{"_input":"https://twitter.com/jack/status/20","_source":"S1-primary","_scrapedAt":"2026-05-18T11:04:30.976327+00:00","rest_id":"20","id_str":"20","conversation_id_str":"20","user_id_str":"12","created_at":"Tue Mar 21 20:50:14 +0000 2006","lang":"en","full_text":"just setting up my twttr","display_text_range":[0,24],"favorite_count":311853,"retweet_count":126211,"reply_count":17883,"quote_count":6481,"bookmark_count":21449,"views":{"state":"Enabled"},"is_quote_status":false,"source":"<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>","entities":{"hashtags":[],"symbols":[],"urls":[],"user_mentions":[]},"author":{"rest_id":"12","screen_name":"jack","name":"jack","description":"no state is the best state","created_at":"Tue Mar 21 20:50:14 +0000 2006","followers_count":7537422,"friends_count":3,"statuses_count":30509,"media_count":2963,"listed_count":33146,"favourites_count":38827,"is_blue_verified":true,"profile_banner_url":"https://pbs.twimg.com/profile_banners/12/1742427520","url":"https://t.co/ZEpOg6rn5L"}}
| Field | Type | Description |
|---|---|---|
_input | string | The URL or ID exactly as you supplied it. Use this to join results back to your input list. |
_source | string | Internal tag for the path used to fetch the record. S1-primary is the fastest, richest path; S2-fallback is a simpler shape used when the primary path is unavailable. |
_scrapedAt | string | ISO-8601 UTC timestamp when the record was scraped. |
rest_id | string | Numeric tweet ID as a string. Stable identifier. |
id_str | string | Same as rest_id; kept for compatibility with older tooling. |
conversation_id_str | string | ID of the root tweet in the conversation thread. Equals rest_id for top-level tweets. |
user_id_str | string | Numeric ID of the author. |
created_at | string | Tweet publication time in X's native format. |
lang | string | Auto-detected language code (e.g. en, id, ja). |
full_text | string | Complete tweet text, including long-form content beyond 280 characters. |
display_text_range | array | [start, end] character offsets of the visible portion (excludes trailing media URLs). |
favorite_count | integer | Like count at scrape time. |
retweet_count | integer | Retweet count. |
reply_count | integer | Reply count. |
quote_count | integer | Quote tweet count. |
bookmark_count | integer | Bookmark count. |
views | object | View counter. count (string) is present when public; state indicates whether counts are exposed. |
is_quote_status | boolean | true if this tweet quotes another tweet. |
source | string | Client used to post the tweet (HTML snippet โ typically "Twitter for iPhone", "Twitter Web Client", etc.). |
entities | object | Parsed entities: hashtags, user_mentions, urls, symbols. |
extended_entities.media | array | Photo, video, and animated-GIF attachments with every size/bitrate variant. Present only when the tweet has media. |
author | object | Snapshot of the tweet's author (handle, display name, followers, profile image, verified status, etc.). |
Error envelope
Tweets that are deleted, protected, or otherwise unreachable return a structured error instead of crashing the run:
{"_input":"https://twitter.com/jack/status/999999999999999999","_error":"not_found","_errorDetail":"S1: TweetUnavailable: NotFound; S2: 404","_source":"S2-fallback","_scrapedAt":"2026-05-18T11:05:14.012345+00:00"}
_error values:
| Value | Meaning |
|---|---|
not_found | Tweet was deleted, never existed, or the ID is invalid. |
private | Author's account is protected โ only their approved followers can see this tweet. |
blocked | Tweet exists but X declined to serve it (age-restricted, region-blocked, or temporarily unavailable). |
invalid_request | Input could not be parsed as a tweet URL or numeric ID. |
Filter on _error to triage failed rows.
Pricing
This actor is billed per result: $8.00 per 1,000 tweets (Tier 6). Each successful tweet = 1 result. Errors (not_found, private, blocked, invalid_request) are not billed.
Other Sosmed Actors
| Platform | Actor | Best for |
|---|---|---|
| Twitter / X | X Account Scraper | Profile + follower counts for any handle |
| Twitter / X | X Account Tweets Scraper | All tweets from a user's timeline |
| Twitter / X | X Search Scraper | Keyword and hashtag search across tweets |
| Bluesky | Bluesky Post Detail Scraper | Single post detail on Bluesky |
| Threads | Threads Post Detail Scraper | Single post detail on Threads |
| Instagram Post Detail Scraper | Single post detail on Instagram | |
| Reddit Post Detail Scraper | Single post + comments thread on Reddit |
Browse the full catalog at apify.com/xtracto.
Notes
- Deleted tweets return
{"_error": "not_found", "_input": "..."}โ they cannot be recovered after the author or X removes them. - Protected accounts cannot be fetched. If the author has set their tweets to "Protected" (followers-only), the tweet returns
{"_error": "private", ...}. - View counts may be missing (
views.countabsent) for very new tweets or accounts that opted out of public view-count display. - Long-form tweets (premium tweets over 280 characters) return the full body in
full_textโ no truncation. - Media variants: when present,
extended_entities.mediacarries every photo size and the full mp4 bitrate ladder for videos, verbatim from X's response โ ready for direct download. - Counters are eventually-consistent and may lag the live network by a few minutes.
- Fallback path: some older tweets are only available via the secondary source (
_source: "S2-fallback"), which returns a slightly simpler shape โreply_countandquote_countmay be absent in that case.
