X Tweet Scraper
Pricing
Pay per usage
X Tweet Scraper
Extract public tweets from X (Twitter) by username or tweet ID. No official API key required.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Ikdem Ben Mbarek
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Scrapes public tweets from X (Twitter) without an official API key and without a browser. Give it one or more handles, tweet IDs, or both. At least one of fromUsers or tweetIds is required.
It reads author timelines and hydrates tweets by ID, then writes each match to the dataset. Search is not supported — X’s search GraphQL is auth-walled for guest traffic, so searchTerms is rejected.
Features
- Timelines from public profiles (
fromUsers) - Direct lookup by tweet ID or
/status/URL (tweetIds) - Date, language, hashtag, engagement, media, and verified filters
- Replies and retweets are off unless you turn them on
- Optional Apify Proxy — pick the groups yourself
- Free runs stop at 10 tweets
Input
Fill in the Console form or pass JSON. You need at least one of fromUsers or tweetIds.
{"fromUsers": ["apify"],"tweetIds": ["https://x.com/apify/status/2087572956683567110"],"maxResults": 50,"language": "en","since": "2025-01-01","includeReplies": false,"includeRetweets": false,"proxyConfiguration": {"useApifyProxy": true}}
| Field | Notes |
|---|---|
fromUsers | Handles, with or without @. |
tweetIds | Numeric IDs or status URLs. Looked up on their own — they do not have to belong to fromUsers. Missing or private tweets are skipped. |
maxResults | How many matching tweets to emit. Default 20. Free users still cap at 10. |
hashtags | Tweet must contain all of them. |
since / until | Inclusive UTC dates (YYYY-MM-DD). |
language | ISO 639-1, e.g. en. |
minLikes / minRetweets / minReplies | Engagement floors. A missing count fails the filter. |
onlyVerified | Verified authors only. |
mediaType | any, text_only, images, video, or links. |
includeReplies / includeRetweets | Default false. |
proxyConfiguration | Standard Apify proxy object. Omit it (or set useApifyProxy: false) to go out directly. Optionally set apifyProxyGroups; the Actor does not pick a group for you. |
If you set several filters, a tweet has to pass all of them.
Output
Each dataset item looks like this:
{"id": "2085359738187854143","url": "https://x.com/apify/status/2085359738187854143","text": "$76 a month turned two competitor posts into 172 warm leads.","lang": "en","createdAt": "2026-08-06T13:38:00.000Z","conversationId": "2085359738187854143","isReply": false,"isRetweet": false,"isQuote": true,"inReplyToId": null,"quotedTweetId": "2084542540099834326","author": {"id": "3510729917","username": "apify","name": "Apify","verified": false,"followers": 12159,"following": 296},"metrics": {"likes": 6,"retweets": 2,"replies": 2,"quotes": 0,"bookmarks": 2,"views": 627},"entities": {"hashtags": [],"mentions": ["MannPriteshh", "InstantlyAI"],"urls": [],"media": []},"source": "Twitter Web App","scrapedAt": "2026-08-19T19:16:23.448Z"}
Fields that X does not provide are null, not omitted. Download the dataset as JSON, CSV, or Excel from the run.
The key-value store also gets an OUTPUT record with pushed, cap, limited, and rateLimited.
Limits
- Public tweets only. Protected accounts and deleted IDs are skipped.
- No keyword / hashtag search. Use a user’s timeline plus filters, or pass IDs.
- Free tier: at most 10 tweets, even when
maxResultsis higher. The cap applies to emitted matching tweets, not upstream page size, so filtering can require extra pages before those 10 are filled.
For longer runs on the platform, consider enabling Apify Proxy and choose the proxy groups that fit the run.
Retries and rate limits
Guest traffic is rate-limited. Each request gets up to 5 attempts:
429and5xxretry with exponential backoff and jitter.Retry-Afteris honored on429. If a proxy is configured, the session/IP rotates before the retry; the guest token stays.403mints a new guest token and a new proxy session, then retries.400is not retried.
If the retry budget runs out after some tweets have already been saved, those tweets stay in the dataset and rateLimited: true is recorded. If nothing was saved yet, the run fails.
How to run
On Apify, open the Actor, set the input, and hit Start.
Locally:
npm installapify run
Input comes from storage/key_value_stores/default/INPUT.json. Results land in storage/datasets/default/.
Paid entitlement uses ENTITLEMENTS_TOKEN and ENTITLEMENTS_STORE_ID (plus the Apify user id). If those are missing, the run is treated as free.
apify loginapify push