How to Scrape Twitter/X: Profiles and Tweets Without a Login or API Key
Pass in a list of Twitter/X usernames and get back structured data for each account: full profile stats plus recent tweets with likes, retweets, view counts, replies, bookmark counts, hashtags, mentions, and expanded URLs. Up to 1,000 tweets per account. No login, no developer API key, no browser automation. The NanoScrape Twitter Scraper runs on Apify at $0.0003 per item delivered.
In this tutorial
What you get
For every username you submit, the actor does two lookups behind the scenes: a profile fetch and a timeline fetch. What comes back:
- Per tweet: tweet ID and URL, full text (never truncated), language, timestamp, conversation ID, reply / retweet / quote / pinned flags, retweeted or quoted tweet ID, in-reply-to fields, and the source client.
- Engagement per tweet: reply count, retweet count, like count, quote count, bookmark count, and view count.
- Entities per tweet: hashtags, @mentions with stable user IDs, expanded URLs (the real destination behind t.co shortlinks), cashtags, and media items (photo / video / GIF) with CDN URLs.
- Author profile embedded on every tweet: username, display name, bio, location, website (with expanded URL), follower count, following count, tweet count, listed count, favourites count, media count, profile image URL, banner URL, account creation date, verified status (both legacy blue tick and X Blue), and protected status.
If you only need profile data, set tweetsPerUser to 0 and turn on includeProfileOnlyItems. Each user produces one row where item_type is profile and the tweet field is omitted.
Prerequisites
- A free Apify account. Sign up at the actor page. The free tier gives you $5 of usage credit every month, which covers about 16,000 tweets across your runs.
- A list of Twitter/X usernames, @-prefixed handles, or full profile URLs you want to scrape. All three formats work in the same input field.
Open the actor on Apify
- Open the NanoScrape Twitter/X Profiles + Tweets Scraper on Apify.
- Click Try for free. Sign up with Google or email if you do not have an account. It takes about a minute.
- Apify redirects you to the actor's input editor in Apify Console.
Configure the input
In the Input tab, paste your accounts in the usernames array. Mix formats freely: plain handles, @-prefixed handles, or full profile URLs. The actor normalizes them all before the first API call.
{
"usernames": [
"openai",
"@AnthropicAI",
"https://x.com/GoogleDeepMind"
],
"tweetsPerUser": 20,
"includeReplies": false,
"includeRetweets": true,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"]
}
}Input fields and when to change them:
usernames(required): an array of handles, @-handles, or full x.com / twitter.com profile URLs.tweetsPerUser: 0 to 1000. The default is 20. Set to 0 and enableincludeProfileOnlyItemsif you only need profile stats.includeReplies:falseby default. Set totrueif you want to include tweets that are direct replies to other accounts.includeRetweets:trueby default. Set tofalseto see only original tweets and quotes.includeProfileOnlyItems:falseby default. Enable to also push one extra profile-only row per user (useful when you need the author record without iterating tweets).proxyConfiguration: leave the residential proxy default. X rate-limits datacenter IPs hard. Residential proxy is included in the $0.01 actor-start fee.
tweetsPerUser: 100 and includeRetweets: false. You get the last 100 original posts per account, ready for sentiment analysis or content benchmarking, without retweet noise inflating the count.Run and download results
- Click Start at the bottom of the input page.
- Apify shows a live log. For a batch of 5 accounts at 20 tweets each, the run finishes in under 30 seconds.
- When the status changes to Succeeded, click the Results tab to open the dataset.
- Use the Export button to download as JSON, JSONL, CSV, or XLSX. You can also read the dataset directly via the Apify API or from an n8n, Make, or Zapier workflow.
includeProfileOnlyItems, 3 additional profile rows appear in the dataset.Output structure
Each dataset row has three top-level fields: item_type, tweet, and author. The following example is taken from the actor README output schema (not a live run; field names and structure are accurate, values are illustrative):
{
"item_type": "tweet",
"tweet": {
"id": "1900000000000000000",
"text": "Full tweet text here.",
"lang": "en",
"created_at": "2026-01-15T16:00:24Z",
"is_reply": false,
"is_retweet": false,
"is_quote": false,
"is_pinned": false,
"url": "https://x.com/example_handle/status/1900000000000000000",
"engagement": {
"reply_count": 186,
"retweet_count": 638,
"like_count": 2444,
"quote_count": 12,
"bookmark_count": 89,
"view_count": 484164
},
"entities": {
"hashtags": [],
"mentions": [{"username": "another_handle", "user_id": "999999999"}],
"urls": [
{
"url": "https://t.co/exampleShort",
"expanded_url": "https://example.com/blog/post",
"display_url": "example.com/blog/post"
}
],
"cashtags": [],
"media": [{"type": "photo", "url": "https://pbs.twimg.com/media/..."}]
}
},
"author": {
"username": "example_handle",
"display_name": "Example Company",
"bio": "Example bio for the account.",
"location": "Example City",
"website_expanded": "https://example.com",
"verified": false,
"blue_verified": true,
"followers_count": 12345,
"following_count": 188,
"tweet_count": 4200,
"created_at": "Tue Sep 01 08:38:01 +0000 2015",
"profile_url": "https://x.com/example_handle"
},
"scraped_at": "2026-07-27T09:00:00Z"
}A few fields worth calling out:
tweet.textis always the full, untruncated text, even for long-form X Premium posts.entities.urls[].expanded_urlresolves the t.co shortlink to the real destination URL. Useful for lead research and tracking shared articles.entities.mentions[].user_idis the mentioned user's stable internal ID. User IDs never change even when someone changes their handle.engagement.view_countmay be 0 for tweets posted within the last few minutes. X populates the count with a short delay.author.blue_verifiedis the X Blue subscription badge.author.verifiedis the legacy verified badge for public figures.
Protected accounts, rate limits, and caveats
- Protected accounts: the actor fetches the profile metadata but cannot retrieve tweets, since tweets on protected accounts are only visible to approved followers. The profile data is still returned in the output.
- Suspended or deleted accounts: silently skipped. They do not appear in the dataset.
- Rate limits: the actor uses residential proxies and rotates to a fresh session if X rate-limits a proxy IP. It retries up to
maxIPRotationstimes (default 5) before logging an escalation. For very large batches (thousands of accounts), consider splitting across multiple runs. - View count delay:
engagement.view_countis sometimes 0 for tweets posted in the past few minutes. If you need accurate view counts, wait a few minutes after a tweet goes live before scraping.
Use with n8n or Make
The actor runs on Apify's public API, so any tool that can make an HTTP POST can trigger it. The simplest path in n8n or Make is the Apify run-sync endpoint, which blocks until the run finishes and returns the dataset as a JSON array.
n8n
Install the Apify n8n node (pre-installed on n8n Cloud; add via Community Nodes on self-hosted). Use the Run an Actor and get dataset operation. Set Actor ID to santamaria-automations/twitter-x-profiles-tweets-scraper, paste your input JSON, and wire the output to a Google Sheets Append node, a database node, or wherever you want the data to land.
For a scheduled monitor: replace the Manual Trigger with a Schedule Trigger, and use a Set node before the Apify node to build the usernames array dynamically from a Google Sheet, Airtable, or any other source. Use an n8n Cloud account if you want a managed instance with no maintenance.
Make (formerly Integromat)
Use the HTTP module to POST to the Apify run-sync endpoint. The URL pattern is:
https://api.apify.com/v2/acts/santamaria-automations~twitter-x-profiles-tweets-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN
Set the content type to application/json and pass your input in the request body. Make returns the full dataset as a parsed JSON array in one step.
Use with AI agents via MCP
The actor is available as an MCP tool for any AI client that supports the Model Context Protocol: Claude Desktop, Claude.ai, Cursor, VS Code, LangChain, LlamaIndex, and others. Add the server to your MCP configuration:
https://mcp.apify.com?tools=santamaria-automations/twitter-x-profiles-tweets-scraper
Once connected, you can give your AI agent instructions like:
- "Fetch the 30 most recent original tweets from these 5 competitor accounts. Skip retweets and replies. Show me a table of tweet text, likes, retweets, and view count."
- "Scrape the profiles for these 20 handles and compare their follower counts, tweet counts, and verified status."
- "Get the last 50 tweets from @openai that mention 'safety'. Return only the tweet text, like count, and timestamp."
add-actor. You do not need to configure the tool parameters manually.What it costs
- Actor start: $0.01 per run. This one-time fee covers the container startup, X session bootstrap, and the first user lookup.
- Per item delivered: $0.0003 per tweet row or profile-only row written to the dataset.
- Free tier: Apify gives you $5 of usage credit every month. After the $0.01 start fee, that leaves $4.99 for items, which is about 16,600 tweets.
Some quick calculations:
- 1 account, 20 tweets: $0.016
- 50 accounts, 20 tweets each: $0.310
- 1,000 accounts, 5 tweets each (profile monitoring): $1.510
- Daily run for 10 accounts at 50 tweets each, over a month: ~$4.65
FAQ
Do I need a Twitter/X login, developer app, or API key?
No. The actor calls the same public GraphQL endpoint that x.com uses for logged-out browsing. You do not need a personal X account, a Meta developer app, or any X-issued credentials. A free Apify account is all you need.
Can I scrape private (protected) Twitter accounts?
No. Protected accounts are visible only to approved followers. The actor returns the public profile metadata for protected accounts (username, bio, follower count) but cannot retrieve their tweets. The author.is_protected field in the output will be true.
How many tweets can I get per account?
Up to 1,000 tweets per account, controlled by the tweetsPerUser input field. Set it to 0 and enable includeProfileOnlyItems if you only need profile-level data.
Does this work for both twitter.com and x.com handles?
Yes. The actor accepts bare handles, @-prefixed handles, and full URLs on both twitter.com and x.com domains. It normalizes all of them to the same username before making the API calls.
What if X rate-limits the scraper mid-run?
If X returns a rate-limit response, the actor automatically rotates to a fresh residential proxy session and retries. It repeats this up to maxIPRotations times (default 5). If all retry attempts are exhausted, the actor logs an escalation message and stops the run. Splitting a very large batch into multiple smaller runs reduces the chance of hitting rate limits.
How do I get only original tweets and not retweets or replies?
Set "includeReplies": false (the default) and "includeRetweets": false in the input. You will get only original tweets and quote-tweets from the user's timeline.
Is scraping public Twitter/X data legal?
Scraping publicly visible data is generally permitted in most jurisdictions. The hiQ Labs v. LinkedIn ruling in the US established that scraping public profiles does not violate the Computer Fraud and Abuse Act. X's Terms of Service restrict automated access, but ToS violations are a contractual matter, not a criminal one. The legal picture also varies by country and intended use. Consult a lawyer if you have specific compliance questions.
Can I run this on a schedule and track follower growth over time?
Yes. In Apify Console, open the actor and use the Schedules tab to configure a recurring run. In n8n, replace the Manual Trigger with a Schedule Trigger. Each run appends a new batch to the dataset, so you can plot follower count or engagement metrics as a time series by including the scraped_at timestamp in your analysis.
Related resources
- Twitter/X Profiles + Tweets Scraper on Apify: full actor documentation, input schema, and complete field reference.
- Instagram Scraper on Apify: extract public Instagram profile stats and recent posts in the same pay-per-result model.
- Instagram Scraper tutorial: the same workflow applied to Instagram public profiles and recent posts.
- Website Contact Extractor: enrich profiles that list an external website by extracting team emails, phones, and names.