Twitter / X Tweet Scraper API
Our Twitter tweet scraper turns any tweet URL or numeric status id into structured JSON: the full text, the author, favorite and reply counts, language, entities, and any attached media, all from one request with no login and no developer account.
Quickstart
curl "https://api.twitterscraperapi.com/api/v1/xtwitter/tweet?url=https://x.com/jack/status/20&api_key=$API_KEY" import requests, os
BASE = "https://api.twitterscraperapi.com"
API_KEY = os.environ["API_KEY"]
# Pass a full tweet URL or just the numeric status id.
resp = requests.get(
f"{BASE}/api/v1/xtwitter/tweet",
params={
"url": "https://x.com/jack/status/20", # or id="20"
"api_key": API_KEY,
},
timeout=30,
)
tweet = resp.json()
print(tweet["user"]["screen_name"], "-", tweet["text"])
print(tweet["favorite_count"], "favorites,", tweet["reply_count"], "replies")
print("posted", tweet["created_at"], "in", tweet["lang"]) Response
{
"id": "20",
"id_str": "20",
"url": "https://x.com/jack/status/20",
"socialPlatform": "twitter",
"text": "just setting up my twttr",
"full_text": "just setting up my twttr",
"lang": "en",
"created_at": "2006-03-21T20:50:14.000Z",
"favorite_count": 308537,
"reply_count": 17947,
"conversation_count": 17947,
"retweet_count": null,
"quote_count": null,
"views": null,
"possibly_sensitive": null,
"is_edited": false,
"user": {
"screen_name": "jack",
"name": "jack",
"id_str": "12",
"is_blue_verified": true,
"verified": false,
"profile_image_url_https": "https://pbs.twimg.com/profile_images/1661201415899951105/azNjKOSH_normal.jpg",
"url": "https://x.com/jack"
},
"entities": {
"urls": [],
"user_mentions": [],
"hashtags": [],
"symbols": []
},
"media": [],
"thumbnail": null
} | Field | Type | Description |
|---|---|---|
id_str | string | The tweet's numeric status id as a string, the stable identifier for the post. |
url | string | Canonical tweet URL, https://x.com/ |
text | string | The tweet body. full_text carries the same value for consistency with X's own field name. |
lang | string | Detected language of the tweet as a BCP-47 code, e.g. en. |
created_at | string | ISO 8601 timestamp of when the tweet was posted. |
favorite_count | integer | Number of likes. Guaranteed on the response along with reply_count. |
reply_count | integer | Number of replies, taken from conversation_count. Guaranteed on the response. |
conversation_count | integer | Reply count for the conversation, equal to reply_count. |
Use it for
Enrich saved tweet links
Track engagement over time
Social listening and mentions
Embed tweets in your app
Why it is hard
X shut its free API tier in 2023 and now starts paid access around 100 dollars a month, while a logged-out visit to a tweet returns a JavaScript shell that hides the text behind a login wall. Reading one public tweet used to be a single GET; today it is an auth-gated, rate-limited endpoint or a brittle scrape.
Pricing
| Plan | Price | Best for |
|---|---|---|
| Free | 1,000 requests | Testing and small jobs |
| Pro | $0.60 / 1k | Production workloads |
| Pay-as-you-go | $0.90 / 1k | Spiky or one-off volume |
Median response 2.6s. You only pay for successful requests.
FAQ
A Twitter tweet scraper is a tool that reads a public tweet and returns its data in a structured format. Our tweet scraper API takes a tweet URL or a numeric status id and returns the full text, author, created_at timestamp, language, favorite and reply counts, entities, and any media as JSON from a single request, with no login required.
No. You authenticate with a single twitterscraperapi key passed as the api_key query parameter. There is no X developer account to apply for, no OAuth flow, and no paid X API tier, which as of 2023 starts at around 100 dollars a month. The free tier includes 1,000 requests so you can test first.
Either works. Pass the full tweet URL, for example https://x.com/jack/status/20 or a twitter.com/.../status/
Favorite count (likes) and reply count are guaranteed on every response. Retweet count, quote count, and view count are best-effort: X includes them on some tweets but not all, so when they are absent our API returns null for that field rather than omitting it, which keeps the JSON shape stable for your parser.
Yes. The entities object breaks out urls, user_mentions, hashtags, and symbols as arrays, any of which can be empty. Attached photos and video thumbnails come back as URLs in the media array, and the first one is also set as thumbnail, or null when the tweet has no media.
Median end-to-end response is about 2.6 seconds, which includes proxy routing, anti-bot handling, retries, and parsing. One call returns the whole tweet, author, and engagement together, so you do not chain extra requests to assemble a single post.