# X User Timeline Tweets Scraper (`automation-lab/x-user-timeline-scraper`) Actor

Extract public X timeline tweets by username with text, timestamps, engagement, media, author context, and canonical source links. No X cookies required.

- **URL**: https://apify.com/automation-lab/x-user-timeline-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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/platform/actors/running/actors-in-store#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 User Timeline Tweets Scraper

Export public **X user timeline tweets** by username or profile URL without supplying X login cookies.
The Actor returns normalized tweet text, timestamps, engagement counters, media links, author identity,
reply/repost context, and canonical source URLs.

Use it for recurring creator monitoring, brand communications research, content analysis, or a one-time timeline export.
Results go to the default Apify dataset, ready for JSON, CSV, Excel, API, webhook, and integration workflows.

### What does X User Timeline Tweets Scraper do?

The Actor turns one or more public X handles into a structured timeline feed.
For each supplied profile, it can:

- fetch the main Tweets timeline;
- fetch the Tweets & Replies timeline;
- include or exclude reposts;
- apply optional `sinceDate` and `untilDate` filters;
- follow public pagination cursors up to the run limit;
- deduplicate pinned or repeated tweet IDs;
- preserve the requested profile separately from the tweet author;
- export media and quoted-post context when publicly displayed.

The output is source-attributed.
Every row includes an `x.com` tweet link and the requested `sourceUsername`.

### Who is it for?

**Social media analysts** can collect a consistent dataset for content and engagement analysis.

**Brand and communications teams** can schedule profile checks and compare new rows between runs.

**Creator partnerships teams** can review public posting activity before campaign outreach.

**Researchers and journalists** can preserve source links while structuring public timeline observations.

**Developers and data teams** can call the Actor from an API, webhook, workflow, or MCP client.

This Actor is deliberately focused on username-to-timeline extraction.
For broad keyword search, profile-only enrichment, or X List monitoring, see the related Actors below.

### Why use this Actor?

- **No user-supplied X cookies:** public profiles are fetched through cookieless public timeline surfaces.
- **Real timeline records:** output is tweet data, not raw page HTML or screenshots.
- **Useful monitoring identity:** `sourceUsername` remains stable even when a profile reposts another author.
- **Typed engagement fields:** replies, reposts, likes, and views are numbers when displayed by the source.
- **Bounded failover:** the Actor checks a small maintained set of public timeline routes and fails clearly if none work.
- **Cost control:** it uses lightweight HTTP extraction rather than launching a browser for every profile.
- **Fair multi-profile limits:** the global item limit is distributed across supplied profiles so one active account does not consume the entire run.

### What data can I extract?

| Field | Meaning |
| --- | --- |
| `tweetId` | Stable X tweet ID |
| `url` | Canonical `x.com` source URL |
| `text` | Public tweet text |
| `createdAt` | ISO timestamp when available |
| `sourceUsername` | Profile requested in the input |
| `authorUsername` | Author of this tweet; may differ for a repost |
| `authorName` | Display name when shown |
| `authorProfileUrl` | Canonical author profile URL |
| `authorAvatarUrl` | Public profile image URL when shown |
| `authorVerified` | Whether a verification badge is shown |
| `replyCount` | Displayed reply count |
| `repostCount` | Displayed repost count |
| `likeCount` | Displayed like count |
| `viewCount` | Displayed view count |
| `mediaUrls` | Public image or video references displayed in the card |
| `isReply` | Whether the card is a reply |
| `isRepost` | Whether the requested profile reposted the card |
| `isPinned` | Whether the tweet is pinned |
| `quotedTweetId` | Quoted tweet ID when present |
| `quotedTweetUrl` | Canonical quoted tweet link |
| `quotedTweetText` | Public quoted text when shown |
| `quotedAuthorUsername` | Quoted post author when shown |
| `scrapedAt` | ISO timestamp for this extraction |

Counts can be absent when X does not display them.
Media availability can also change after the run.

### How to get started

1. Open the Actor input page.
2. Enter one or more handles in **X usernames**, or add public profile URLs.
3. Choose whether to include profile replies and reposts.
4. Set `maxItems` for the total number of rows you need.
5. Optionally add ISO date boundaries.
6. Click **Start**.
7. Open the **Dataset** tab to inspect or download the timeline rows.
8. For monitoring, schedule the same input and compare tweet IDs in downstream storage.

Start with 10–30 items while validating a workflow.
Raise the limit only when you need deeper public history.

### Input parameters

#### `usernames`

An array of public X handles.
Values can be `Apify` or `@Apify`.
Up to 20 unique profiles can be combined in one run.

#### `startUrls`

An array of `https://x.com/<handle>` or `https://twitter.com/<handle>` profile URLs.
URLs and handles are normalized into one deduplicated profile list.

#### `maxItems`

Maximum total rows saved across all profiles.
Allowed range: 1–2,000.
Default: 100.
For multiple profiles, the remaining budget is distributed fairly.

#### `includeReplies`

When `false`, use the profile's main Tweets timeline.
When `true`, use its Tweets & Replies timeline.
Default: `false`.

#### `includeReposts`

Keep cards reposted by the requested profile.
Set this to `false` when you only want posts authored by the profile.
Default: `true`.

#### `sinceDate` and `untilDate`

Optional ISO date or datetime boundaries.
For example, `2026-01-01` or `2026-08-31T23:59:59Z`.
The Actor rejects a lower bound later than the upper bound.

#### `requestDelayMs`

Delay between public timeline page requests.
Allowed range: 0–10,000 milliseconds.
Default: 500 milliseconds.
Increase it for a large run if a public route starts rate-limiting.

### Example input

```json
{
  "usernames": ["OpenAI", "AnthropicAI", "GoogleDeepMind"],
  "maxItems": 30,
  "includeReplies": false,
  "includeReposts": false,
  "requestDelayMs": 750
}
```

This input returns up to 30 normalized timeline rows distributed across the three profiles.
It is suitable for a scheduled brand-monitoring feed.

### Example output

The following shape comes from a current public `Apify` timeline run:

```json
{
  "tweetId": "2087572956683567110",
  "url": "https://x.com/apify/status/2087572956683567110",
  "text": "Everything runs on Apify. One day. San Francisco...",
  "createdAt": "2026-08-12T16:12:00.000Z",
  "sourceUsername": "Apify",
  "authorUsername": "apify",
  "authorName": "Apify",
  "authorProfileUrl": "https://x.com/apify",
  "authorVerified": true,
  "replyCount": 2,
  "repostCount": 4,
  "likeCount": 16,
  "viewCount": 1337,
  "mediaUrls": [
    "https://pbs.twimg.com/media/HPiMidvXgAEpJ53.jpg"
  ],
  "isReply": false,
  "isRepost": false,
  "isPinned": true,
  "scrapedAt": "2026-08-17T20:07:41.953Z"
}
```

Engagement metrics are a snapshot of what the public source displayed during extraction.
They can change after the run.

### How much does it cost to extract X user timeline tweets?

The Actor uses pay-per-event pricing:

- a **$0.003** one-time start event per run;
- a tiered per-tweet `item` event;
- **$0.001268 per tweet on the BRONZE tier**.

At that BRONZE price, before platform-plan differences:

- 10 tweets cost about **$0.01568** including the start event;
- 100 tweets cost about **$0.1298** including the start event;
- 1,000 tweets cost about **$1.271** including the start event.

FREE, SILVER, GOLD, PLATINUM, and DIAMOND plans use their displayed tier price.
The Actor charges only rows accepted for the dataset.
Replies, reposts, and quote context do not create separate event types.

### Monitoring and integration workflows

#### Recurring creator monitoring

Schedule one profile daily.
Store the latest tweet IDs in your database.
Treat unseen IDs as new public posts and send them to a review queue.

#### Multi-brand communications comparison

Supply several brand handles with `includeReposts: false`.
The fair profile budget gives each brand representation in the dataset.
Group records by `sourceUsername` downstream.

#### Content and engagement analysis

Export CSV or connect Google Sheets.
Analyze posting cadence, text themes, links, media presence, and displayed engagement.
Remember that counts are point-in-time observations.

#### Webhook pipeline

Use an Actor run-finished webhook.
Read the default dataset, deduplicate by `tweetId`, and send new rows to a warehouse, Slack, or a custom API.

### Use the Actor with the Apify API

Replace `YOUR_APIFY_TOKEN` with your token.
The API returns a run object; dataset rows are available from the run's default dataset.

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~x-user-timeline-scraper/runs?token=YOUR_APIFY_TOKEN&waitForFinish=120" \
  -H "Content-Type: application/json" \
  -d '{"usernames":["Apify"],"maxItems":10,"includeReplies":false}'
```

#### JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/x-user-timeline-scraper').call({
  usernames: ['Apify'],
  maxItems: 10,
  includeReplies: false,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/x-user-timeline-scraper').call(run_input={
    'usernames': ['Apify'],
    'maxItems': 10,
    'includeReplies': False,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use X timeline data with MCP

#### Claude Code setup

Add the Apify MCP server to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/x-user-timeline-scraper"
```

#### Claude Desktop, Cursor, and VS Code setup

Use this equivalent HTTP configuration in Claude Desktop, Cursor, or VS Code:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/x-user-timeline-scraper"
    }
  }
}
```

Example prompts:

- “Run X User Timeline Tweets Scraper for `Apify` and summarize the latest 10 public posts.”
- “Collect 15 posts each from OpenAI and AnthropicAI, exclude reposts, and compare topics.”
- “Fetch NASA's public Tweets & Replies timeline and return rows containing media.”

MCP clients still use your Apify account and the Actor's active pricing.

### Tips for reliable runs

- Use exact public handles rather than search terms.
- Start with a small item limit before scheduling a large batch.
- Disable reposts when the buyer job is original-author analysis.
- Keep `sourceUsername`; it identifies why a repost is present.
- Use ISO timestamps with `Z` when an exact UTC boundary matters.
- Deduplicate monitoring runs by `tweetId`, not text.
- Increase `requestDelayMs` instead of retrying a rate-limited large run immediately.
- Inspect the run log when a profile produces no rows.

### Limits and failure behavior

Only anonymously reachable public profiles are supported.
Private, suspended, age-gated, deleted, or restricted accounts may return no timeline.

The Actor depends on public, third-party-compatible timeline routes.
Those routes can be rate-limited, challenged, unavailable, or temporarily stale.
The Actor rotates through a bounded route list and fails non-zero if no recognizable timeline is available.
It does not silently return a successful empty dataset for a total upstream failure.

Public timelines may not expose every historical tweet.
Pagination depth depends on the source cursor, and `maxItems` is a cap rather than a completeness promise.
Deleted posts and media can disappear after extraction.

This Actor does not scrape keyword search results, followers, following lists, private posts, bookmarks, direct messages, or authenticated-only content.
It does not ask for X account cookies.

### Troubleshooting

#### “No public timeline tweets matched”

Confirm the handle exists and is public.
Remove narrow date filters and retry a small run.
A valid public profile can also have no matching rows after repost or date filters.

#### “Public timeline data is temporarily unavailable”

The bounded public routes all failed or returned a challenge.
Wait before retrying, keep the run small, and inspect the Apify status page and Actor log.
Do not supply private X credentials.

#### My multi-profile run contains fewer rows for one account

Profiles naturally differ in public activity and available history.
The Actor allocates a fair maximum budget, but it cannot invent rows for a sparse profile.

#### Why are some metrics missing?

The source does not always display every counter.
Missing means “not publicly displayed in that card,” not zero.

### Responsible and legal use

Use this Actor only for public data you are authorized to collect and process.
Follow X's terms, applicable laws, contractual obligations, and your organization's policies.
Do not use the output for harassment, unlawful surveillance, discrimination, or attempts to identify private individuals.

Minimize personal-data collection, define a retention period, secure exports, and honor valid deletion or access requests.
The Actor is a data-collection tool, not legal advice.
You are responsible for the purpose and downstream use of collected data.

### Related Automation Lab Actors

- [Twitter/X Scraper](https://apify.com/automation-lab/twitter-scraper) for broader tweet, profile, and supported search workflows.
- [X Profiles Scraper](https://apify.com/automation-lab/x-profile-scraper) for bulk public profile metadata without timeline rows.
- [Twitter/X Lists Scraper](https://apify.com/automation-lab/twitter-lists-scraper) for public List metadata, members, and List posts.

Choose this Actor when the primary input is one or more usernames and the primary output is their public timeline tweets.

### FAQ

#### Does it require an X login or cookies?

No.
The supported workflow uses anonymously reachable public timeline surfaces.

#### Can it include profile replies?

Yes.
Set `includeReplies` to `true` to use the public Tweets & Replies timeline.

#### Can it exclude reposts?

Yes.
Set `includeReposts` to `false`.

#### Can I scrape multiple profiles?

Yes, up to 20 unique profiles per run.
The total `maxItems` budget is distributed across them.

#### Is this a real-time stream?

No.
Each run captures a public timeline snapshot.
Use an Apify schedule for recurring monitoring.

#### Does it download media files?

No.
It exports public media URLs shown in the timeline card.

#### Does it guarantee complete historical coverage?

No.
The Actor follows available public cursors but cannot exceed history exposed by the current source.

#### How should I detect new tweets between runs?

Persist the `tweetId` field from prior datasets and compare it with the next run.
Treat a previously unseen ID as a new observed timeline row.

# Actor input Schema

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

Public X handles, with or without @. You can combine these with profile URLs below (20 unique profiles maximum).

## `startUrls` (type: `array`):

Public x.com or twitter.com profile URLs. Timeline and profile URL inputs follow the same filters.

## `maxItems` (type: `integer`):

Maximum total tweet records saved across all supplied profiles.

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

Include posts from the profile's Tweets & Replies timeline. When disabled, fetch the main Tweets timeline.

## `includeReposts` (type: `boolean`):

Include posts that the requested profile reposted from another author.

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

Optional ISO date or datetime lower bound, for example 2026-01-01.

## `untilDate` (type: `string`):

Optional ISO date or datetime upper bound, for example 2026-12-31T23:59:59Z.

## `requestDelayMs` (type: `integer`):

Politeness delay between page requests. Increase this if a public timeline mirror rate-limits a large run.

## Actor input object example

```json
{
  "usernames": [
    "Apify"
  ],
  "startUrls": [
    {
      "url": "https://x.com/Apify"
    }
  ],
  "maxItems": 20,
  "includeReplies": false,
  "includeReposts": true,
  "requestDelayMs": 500
}
```

# Actor output Schema

## `overview` (type: `string`):

Open the default dataset with the timeline overview view.

# 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": [
        "Apify"
    ],
    "startUrls": [
        {
            "url": "https://x.com/Apify"
        }
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/x-user-timeline-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": ["Apify"],
    "startUrls": [{ "url": "https://x.com/Apify" }],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/x-user-timeline-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": [
    "Apify"
  ],
  "startUrls": [
    {
      "url": "https://x.com/Apify"
    }
  ],
  "maxItems": 20
}' |
apify call automation-lab/x-user-timeline-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/x-user-timeline-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/w2ZUmnKQVyjXM5R1A/builds/50Ay8A5IQhEI7bj2t/openapi.json
