# X / Twitter Scraper — Clean Data API (`ladra/x-twitter-scraper-clean-data`) Actor

Extract public X posts into duplicate-free clean JSON. No buyer API keys. Never fabricates results. Pay only for delivered unique posts.

- **URL**: https://apify.com/ladra/x-twitter-scraper-clean-data.md
- **Developed by:** [Ladra Software](https://apify.com/ladra) (community)
- **Categories:** Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.25 / 1,000 validated unique posts

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 / Twitter Scraper — Clean Data API

Extract public X (Twitter) posts into **clean, duplicate-free JSON** with engagement metrics, author profiles, and media.

**Store promise:** never fabricates posts to hit a quota. Empty or blocked sources → warnings + receipt, not filler rows.

**No buyer API keys.** Paste handles, URLs, search terms, lists, or conversation IDs — pay only for **delivered unique posts**.

### Why this Actor

| Need | What you get |
|---|---|
| Reliable post lookup | Public status URLs work with zero keys (public embed path) |
| Profiles, search, lists, threads | When the publisher enables a data transport (buyers still paste nothing) |
| Enriched fields | Likes, reposts, replies, quotes, views, bookmarks, author meta, media, reply/quote/retweet flags |
| Advanced search | Filters for users, language, verified, media, links, min engagement, date range |
| Clean pipelines | Canonical URLs, post-ID dedupe, exact `maxResults` (up to 50,000) |
| Transparent billing | PPE only for delivered unique posts; receipt is never billed |

### Quick start

#### Public post URLs (zero secrets)

```json
{
  "postUrls": [
    "https://x.com/OpenAI/status/1950240351547248941"
  ],
  "maxResults": 20
}
```

#### Handles + search

```json
{
  "handles": ["Apify"],
  "searchTerms": ["web scraping"],
  "searchType": "Latest",
  "language": "en",
  "excludeRetweets": true,
  "maxResults": 50,
  "includeReplies": false
}
```

#### Lists + conversations + filters

```json
{
  "listUrls": ["https://x.com/i/lists/1234567890"],
  "conversationIds": ["1950240351547248941"],
  "fromUsers": ["OpenAI"],
  "minLikes": 10,
  "sinceDate": "2026-01-01",
  "maxResults": 100
}
```

Buyers never configure tokens. If timelines/search are unavailable, the run warns and still processes any post URLs it can resolve.

### Output

| `record_type` | Description | Billed? |
|---|---|---|
| `post` | One unique validated public post | **Yes** → `validated-unique-post` |
| `receipt` | Counts, transport, resource plan, warnings | **Never** |

#### Example post (enriched)

```json
{
  "record_type": "post",
  "id": "1950240351547248941",
  "url": "https://x.com/OpenAI/status/1950240351547248941",
  "text": "…",
  "author_handle": "OpenAI",
  "author_name": "OpenAI",
  "author": {
    "handle": "OpenAI",
    "name": "OpenAI",
    "is_blue_verified": true,
    "followers_count": 1000000,
    "profile_image_url": "https://…"
  },
  "published_at": "2025-07-30T12:00:00+00:00",
  "language": "en",
  "conversation_id": "1950240351547248941",
  "is_reply": false,
  "is_quote": false,
  "is_retweet": false,
  "like_count": 1200,
  "retweet_count": 340,
  "reply_count": 88,
  "quote_count": 12,
  "view_count": 50000,
  "bookmark_count": 90,
  "media": [],
  "source": "x_data_api"
}
```

`source` is one of: `x_public_oembed` | `x_api_v2` | `x_data_api` (never names an upstream vendor).

### Pricing (pay-per-event)

| Event | When | Paid plans (≈) | Free plan (≈) |
|---|---|---|---|
| `validated-unique-post` | Each unique post delivered | **$0.34–$0.40 / 1K** | **$8.00 / 1K** (deterrent) |

| Plan | USD / post | USD / 1K |
|---|---:|---:|
| FREE | $0.00800 | $8.00 |
| BRONZE | $0.00040 | $0.40 |
| SILVER | $0.00039 | $0.39 |
| GOLD | $0.00037 | $0.37 |
| PLATINUM | $0.00035 | $0.35 |
| DIAMOND | $0.00034 | $0.34 |

Not billed: receipts, duplicates, empty runs, warnings, failed fetches.

### How keys work (publisher vs buyer)

| Role | What they do |
|---|---|
| **Buyer (Store user)** | Input JSON only — no OpenAI, no X developer account, no third-party keys |
| **Publisher** | Sets a data transport once on the Actor so handles/search/lists work for everyone |

This matches market leaders: “No API key” for the person running the Actor.

AI/sentiment is **not** bundled — export JSON and analyze in your own stack (or a separate analysis Actor later).

### Input fields

| Field | Description |
|---|---|
| `postUrls` | Public status URLs |
| `handles` | Profile timelines |
| `searchTerms` | Search queries (supports X advanced-search operators) |
| `listUrls` | Public list URLs |
| `conversationIds` | Root tweet IDs for thread/conversation pull |
| `maxResults` | Unique post cap (**1–50,000**) |
| `includeReplies` | Include replies on profile timelines |
| `searchType` | `Latest` or `Top` (third-party search) |
| `fromUsers` / `mentionUsers` | Author / mention filters |
| `language` | ISO 639-1 code (e.g. `en`) |
| `onlyVerified` / `mediaOnly` / `linksOnly` | Boolean search filters |
| `excludeReplies` / `excludeRetweets` | Drop replies / retweets from search |
| `minLikes` / `minRetweets` | Minimum engagement (third-party transport) |
| `sinceDate` / `untilDate` | `YYYY-MM-DD` date bounds |
| `maxConcurrency` | Parallel fetches (1–16) |
| `resourceProfile` | `safe` / `speed` / `manual` |
| `memoryMbytes` | Preferred run memory |

### Memory

Dynamic defaults typically **512–2048 MB** (max **4096**). Console override wins.

### Limitations

- Public oEmbed path is for **status URLs**, not firehose search without publisher transport.
- Search windows depend on the publisher’s data transport (official X recent search is often ~7 days).
- `minLikes` / `minRetweets` apply on the third-party transport; official X API ignores them with a warning.
- Private/suspended posts fail with a warning — no synthetic substitutes.
- Comply with X Terms and applicable law for your use case.

### Support

Include run ID + receipt when reporting issues. Target: first response within **24 hours** when published.

### Changelog

See [CHANGELOG.md](../CHANGELOG.md).

# Actor input Schema

## `postUrls` (type: `array`):

Public x.com or twitter.com status URLs. Works with no API keys (public embed path).

## `handles` (type: `array`):

Recent profile posts (e.g. "OpenAI"). Available when the Actor publisher configured a data transport (buyers never paste tokens).

## `searchTerms` (type: `array`):

Search queries. Supports X advanced-search operators (e.g. "apify (from:elonmusk) lang:en -is:retweet"). Combine with the filter fields below. Available when the publisher configured a data transport.

## `listUrls` (type: `array`):

Public X list URLs (e.g. https://x.com/i/lists/1234567890). Requires the publisher data transport.

## `conversationIds` (type: `array`):

Root tweet IDs to pull a thread/conversation (recent-search window). Requires the publisher data transport.

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

Hard upper limit for unique returned posts. The actor never intentionally exceeds this number.

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

Include replies on profile timelines when the data transport is enabled by the publisher.

## `searchType` (type: `string`):

Ranking mode for search queries on the publisher data transport. Latest = chronological; Top = relevance/popularity. Official X API recent search is always chronological.

## `fromUsers` (type: `array`):

Only posts authored by these handles (applied to every search query).

## `mentionUsers` (type: `array`):

Only posts mentioning these handles.

## `language` (type: `string`):

ISO 639-1 language code (e.g. "en", "es", "ja").

## `onlyVerified` (type: `boolean`):

Only posts from verified accounts.

## `mediaOnly` (type: `boolean`):

Only posts containing photos or videos.

## `linksOnly` (type: `boolean`):

Only posts containing links.

## `excludeReplies` (type: `boolean`):

Drop replies from search and timelines.

## `excludeRetweets` (type: `boolean`):

Drop retweets from search and timelines.

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

Only posts with at least this many likes (third-party transport only).

## `minRetweets` (type: `integer`):

Only posts with at least this many retweets (third-party transport only).

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

Only posts on/after this date (YYYY-MM-DD).

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

Only posts on/before this date (YYYY-MM-DD).

## `maxConcurrency` (type: `integer`):

Requested parallel post fetches. Resource profile and run memory may cap this (except profile=manual).

## `resourceProfile` (type: `string`):

How aggressively to use allocated Apify RAM. Safe caps concurrency, speed allows more, manual honors maxConcurrency.

## `memoryMbytes` (type: `integer`):

Optional preferred Apify run memory (power of 2 after rounding). Console run override still wins.

## Actor input object example

```json
{
  "postUrls": [
    "https://x.com/OpenAI/status/1950240351547248941"
  ],
  "maxResults": 20,
  "includeReplies": false,
  "searchType": "Latest",
  "onlyVerified": false,
  "mediaOnly": false,
  "linksOnly": false,
  "excludeReplies": false,
  "excludeRetweets": false,
  "maxConcurrency": 4,
  "resourceProfile": "safe"
}
```

# Actor output Schema

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

Posts and receipt in the default dataset.

## `posts` (type: `string`):

Unique posts delivered this run (billable as validated-unique-post).

# 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 = {
    "postUrls": [
        "https://x.com/OpenAI/status/1950240351547248941"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ladra/x-twitter-scraper-clean-data").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 = { "postUrls": ["https://x.com/OpenAI/status/1950240351547248941"] }

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

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

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

```

## CLI example

```bash
echo '{
  "postUrls": [
    "https://x.com/OpenAI/status/1950240351547248941"
  ]
}' |
apify call ladra/x-twitter-scraper-clean-data --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=ladra/x-twitter-scraper-clean-data",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/7x5zi8wQ9Q2aZDLd5/builds/YMe7MeaTgQQdXGjHc/openapi.json
