# X (Twitter) Profile Tweet Scraper (`mrdoe/x-twitter-profile-tweet-scraper`) Actor

Scrape any public X/Twitter account's tweet timeline - text, engagement stats, media, and author info. Give it a handle, @handle, or profile URL. No login, cookies, or session tokens required.

- **URL**: https://apify.com/mrdoe/x-twitter-profile-tweet-scraper.md
- **Developed by:** [MrDoe](https://apify.com/mrdoe) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 tweet scrapeds

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

![X (Twitter) Profile Tweet Scraper](https://api.apify.com/v2/key-value-stores/ZufoLXRwZJKRdXU7w/records/x-scraper--hero.png)

## X (Twitter) Profile Tweet Scraper

**Scrape any public X/Twitter account's tweet timeline** — full text, likes, retweets, replies, quotes, view counts, media, and author details. Give it a handle, an `@handle`, or a profile URL and get one clean row per tweet. No login, no cookies, no session tokens, no account needed.

This Actor is a **Twitter/X scraper**, a **tweet exporter**, and a **profile timeline downloader** rolled into one.

### At a glance

- **Input:** one or more X/Twitter usernames, `@handles`, or profile URLs.
- **Output:** one row per tweet — text, engagement stats, media links, posted date, and author info.
- **Retweets:** automatically resolved to the original tweet's own content, flagged `isRetweet`.
- **Login:** none required — no account, no cookies, no session tokens.
- **Runs on:** the Apify platform — schedule it, call it via API, or wire it into Make/Zapier/Google Sheets.

### What does the X (Twitter) Profile Tweet Scraper do?

Give it a **username** (or several) and it returns that account's public tweet timeline — original tweets, retweets, replies, and quote tweets — paginated back through the account's history up to your `maxResults`. Every tweet is returned as one clean, spreadsheet-ready row.

![Everything visible on a tweet becomes a dataset field](https://api.apify.com/v2/key-value-stores/ZufoLXRwZJKRdXU7w/records/x-scraper--tweet-anatomy.png)

Everything visible on a tweet becomes a dataset field:

| On the tweet                     | Dataset field                                    |
| --------------------------------- | ------------------------------------------------- |
| `NASA` · verified badge           | `author.username`, `author.displayName`, `author.isVerified` |
| The tweet text                    | `text`                                            |
| Photo / video                     | `imageUrls`, `videoUrl`                           |
| 153 replies · 310 retweets · 3,472 likes · 952,801 views | `replyCount`, `retweetCount`, `likesCount`, `viewCount` |
| "Sep 11, 2026"                    | `postedAt` (`YYYY-MM-DD HH:mm`, UTC)              |
| The permalink                     | `url`, `id`                                       |

### Why use this X/Twitter scraper?

- **Scrape any public account's timeline** — one username in, that account's tweets out, fully paginated.
- **Real engagement numbers** — likes, retweets, replies, quotes, and view counts as actual numbers, not placeholders.
- **Retweets handled correctly** — a retweet is returned as the *original* tweet's real text, media, and counts, with `isRetweet: true` and `retweetedBy` telling you who shared it. No garbled "RT @..." text with empty stats.
- **Media links included** — image URLs and the direct video file link for tweets that have them.
- **No login** — no account, no cookies, nothing to connect and nothing to get banned.
- **Standard exports** — JSON, CSV, Excel, XML, or the Apify API.

### What makes this Actor different?

Most Twitter/X scrapers either need your own login cookies (risky, and against X's rules, and your account can get suspended for it) or return raw, jargon-named fields straight off the wire. This one runs **fully logged-out**, resolves retweets to their original content automatically, and returns clean, consistently-typed fields — real numbers for counts, a readable UTC timestamp, and working media URLs — ready to drop into a spreadsheet or database.

### How it works

![How the X Profile Tweet Scraper works](https://api.apify.com/v2/key-value-stores/ZufoLXRwZJKRdXU7w/records/x-scraper--how-it-works.png)

1. **Your input** — one or more usernames, `@handles`, or profile URLs.
2. **The Actor collects the data** — it handles everything between your input and clean results: no login, anti-bot handling, rate limiting, rotating identities over residential IPs, retries, and paging through to your `maxResults`.
3. **Output** — a dataset row per tweet with full text, engagement stats, media, and author info.

### What data you get

| Field                | Description                                                                                          |
| --------------------- | ----------------------------------------------------------------------------------------------------- |
| `url` / `id`           | Tweet permalink and numeric id                                                                        |
| `text`                 | Full tweet text                                                                                       |
| `postedAt`             | Publish time, `YYYY-MM-DD HH:mm` (UTC)                                                                |
| `likesCount`           | Likes                                                                                                  |
| `retweetCount`         | Retweets                                                                                               |
| `replyCount`           | Replies                                                                                                |
| `quoteCount`           | Quote tweets                                                                                           |
| `viewCount`            | View count, when the platform exposes one for that tweet                                              |
| `bookmarkCount`        | Bookmarks, when exposed                                                                                |
| `isRetweet`            | `true` if this row is a retweet - `text`/media/counts are the *original* tweet's                      |
| `retweetedBy`          | The scraped account's username, when `isRetweet` is `true`                                            |
| `isReply`              | `true` if this tweet is a reply                                                                        |
| `inReplyToUsername`    | The account being replied to, when `isReply` is `true`                                                |
| `isQuote`              | `true` if this tweet quotes another tweet                                                              |
| `language`             | Detected tweet language code (e.g. `en`)                                                              |
| `imageUrls`            | Array of image URLs attached to the tweet                                                              |
| `videoUrl`             | Direct link to the tweet's video, at the highest available quality - `null` if there is no video       |
| `author`               | `username`, `displayName`, `isVerified`, `avatarUrl`                                                  |

![Clean, spreadsheet-friendly output fields](https://api.apify.com/v2/key-value-stores/ZufoLXRwZJKRdXU7w/records/x-scraper--clean-fields.png)

### Input parameters

| Parameter             | Type    | Required | Default           | Description                                                                                       |
| ---------------------- | ------- | -------- | ------------------ | --------------------------------------------------------------------------------------------------- |
| `usernames`            | Array   | Yes      | –                  | Bare handle (`nasa`), `@handle`, or full profile URL (`https://x.com/nasa`). One or more accounts.  |
| `maxResults`           | Integer | No       | `20`               | Stop after this many tweets **per account**. Raise it for a fuller export.                          |
| `proxyConfiguration`   | Object  | Yes      | Apify Residential  | A residential proxy is strongly recommended - X rate-limits and flags datacenter IPs.               |
| `notificationWebhookUrl` | String | No     | –                  | Optional Discord/Slack/Zapier/Make webhook URL, pinged with a summary when the run finishes.        |

### Example output

![Example dataset row from the X Profile Tweet Scraper](https://api.apify.com/v2/key-value-stores/ZufoLXRwZJKRdXU7w/records/x-scraper--output.png)

```json
{
    "url": "https://x.com/NASA/status/2098520709056065990",
    "id": "2098520709056065990",
    "text": "On Wednesday, Sept. 16, the four members of Crew-12 will call from the @Space_Station to recap their mission and answer questions from the media.",
    "postedAt": "2026-09-11 21:15",
    "likesCount": 3472,
    "retweetCount": 310,
    "replyCount": 153,
    "quoteCount": 18,
    "viewCount": 952801,
    "bookmarkCount": null,
    "isRetweet": false,
    "retweetedBy": null,
    "isReply": false,
    "inReplyToUsername": null,
    "isQuote": false,
    "language": "en",
    "imageUrls": ["https://pbs.twimg.com/media/HR9k0dSW4AMngYx.jpg"],
    "videoUrl": null,
    "author": {
        "username": "NASA",
        "displayName": "NASA",
        "isVerified": true,
        "avatarUrl": "https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB_400x400.jpg"
    }
}
```

### How to use the X (Twitter) Profile Tweet Scraper

1. Open the Actor.
2. Add one or more **`usernames`** (bare handle, `@handle`, or profile URL).
3. Set **`maxResults`** (per account).
4. Press **Start**.
5. Read the rows in the **Dataset** tab (export JSON / CSV / Excel / XML).

### Usage examples

**Scrape one account's recent tweets**

```json
{ "usernames": ["nasa"], "maxResults": 20 }
```

**Scrape several accounts in one run**

```json
{ "usernames": ["nasa", "@BBCBreaking", "https://x.com/elonmusk"], "maxResults": 50 }
```

**A larger export for analysis**

```json
{ "usernames": ["nasa"], "maxResults": 500 }
```

### Tips for best results

- **Use a residential proxy.** A good residential proxy pool is the single biggest reliability factor. Datacenter IPs get rate-limited fast.
- **`maxResults` is per username**, not per run — 3 usernames at `maxResults: 20` can return up to 60 rows.
- **A retweet row is the original tweet.** If you only want an account's *own* tweets, filter out rows where `isRetweet` is `true`.
- **For a tweet-history archive**, schedule the Actor on the same `usernames` and append new runs' output over time.
- **Protected/private accounts return no data** — their tweets aren't publicly readable, by design.

### Limitations

- **Public accounts only.** Protected, suspended, or nonexistent accounts return no data for that username.
- X rate-limits aggressively; the Actor retries and rotates identities automatically, but very large exports go faster with a bigger residential proxy pool.
- `viewCount` is `null` for tweets where the platform doesn't expose a view count (this varies by tweet age and type).
- A row is a snapshot at collection time; like/retweet/reply counts keep moving after that.
- This Actor reads public tweet timelines only — it doesn't access DMs, private lists, or protected accounts.

### Export formats & integrations

Export the dataset as **JSON, CSV, Excel, or XML** from the Dataset tab or the Apify API. Connect results to Google Sheets, Make, Zapier, Slack, or your own systems via the API and webhooks, and schedule runs to build a tweet-history archive or a brand-mention monitor.

### Frequently asked questions

**Do I need an X/Twitter account or login?**

No. It works fully logged out — no account, no cookies, no session tokens.

**Can I scrape more than one account in a single run?**

Yes. Add as many usernames as you like to the `usernames` array; each gets its own `maxResults`.

**Does it include retweets?**

Yes, and they're resolved to the original tweet's real text, media, and engagement counts rather than the empty-stats retweet action itself. Look at `isRetweet` and `retweetedBy` to identify and, if you want, filter them out.

**Can I download the video from a tweet?**

The dataset row includes `videoUrl`, a direct link to the video file, for tweets that have one. Download it separately with any HTTP client.

**Why did a run return nothing for an account?**

Usually a datacenter proxy IP being rate-limited, a private/protected account, or a typo'd handle. Switch to a residential proxy and double-check the handle.

**What does `viewCount: null` mean?**

The platform doesn't expose a view count for every tweet - it's most consistently available on more recent tweets. `null` isn't an error.

**How many tweets can it collect per account?**

As many as `maxResults`. It pages back through the account's public timeline automatically.

**Is this against X's rules?**

The Actor only reads publicly available data and doesn't log in or use anyone's account. You are responsible for how you use the data — see below.

### Related scrapers

Building a social-media data pipeline? These pair well with this Actor:

- [Instagram Reel & Audio Scraper](https://apify.com/mrdoe/instagram-reel-and-audio-scraper-trending-sound-finder) — Reels by trending audio or by username, with video/audio download.
- [TikTok Scraper](https://apify.com/mrdoe/tiktok-scraper) — profile videos with views, likes, comments and audio/video download.
- [Facebook Marketplace Scraper](https://apify.com/mrdoe/facebook-marketplace-scraper) — listings, prices and locations, no login.
- [YouTube Video Downloader](https://apify.com/mrdoe/youtube-video-downloader) — videos, Shorts, playlists and whole channels as MP4/MP3.

### Support

Found a bug or need another field exposed? Open an issue on the Actor's **Issues** tab in the Apify Console.

### Legal / responsible use

This Actor collects publicly available X (Twitter) data. It does not log in, access private content, or touch any account. You are responsible for how you use the Actor and its output, including compliance with X's Terms of Service, applicable copyright in any media you collect, and the data-protection laws that apply to you (GDPR, CCPA, and others).

# Actor input Schema

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

X/Twitter usernames, e.g. "nasa" - an "@handle" or a full profile URL like "https://x.com/nasa" also work. Scrapes that account's public tweet timeline.

## `maxResults` (type: `integer`):

Stop scraping a given account once this many tweets have been collected for it.

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

Required - X aggressively rate-limits and flags datacenter IPs. A residential proxy is strongly recommended.

## `notificationWebhookUrl` (type: `string`):

Get notified when the run finishes. Paste a Discord or Slack incoming webhook URL to post a message there, or any other webhook endpoint (Zapier, Make, Pipedream, or an email-forwarding webhook service) to receive a JSON summary with a direct dataset download link instead. Leave blank to disable.

## Actor input object example

```json
{
  "usernames": [
    "nasa"
  ],
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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": [
        "nasa"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mrdoe/x-twitter-profile-tweet-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": ["nasa"] }

# Run the Actor and wait for it to finish
run = client.actor("mrdoe/x-twitter-profile-tweet-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": [
    "nasa"
  ]
}' |
apify call mrdoe/x-twitter-profile-tweet-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mrdoe/x-twitter-profile-tweet-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/HlEi35tAJcnacCrMY/builds/QfaEAtBmoqXykAxyM/openapi.json
