X (Twitter) Post Detail Scraper avatar

X (Twitter) Post Detail Scraper

Pricing

from $0.15 / 1,000 results

Go to Apify Store
X (Twitter) Post Detail Scraper

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

Farhan Febrian Nauval

Farhan Febrian Nauval

Maintained by Community

Actor stats

0

Bookmarked

42

Total users

15

Monthly active users

12 hours

Issues response

11 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 (isNoteTweet: true).
  • X Articles — detected with isArticle: true; title, plain-text body and cover image come back under article.
  • 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, _scrapedAt envelope fields so you can join results back to your input list.

How it works

  1. You provide a list of tweet URLs (https://twitter.com/jack/status/20, https://x.com/jack/status/20) or bare status IDs (20).
  2. 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.
  3. 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, the actor by default falls back to a secondary source so you still get a result. Set fallback: false to get primary-source rows only, and maxRetries: 0 to send each request exactly once.

Input

{
"tweets": [
"https://twitter.com/jack/status/20",
"1445078208190291973"
],
"fallback": true,
"maxRetries": 4,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["DATACENTER"]
}
}
FieldTypeDescription
tweetsarrayList 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.
fallbackbooleanDefault true. When the primary source cannot return a tweet, try the secondary source (rows tagged _source: "S2-fallback", simpler shape). false = primary only; a primary failure becomes an error row tagged _source: "S1-primary".
maxRetriesintegerDefault 4 (5 attempts). How many times a failed primary request is re-sent on rate limit, server error, network error, or one guest-token refresh. 0 = one attempt per tweet, no retries.
proxyConfigurationobjectApify 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"
}
}
FieldTypeDescription
_inputstringThe URL or ID exactly as you supplied it. Use this to join results back to your input list.
_sourcestringInternal 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.
_scrapedAtstringISO-8601 UTC timestamp when the record was scraped.
rest_idstringNumeric tweet ID as a string. Stable identifier.
id_strstringSame as rest_id; kept for compatibility with older tooling.
conversation_id_strstringID of the root tweet in the conversation thread. Equals rest_id for top-level tweets.
user_id_strstringNumeric ID of the author.
created_atstringTweet publication time in X's native format.
langstringAuto-detected language code (e.g. en, id, ja).
full_textstringComplete tweet text. For long-form (premium) posts this is the full note body, not the ~280-character preview. For an Article it is only the t.co link — read article instead.
isNoteTweetbooleantrue when the post is a long-form note; full_text then holds the full body and note_tweet the raw note object.
fullTextSourcestringnote_tweet or legacy — which object full_text was taken from.
isArticlebooleantrue when the post is an X Article.
articleobjectPresent only when isArticle is true: rest_id, url, title, preview_text, plain_text (full body as plain text), cover_image_url, first_published_at_secs, modified_at_secs.
display_text_rangearray[start, end] character offsets of the visible portion (excludes trailing media URLs).
favorite_countintegerLike count at scrape time.
retweet_countintegerRetweet count.
reply_countintegerReply count.
quote_countintegerQuote tweet count.
bookmark_countintegerBookmark count.
viewsobjectView counter. count (string) is present when public; state indicates whether counts are exposed.
is_quote_statusbooleantrue if this tweet quotes another tweet.
sourcestringClient used to post the tweet (HTML snippet — typically "Twitter for iPhone", "Twitter Web Client", etc.).
entitiesobjectParsed entities: hashtags, user_mentions, urls, symbols.
extended_entities.mediaarrayEvery photo, video, and animated-GIF attachment, one entry per item with its own id_str/media_key and type (photo, video, animated_gif), in post order — including posts that mix photos and videos. Videos and GIFs carry video_info.variants. Present only when the tweet has media.
authorobjectSnapshot 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:

ValueMeaning
not_foundTweet was deleted, never existed, or the ID is invalid.
privateAuthor's account is protected — only their approved followers can see this tweet.
blockedTweet exists but X declined to serve it (age-restricted, region-blocked, or temporarily unavailable).
invalid_requestInput could not be parsed as a tweet URL or numeric ID.

Filter on _error to triage failed rows.

Pricing

Pay per event:

  • Actor start — $0.005 per GB of run memory (minimum one). This actor is HTTP-only, so 256–512 MB is plenty; the default 4 GB means 4 start events.
  • Result — $0.00075 per dataset row on the Free plan (down to $0.00015 on higher plans). Every row counts, including error rows.
  • Platform usage (compute, proxy) is billed separately at Apify's standard rates.

A run's maximum-cost limit (maxTotalChargeUsd) caps the event charges above: once it is reached, no further rows are pushed and the run is aborted.

Other Sosmed Actors

PlatformActorBest for
Twitter / XX Account ScraperProfile + follower counts for any handle
Twitter / XX Account Tweets ScraperAll tweets from a user's timeline
Twitter / XX Search ScraperKeyword and hashtag search across tweets
BlueskyBluesky Post Detail ScraperSingle post detail on Bluesky
ThreadsThreads Post Detail ScraperSingle post detail on Threads
InstagramInstagram Post Detail ScraperSingle post detail on Instagram
RedditReddit Post Detail ScraperSingle 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.count absent) 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.media carries 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: rows from the secondary source (_source: "S2-fallback") have a different, simpler shape — text instead of full_text, mediaDetails instead of extended_entities, user instead of author, id_str but no rest_id, long-form notes truncated, no retweet_count/reply_count/quote_count. Set fallback: false if your pipeline maps only the primary shape.
  • Articles: full_text of an Article post is just a link. The body is in article.plain_text; rich formatting and inline article media are not included.