X (Twitter) Tweets & Profiles Scraper
Pricing
from $6.15 / 1,000 results
X (Twitter) Tweets & Profiles Scraper
Scrape public X (Twitter) tweets and profiles by handle or tweet ID. Extract text, author, likes, retweets, replies, quotes, views, followers, bio, hashtags and media. No login needed. Export to JSON, CSV or Excel.
Pricing
from $6.15 / 1,000 results
Rating
5.0
(1)
Developer
Scrapers Lat
Maintained by CommunityActor stats
0
Bookmarked
6
Total users
1
Monthly active users
21 hours ago
Last modified
Categories
Share
X (Twitter) Tweets & Profiles Scraper
Here is one real result, with every field a tweet record returns:
{"id": "2085865635586912359","url": "https://x.com/OpenAI/status/2085865635586912359","text": "https://t.co/zBh8ck0Gbc","author": {"handle": "OpenAI","name": "OpenAI","verified": true,"followers": 5096946},"createdAt": "Fri Aug 07 23:08:15 +0000 2026","conversationId": "2085801349866729975","likeCount": 358,"retweetCount": 3,"replyCount": 37,"quoteCount": 3,"bookmarkCount": 18,"viewCount": 183207,"lang": "zxx","source": "Twitter Web App","isReply": true,"inReplyToTweetId": "2085801349866729975","inReplyToUserId": "4398626122","inReplyToHandle": "OpenAI","isRetweet": false,"isQuote": true,"possiblySensitive": false,"noteTweet": null,"media": [],"entities": {"hashtags": [],"mentions": [],"urls": ["https://x.com/sama/status/2085862292311396515"]},"quotedTweet": {"id": "2085862292311396515","text": "astra is a powerful model and we are working to make it generally available.\n\nwe do not think it is a good strategy to keep powerful models to a chosen few.\n\ngiven its cyber capabilities, we need a little big longer to do do this safely. but hopefully not too long!","author": {"handle": "sama","name": "Sam Altman"}},"retweetedTweet": null,"observedAt": "2026-08-10T14:39:54.066Z"}
The most complete X (Twitter) scraper available for logged-out reads. It returns every field X exposes for each tweet, from full engagement metrics (likes, retweets, replies, quotes, bookmarks, views) to entities, media, and the referenced quote or retweet, plus three modes so you can pull an account's tweets, a full profile, or specific tweets by ID or URL.
📥 Input · 📤 Output · 💰 Pricing · ▶️ Examples
Table of contents
- What it does
- Quickstart
- Input reference
- Output reference
- Example output record
- Run via API and CLI
- Fetch results
- Billing and limits
- FAQ and troubleshooting
What it does
The actor reads public X (Twitter) data through X's guest GraphQL endpoints and writes one normalized record per tweet or profile to the run's dataset. Pick a mode:
userTweets(default): pull a public account's recent posts. One record per tweet.userProfile: pull profile details (bio, followers, counts). One record per handle.tweet: fetch specific tweets by numeric ID or full status URL.
Handles can be provided as @name, name, or a profile URL; duplicates are removed. Missing source values are returned as null. Longform note-tweets are returned with their full untruncated text.
Keyword search is shown in the input but is not available: X requires a logged-in account for search, so that mode returns a clear error instead of fake or empty data.
Quickstart
Open the actor, paste this into the input, and press Run. It returns up to 10 recent tweets from the given accounts.
{"mode": "userTweets","handles": ["nasa", "OpenAI"],"tweetsLimit": 10,"maxPosts": 10}
Switch mode to userProfile for profile records, or to tweet and pass tweetIds (IDs or URLs) to fetch specific tweets. Set includeReplies to true to include the account's replies.
Input reference
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
mode | enum | no | userTweets | What to scrape: userTweets, userProfile, tweet, or search (search returns a login-required error). |
handles | string[] | for user modes | ["nasa","OpenAI"] | Public X handles for userTweets and userProfile. Accepts @name, name, or a profile URL. |
tweetsLimit | integer | no | 100 | For userTweets: maximum tweets to collect per handle (paginated). Range 1 to 3200. |
includeReplies | boolean | no | false | For userTweets: also include the account's replies (tweets-and-replies timeline). |
tweetIds | string[] | for tweet mode | (sample) | Numeric tweet IDs (for example 20) or full status URLs such as https://x.com/jack/status/20. |
maxPosts | integer | no | (unbounded) | Maximum posts to collect across all inputs. Caps the whole run. |
searchQuery | string | no | (empty) | Keyword for search mode. Not available (X login-gated); returns a clear error. |
searchType | enum | no | Top | Top or Latest for search mode. Not used (search login-gated). |
lang | string | no | en | Two-letter UI language hint sent to X for localized fields. |
Output reference
Tweet records (userTweets and tweet modes). Types: string, number, boolean, object, object[], or null when the source value is absent.
| Field | Type | Description |
|---|---|---|
id | string | Tweet ID (unique per tweet). |
url | string | Canonical tweet URL on x.com. |
text | string | Tweet text (full untruncated text for longform note-tweets). |
author | object | Author object: handle, name, verified, followers. |
createdAt | string | Tweet creation timestamp as returned by X. |
conversationId | string | ID of the conversation (thread root). |
likeCount | number | Number of likes. |
retweetCount | number | Number of retweets. |
replyCount | number | Number of replies. |
quoteCount | number | Number of quote tweets. |
bookmarkCount | number | Number of bookmarks, or null. |
viewCount | number | Number of views, or null when X does not expose it. |
lang | string | Language code X assigned to the tweet. |
source | string | Posting client label, for example Twitter Web App. |
isReply | boolean | Whether the tweet is a reply. |
inReplyToTweetId | string | ID of the tweet being replied to, or null. |
inReplyToUserId | string | User ID being replied to, or null. |
inReplyToHandle | string | Handle being replied to, or null. |
isRetweet | boolean | Whether the tweet is a retweet. |
isQuote | boolean | Whether the tweet quotes another tweet. |
possiblySensitive | boolean | X sensitivity flag, or null. |
noteTweet | string | Full longform note-tweet text when present, else null. |
media | object[] | Attached media: each object holds type, url, videoUrl, width, height, expandedUrl. |
entities | object | Parsed entities: hashtags, mentions, urls; null when the tweet has none. |
quotedTweet | object | Compact quoted tweet (id, text, author), or null. |
retweetedTweet | object | Compact retweeted tweet (id, text, author), or null. |
observedAt | string | ISO 8601 timestamp of when the record was collected. |
In userProfile mode each record instead holds profile fields: handle, name, bio, website, followers, following, tweetsCount, mediaCount, listedCount, verified, protected, location, joinedAt, pinnedTweetId, avatar, banner, url, id, observedAt. On any failure, a single item with a populated error field is written instead.
Example output record
Real tweet record from a live run (input {"mode":"userTweets","handles":["nasa","OpenAI"],"tweetsLimit":10}):
{"id": "2085865635586912359","url": "https://x.com/OpenAI/status/2085865635586912359","text": "https://t.co/zBh8ck0Gbc","author": {"handle": "OpenAI","name": "OpenAI","verified": true,"followers": 5096946},"createdAt": "Fri Aug 07 23:08:15 +0000 2026","conversationId": "2085801349866729975","likeCount": 358,"retweetCount": 3,"replyCount": 37,"quoteCount": 3,"bookmarkCount": 18,"viewCount": 183207,"lang": "zxx","source": "Twitter Web App","isReply": true,"inReplyToTweetId": "2085801349866729975","inReplyToUserId": "4398626122","inReplyToHandle": "OpenAI","isRetweet": false,"isQuote": true,"possiblySensitive": false,"noteTweet": null,"media": [],"entities": {"hashtags": [],"mentions": [],"urls": ["https://x.com/sama/status/2085862292311396515"]},"quotedTweet": {"id": "2085862292311396515","text": "astra is a powerful model and we are working to make it generally available.\n\nwe do not think it is a good strategy to keep powerful models to a chosen few.\n\ngiven its cyber capabilities, we need a little big longer to do do this safely. but hopefully not too long!","author": {"handle": "sama","name": "Sam Altman"}},"retweetedTweet": null,"observedAt": "2026-08-10T14:39:54.066Z"}
Run via API and CLI
Start a run and wait for it to finish, then read the dataset. Replace <TOKEN> with your Apify API token.
Run synchronously and get dataset items in one call:
curl -X POST "https://api.apify.com/v2/acts/scrapers_lat~x-twitter-scraper/run-sync-get-dataset-items?token=<TOKEN>" \-H "Content-Type: application/json" \-d '{"mode":"userTweets","handles":["nasa"],"tweetsLimit":25}'
Start a run asynchronously:
curl -X POST "https://api.apify.com/v2/acts/scrapers_lat~x-twitter-scraper/runs?token=<TOKEN>" \-H "Content-Type: application/json" \-d '{"mode":"tweet","tweetIds":["https://x.com/BarackObama/status/266031293945503744"]}'
Apify CLI:
apify call scrapers_lat/x-twitter-scraper \--input '{"mode":"userProfile","handles":["OpenAI"]}'
Fetch results
Every run writes to a dataset. Fetch items as JSON, CSV, or Excel by changing format:
# JSONcurl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=json"# CSVcurl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=csv"# Paginate large datasetscurl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&offset=1000&limit=1000"
<DATASET_ID> is returned as defaultDatasetId in the run object. Use offset and limit to page through large result sets. clean=true drops empty and internal fields.
Billing and limits
- Pay per result. You are charged per tweet or profile record returned (
resultevent). See the pricing tab for the current per-result price. - No charge on failure. Handles or tweets that cannot be read (not found, suspended, protected, rate-limited) are written with a populated
errorfield and are not charged. - Spend cap respected. Set
maxTotalChargeUsdon the run; once reached, the actor stops emitting and charging further billable results. - Free Apify plans are capped at 10 records per run. Upgrade for more.
FAQ and troubleshooting
Why can't I search by keyword?
X disabled logged-out (guest) search, so the search mode returns a clear error rather than fake results. Use userTweets to pull a specific account's posts.
How many tweets can I get per account?
Up to tweetsLimit (max 3200), paginated through the account timeline. maxPosts caps the whole run across all handles.
Why did a handle or tweet return an error?
The account or tweet is protected, suspended, deleted, or X rate-limited the request at that moment. Error records are not charged. Re-run rate-limited inputs.
How do I get replies too?
Set includeReplies to true in userTweets mode. If X's replies timeline is temporarily unavailable, the actor falls back to the default timeline so you still get the account's posts.
Is this an official X tool? No. This actor is independent and has no affiliation with X (formerly Twitter). It reads only data that is publicly available to logged-out users.
Related scrapers
- X (Twitter) Profile & Tweets Scraper: profile plus recent tweets in one record per handle.
- Farcaster Casts Scraper: posts and profiles from the Farcaster network.
- Hacker News Scraper: stories, comments, and points from Hacker News.
- Google News Scraper: news articles by query and topic.
- GDELT News & Events Scraper: global news events and coverage.
More scrapers at scrapers.lat
Built and maintained by scrapers.lat, where we publish scrapers for US and Latin American public platforms: company registries, government data, finance, e-commerce and more. Browse the catalog or request a custom scraper at scrapers.lat.
Independent tool, not affiliated with X (formerly Twitter). Accesses only publicly available data. Keyword search is login-gated by X and is not supported.
