# Twitter/X Profile Scraper - Tweets, Likes & Media (`thirdwatch/twitter-scraper`) Actor

Scrape public tweets from any Twitter/X profile. Extracts tweet text, likes, retweets, replies, posted date, and media URLs. No login or API key needed.

- **URL**: https://apify.com/thirdwatch/twitter-scraper.md
- **Developed by:** [Thirdwatch](https://apify.com/thirdwatch) (community)
- **Categories:** Social media, News, AI
- **Stats:** 100 total users, 9 monthly users, 72.1% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.80 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Twitter/X Profile Scraper

> **Thirdwatch portfolio:** 5K users across 88 public Actors, 2M+ records delivered, and >99% run success. [Explore all Thirdwatch Actors](https://apify.com/thirdwatch).

> Scrape public posts from any Twitter/X profile — text, likes, retweets, replies, views, bookmarks, posted dates, and media URLs. No login or API key.

### What you get

Structured post data from any public Twitter/X profile. Pass a list of handles and get back every post's text, engagement metrics, posting date, media URLs, and author info. Useful for monitoring, research, and content analysis without depending on the paid X API.

Two modes:

- **`posts`** (default) — one row per post from each handle's timeline, paginated. Set `maxTweetsPerUser` above 100 to walk months back through a timeline.
- **`profiles`** — one row per handle with the account's public profile: follower and following counts, post count, bio, location, website, verification and account age. No timelines are read, so it is one request per handle.

### Output fields

| Field | Description |
|-------|-------------|
| `text` | Tweet text |
| `likes` | Number of likes |
| `retweets` | Number of retweets |
| `replies` | Number of replies |
| `posted_date` | ISO 8601 tweet timestamp |
| `media_urls` | Attached media URLs |
| `author` | Author handle |
| `url` | Tweet URL |
| `author_name` | Display name from the public tweet payload |
| `author_verified` | Public verified flag when available |
| `views` | View count, from X's own counter |
| `bookmarks` | Bookmark count |
| `quotes` | Quote-post count |
| `is_reply` / `is_retweet` / `is_quote` | Post type flags |
| `quote_tweet_url` | The post this one quotes |
| `hashtags` / `mentions` / `external_urls` | Parsed entities |
| `video_url` | Highest-bitrate MP4 when the post carries video |
| `author_followers` | Author's follower count |
| `author_bio`, `author_location`, `author_website` | Author profile fields |
| `dataSource` | `graphql_user_tweets`, `graphql_tweet`, or the `syndication` fallback |

#### `profiles` mode fields

| Field | Description |
|-------|-------------|
| `username`, `user_id`, `name` | Account identity |
| `followers`, `following` | Audience counts |
| `tweet_count`, `media_count`, `likes_count` | Activity counts |
| `bio`, `location`, `website` | Profile text |
| `verified`, `verified_type`, `is_blue_verified`, `protected` | Account flags |
| `profile_image`, `banner_image`, `created_at`, `profile_url` | Assets and metadata |

### Example output

```json
{
    "text": "Excited to announce our latest product launch...",
    "likes": 15000,
    "retweets": 3200,
    "replies": 800,
    "posted_date": "2026-04-08T14:30:00Z",
    "media_urls": ["https://pbs.twimg.com/media/..."],
    "author": "elonmusk",
    "url": "https://twitter.com/elonmusk/status/..."
}
```

### Input parameters

| Parameter | Required | Description |
|-----------|----------|-------------|
| `usernames` | Yes | List of Twitter/X handles to scrape (without the `@` symbol). Example: `["elonmusk", "sundarpichai"]`. |
| `mode` | No | `posts` (default) for timelines, `profiles` for account details only. |
| `maxTweetsPerUser` | No | Maximum posts to extract per profile. Default `15`, max `3000`. |
| `tweetUrls` | No | Individual post URLs or IDs to fetch. Can be combined with `usernames`. |
| `sinceDate` | No | Drop posts older than `YYYY-MM-DD`. Pagination stops at this boundary, so it makes deep runs cheaper. |
| `includeReplies`, `includeRetweets`, `onlyReplies`, `onlyWithMedia`, `minLikes` | No | Post filters. |
| `proxyConfiguration` | No | Defaults to the standard Apify Proxy. The endpoint this Actor uses is not IP-gated, so the expensive residential group is not needed. |

### Use cases

- **Social media analysts**: Track engagement metrics and posting patterns per account.
- **Brand monitoring**: Watch official brand accounts and executive handles for announcements.
- **Content researchers**: Collect tweet corpora for sentiment and topic analysis.
- **Journalists**: Pull public timelines for background and quote verification.
- **Investor research**: Monitor founder and exec accounts for product and company signals.

### Use cases & recipes

Step-by-step guides on [thirdwatch.dev/blog](https://thirdwatch.dev/blog):

- [Build a Twitter Data Pipeline for Research (2026 Guide)](https://thirdwatch.dev/blog/build-twitter-data-pipeline-for-research)
- [Monitor Influencer Tweets at Scale (2026 Guide)](https://thirdwatch.dev/blog/monitor-influencer-tweets-at-scale)
- [Scrape Twitter/X Profiles Without API at Scale (2026)](https://thirdwatch.dev/blog/scrape-twitter-profiles-without-api)
- [Track Brand Mentions on Twitter/X at Scale (2026)](https://thirdwatch.dev/blog/track-brand-mentions-on-twitter)

### Pricing

Pay-per-result pricing. Tiered discounts apply automatically based on usage volume.

| Tier | Price per result |
|------|------------------|
| FREE | $0.003 |
| BRONZE | $0.0025 |
| SILVER | $0.002 |
| GOLD | $0.0016 |

### Limitations

- Only public accounts — protected accounts cannot be scraped, and are reported as such rather than returned empty.
- **No keyword search.** X gated every unauthenticated search surface: its `SearchTimeline` GraphQL operation, and every legacy REST and syndication search path, refuse a guest session. This Actor is profile-first by necessity, not by preference. Anything advertising logged-out X keyword search is either using an account pool or a third-party mirror.
- **No replies to someone else's post.** `TweetDetail` is gated the same way. Replies *written by* a scraped handle do appear in its timeline.
- No follower or following lists — also gated.
- A handful of very large accounts are served from an X edge cache that returns roughly 100 posts and no pagination cursor. For those, ~100 posts is the ceiling regardless of `maxTweetsPerUser`.
- When the guest timeline returns nothing, the Actor falls back to X's syndication embed. That path is heavily rate-limited, so it is a backstop rather than the main route.

### Compared to alternatives

- **vs. apidojo/tweet-scraper** ($0.0004/result BRONZE, 48K users): That actor is cheaper per tweet with a broader crawl model (search, lists, conversations). This actor is profile-first: give it a list of handles and get back one clean row per tweet, which is the simpler shape for most monitoring and analytics pipelines.

Pairs well with [Google News Scraper](https://apify.com/thirdwatch/google-news-scraper?fpr=9m2cd6) and [Reddit Scraper](https://apify.com/thirdwatch/reddit-scraper?fpr=9m2cd6) for broad social listening.

### FAQ

**Do I need X API credentials?**
No. The actor works without login or API keys.

**Does it include replies and retweets?**
Replies from the handle are included when publicly visible. Retweets appear as separate rows with the original author attributed in `text`/`url`.

**How many posts can I pull per profile?**
The timeline is paginated, so `maxTweetsPerUser` can go well past 100 — hundreds of posts, months back. A few very large accounts are edge-cached by X at ~100 posts with no cursor.

**Can I search by keyword instead of handle?**
No. X does not serve keyword search to logged-out clients on any endpoint, so this Actor does not pretend to. It is profile-first. For keyword discovery use a news or search scraper.

**Do I need residential proxies?**
No. The public endpoint this Actor uses answered 10/10 requests through ordinary Apify datacenter IPs in testing.

Last verified: 2026-09

More scrapers at [thirdwatch.dev](https://thirdwatch.dev).

# Actor input Schema

## `usernames` (type: `array`):

List of Twitter/X handles to scrape (without the @ symbol).

## `mode` (type: `string`):

`posts` returns one row per post from each handle's timeline. `profiles` returns one row per handle with the account's public profile and follower counts, and does not read timelines.

## `maxTweetsPerUser` (type: `integer`):

Maximum number of posts to extract per profile. The timeline is paginated, so values well above 100 are supported; deeper runs cost proportionally more.

## `tweetUrls` (type: `array`):

Individual posts to fetch, as x.com/twitter.com status URLs or bare post IDs. Can be combined with Usernames.

## `includeReplies` (type: `boolean`):

Keep posts that are replies inside a conversation. Turn off to get only standalone posts.

## `includeRetweets` (type: `boolean`):

Keep retweets of other accounts. Turn off to get only original posts.

## `onlyWithMedia` (type: `boolean`):

Keep only posts that carry an image, GIF or video.

## `minLikes` (type: `integer`):

Drop posts below this like count. 0 keeps everything.

## `sinceDate` (type: `string`):

Drop posts older than this date (YYYY-MM-DD). Pagination stops once the timeline is older than this, so setting it makes deep runs cheaper.

## `onlyReplies` (type: `boolean`):

Keep only posts that are replies. Useful for reading how an account responds to people rather than what it broadcasts.

## `proxyConfiguration` (type: `object`):

Proxy used to reach X. The default Apify Proxy is enough: the public GraphQL endpoint this Actor uses is not IP-gated. Switch to RESIDENTIAL only if you see upstream blocks.

## Actor input object example

```json
{
  "usernames": [
    "elonmusk"
  ],
  "mode": "posts",
  "maxTweetsPerUser": 15,
  "tweetUrls": [],
  "includeReplies": true,
  "includeRetweets": true,
  "onlyWithMedia": false,
  "minLikes": 0,
  "onlyReplies": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "usernames": [
        "elonmusk"
    ],
    "mode": "posts",
    "maxTweetsPerUser": 15
};

// Run the Actor and wait for it to finish
const run = await client.actor("thirdwatch/twitter-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "usernames": ["elonmusk"],
    "mode": "posts",
    "maxTweetsPerUser": 15,
}

# Run the Actor and wait for it to finish
run = client.actor("thirdwatch/twitter-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "usernames": [
    "elonmusk"
  ],
  "mode": "posts",
  "maxTweetsPerUser": 15
}' |
apify call thirdwatch/twitter-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,thirdwatch/twitter-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/DAgsx8v83anrHGRpV/builds/S4dx7JECm3RBkh0NG/openapi.json
