# X/Twitter Data API (`nourishing_fort/x-twitter-api`) Actor

Extract tweets, users, media, bookmarks from X.com.

- **URL**: https://apify.com/nourishing\_fort/x-twitter-api.md
- **Developed by:** [quan qing](https://apify.com/nourishing_fort) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 1 monthly users, 14.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.10 / 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

## X/Twitter Scraper — Profile, Tweets & Media API

Scrape public X/Twitter data in one call: **user profile + latest tweets + media + followers**. Export as JSON, CSV, or Excel. No OAuth approval, no login required for public data.

***

### Why use this instead of the X/Twitter API?

| Problem with X API | How this Actor solves it |
|---|---|
| **$100+/month** for Basic tier, $5,000/mo for Pro | **Pay-per-event** — $0.00025 per result. No monthly fee. |
| **OAuth approval** can take days | **No approval needed** — paste a URL or @handle and run |
| **3+ API calls** for profile + tweets + media | **One call** — profile endpoint returns everything in a single run |
| **No email/lead extraction** from bios | **Auto-extracts emails** and links from user bios |
| **Rate limits** (17k reads/mo on Basic) | **No hard cap** — scale to 10k+ profiles with concurrent runs |
| **No followers list** without enterprise tier | **Followers/following** with a browser cookie (free) |
| **JSON only** output | **JSON, CSV, Excel, JSONL** — pick your format |

**Bottom line:** if you need X/Twitter data for lead gen, research, or monitoring — this costs less, starts faster, and extracts more than the official API.

***

### 🚀 Quick Start — One-Call Profile

Paste a profile URL, `@handle`, or numeric user ID, and pull everything in one run.

```json
{
  "profileUrls": "https://x.com/NASA\nhttps://twitter.com/elonmusk"
}
```

Or use any of these input formats (all auto-detected):

```json
{ "handles": "NASA, elonmusk, SpoxCHN_MaoNing" }
```

```json
{ "userIds": "44196397, 813286" }
```

Default output: profile info + latest 20 tweets + media info.

***

### 📥 Input Reference

You pick **who/what** (the target) and **what to extract** (the switches). Mix and match freely.

#### Target (choose one or several)

| Field | What to paste | Example |
|---|---|---|
| `profileUrls` | Full X/Twitter profile URLs, one per line | `https://x.com/NASA` |
| `handles` | @handles, comma- or newline-separated. `@` is optional | `NASA, elonmusk` |
| `userIds` | Numeric user IDs (rest\_id) | `44196397` |
| `searchQuery` | Keyword to search X/Twitter users | `AI researcher` |
| `tweetUrls` | Full tweet URLs, one per line | `https://x.com/user/status/2090877991228264814` |
| `tweetIds` | Numeric tweet IDs | `2090877991228264814` |

#### Extract switches (turn on what you need)

| Switch | Default | What it adds to output |
|---|---|---|
| `getProfile` | ✅ on | bio, followers, following, verified status, account age, avatar, banner |
| `getRecentTweets` | ✅ on | user's latest 20 tweets, text + media + engagement |
| `getRecentMedia` | ❌ off | user's recent image & video posts as separate items |
| `getFollowers` | ❌ off | list of accounts following the user (requires cookie) |
| `getFollowing` | ❌ off | list of accounts the user follows (requires cookie) |
| `getRetweeters` | ❌ off | list of accounts who retweeted a given tweet (requires cookie) |
| `includeBlueVerifiedFollowers` | ❌ off | restrict followers list to blue-check subscribers |
| `includeTweetsForFollowers` | ❌ off | pull latest tweet for each follower (context enrichment) |

#### Count knobs

| Field | Default | Max |
|---|---|---|
| `recentTweetCount` | 20 | 200 |
| `recentMediaCount` | 5 | 50 |
| `followListCount` | 100 | 5000 |

#### Advanced (only when needed)

| Field | When to fill |
|---|---|
| `auth_token` | Required for `getFollowers`, `getFollowing`, `getRetweeters`. X.com auth cookie. |
| `ct0` | Required together with `auth_token`. X.com csrf cookie. |
| `proxyUrl` | Custom HTTP/SOCKS5 proxy if you need a specific exit IP. |

***

### 🔑 Which Identifier to Use?

X/Twitter accounts have **two names**:

| Name | Example | Unique? | Use? |
|---|---|---|---|
| **@handle** (screen name) | `@NASA` | ✅ yes | **yes — always this** |
| Display name | `NASA` | ❌ no | never |

Input accepts `handle` **with or without `@`**. Pasting a full profile URL works too — `@handle` is auto-extracted.

For numeric input (user\_id), find it in any tweet URL like `x.com/123456789/...` where `123456789` is the user\_id.

***

### 📊 Output Fields

Every data item in the dataset is a flat JSON row. Two views are pre-configured:

**User Profile row** (`item_type=user`): @handle, display name, bio, location, links, **extracted email**, **extracted bio links**, account creation date, account age (days), followers/following ratio, verified/blue/protected flags, professional type, business email, fetched timestamp.

**Tweet row** (`item_type=tweet` or `media`): tweet text, tweet URL, created date, language, image/video URLs, like/retweet/reply/quote/view counts, retweet/reply/pinned/quote flags, reply-to handle & id, conversation id.

Filter by `item_type` to slice the data: `user`, `tweet`, `media`, `follower`, `following`, `retweeter`, `search_result`.

***

### 💡 Common Use Cases

**1. Lead generation from a KOL's followers**

```json
{
  "handles": "naval",
  "getFollowers": true,
  "followListCount": 1000
}
```

Then in the dataset, filter `item_type=follower` and sort by `followers_count` desc to find high-value accounts. `bio_has_email=true` flags leads with public contact info.

**2. RAG / LLM knowledge base from a topic influencer**

```json
{
  "handles": "paulg, sama, sama",
  "getRecentTweets": true,
  "recentTweetCount": 100
}
```

Each tweet becomes one row with full text + media URLs + engagement metrics — ready to feed into a vector store.

**3. Market research user profile dump**

```json
{
  "profileUrls": "https://x.com/AIresearcher1\nhttps://x.com/AIresearcher2\n...",
  "getProfile": true,
  "getRecentTweets": false
}
```

Lightweight: just bio, followers, account age. Cheap and fast.

**4. Competitive tweet monitoring**

```json
{
  "handles": "competitor1, competitor2",
  "getRecentTweets": true,
  "getRecentMedia": true
}
```

Both text and media surface in one dataset. Use `view_count` to find viral posts.

**5. Extract retweeters of a viral post**

```json
{
  "tweetIds": "2090877991228264814",
  "getRetweeters": true,
  "followListCount": 500
}
```

Who amplified this post? Perfect for influencer outreach.

***

### ❓ Troubleshooting

| Symptom | Cause | Fix |
|---|---|---|
| Empty dataset, no error | Invalid input — the target doesn't exist or is private | Check the handle/ID; private accounts return no public data |
| `code 353 — Could not authenticate you` | X.com rate-limit / session expired | Wait 60s, retry; the Actor rotates proxies automatically |
| `code 32 — Could not authenticate you` | Cookie expired/invalid | Refresh `auth_token` + `ct0` from a logged-in browser session |
| Followers/following returns empty | Missing or invalid auth cookie | Provide fresh `auth_token` + `ct0` in Advanced fields |
| Email field is empty | Bio doesn't contain a public email | Try alternative accounts; not all users publish email publicly |
| Tweet URLs are short (t.co) | X uses t.co redirects | This is normal — use the `tweet_url` field for the resolved canonical URL |
| Run takes >2 min for one profile | Network throttle or large followers list | Reduce `followListCount`; split into smaller batches |
| Some followers missing | Cursor boundary; X.com only returns first ~1000 per page | Reduce target count; for >1000 use pagination across multiple runs |

***

### ❓ FAQ

**Do I need an X/Twitter developer account or API key?**

No. This Actor scrapes public data from x.com directly. No developer portal, no API key, no OAuth approval. Just paste a URL or @handle and run.

**Is there a free tier? How much does it cost?**

Yes. Apify gives every new account $5 free credit. At $0.00025 per result, that's ~20,000 results free. After that, pay-per-event — no monthly subscription. See the [Pricing](#-pricing-model-pay-per-event) section for cost examples.

**Can I extract followers without the paid X API?**

Yes. Provide a valid `auth_token` + `ct0` cookie from your logged-in x.com browser session. The Actor uses your session to pull followers/following lists — no enterprise API tier needed. See [Authentication & Proxies](#-authentication--proxies).

**Does this work with private or protected accounts?**

No. Protected accounts (locked profiles) return no public data. The Actor only scrapes publicly visible profiles, tweets, and media.

**How many profiles can I scrape in one run?**

There's no hard limit. For best results, keep batches under 200 profiles per run. For 1,000+ profiles, split into multiple runs or use the API for concurrent execution.

**Can I use this for lead generation?**

Yes. The `bio_has_email` and `bio_has_link` fields flag leads with public contact info. Combine with `getFollowers` to extract follower lists from a target KOL's audience, then filter by email presence and follower count.

**What's the difference between @handle and user ID?**

| | @handle (screen\_name) | User ID (rest\_id) |
|---|---|---|
| Example | `@NASA` | `44196397` |
| Changes? | Can be changed by user | Permanent |
| Use | Most common input | When handle is unknown |

Both work as input. The Actor auto-detects which one you provided.

**Can I schedule recurring scrapes?**

Yes. Use Apify Scheduler to run the Actor daily/weekly. Or use the API to trigger runs from a cron job, Airflow, or n8n.

**Does the Actor respect rate limits?**

The Actor rotates proxies automatically and throttles requests to avoid X.com blocks. For large jobs, spread runs across time to stay under the radar.

***

### 🔌 API Integration

#### Start a run

```bash
POST https://api.apify.com/v2/acts/7aVQYR4P86AUB5dFs/runs?token=YOUR_API_TOKEN
Content-Type: application/json

{
  "handles": "NASA, elonmusk",
  "getProfile": true,
  "getRecentTweets": true,
  "recentTweetCount": 50
}
```

#### Wait + fetch (synchronous)

```bash
POST https://api.apify.com/v2/acts/7aVQYR4P86AUB5dFs/run-sync-get-dataset-items?token=YOUR_API_TOKEN
Content-Type: application/json

{
  "handles": "NASA",
  "getRecentTweets": true
}
```

The response includes the full dataset inline as a JSON array.

#### Python SDK

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("7aVQYR4P86AUB5dFs").call({
    "handles": "NASA, elonmusk",
    "getRecentTweets": True,
    "getRecentMedia": True,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["item_type"], item.get("screen_name"))
```

#### Node.js SDK

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('7aVQYR4P86AUB5dFs').call({
    handles: 'NASA, elonmusk',
    getRecentTweets: true,
    getRecentMedia: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach(i => console.log(i.item_type, i.screen_name));
```

#### No-code integrations

This Actor works with any tool that can call a REST API or trigger an Apify run.

**Zapier** — connect to 6,000+ apps:

1. Create a Zap with "Apify — Run Actor" trigger
2. Map your input fields (handles, getProfile, etc.)
3. Use "Apify — Fetch Dataset Items" as the next step
4. Send results to Google Sheets, HubSpot, Notion, Slack, etc.

**n8n** (self-hosted or cloud):

```json
{
  "nodes": [
    {
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "method": "POST",
        "url": "https://api.apify.com/v2/acts/7aVQYR4P86AUB5dFs/run-sync-get-dataset-items",
        "queryParameters": { "token": "YOUR_API_TOKEN" },
        "bodyParameters": { "handles": "NASA", "getRecentTweets": true }
      }
    }
  ]
}
```

**Make (Integromat)**:

1. Add an "HTTP" module → POST to `https://api.apify.com/v2/acts/7aVQYR4P86AUB5dFs/run-sync-get-dataset-items`
2. Pass your API token as query parameter
3. Map the JSON response to downstream modules (Google Sheets, Airtable, email, etc.)

**Airflow / cron**:

```python
## Airflow PythonOperator example
from apify_client import ApifyClient

def scrape_twitter(handles: list[str]):
    client = ApifyClient("YOUR_API_TOKEN")
    run = client.actor("7aVQYR4P86AUB5dFs").call({
        "handles": ",".join(handles),
        "getRecentTweets": True,
    })
    return list(client.dataset(run["defaultDatasetId"]).iterate_items())
```

***

### 💰 Pricing Model (Pay Per Event)

This Actor uses Apify Pay-Per-Event pricing. You only pay for results — no monthly subscription.

| Event | When it fires | Cost |
|---|---|---|
| Dataset item | Each row pushed to dataset (profile, tweet, media, follower, etc.) | $0.00025 |
| Actor start | Once per run (per GB of memory) | $0.001 / GB |

**Store discounts** (automatic at higher usage tiers):

| Tier | Per item price | vs. base |
|---|---|---|
| No discount | $0.00025 | — |
| Bronze | $0.00020 | 20% off |
| Silver | $0.00015 | 40% off |
| Gold | $0.00010 | 60% off |

**Cost examples** (default 4 GB memory, no discount):

| Scenario | Items | Estimated cost |
|---|---|---|
| One profile + 20 tweets | 21 | ~$0.01 |
| 100 profiles, no tweets | 100 | ~$0.03 |
| 1,000 followers from one user | 1,000 | ~$0.25 |
| 10,000 tweets across 50 users | 10,000 | ~$2.70 |

You see the running cost in the Apify Console while the run is in progress.

***

### 🔒 Authentication & Proxies

**Public data** (profiles, tweets, media, search results) — no auth needed. The Actor uses Apify's built-in proxy rotation.

**Authenticated data** (followers, following, retweeters, bookmarks) — requires a valid `auth_token` + `ct0` cookie pair. You can:

1. Log into x.com in your browser
2. Open DevTools → Application → Cookies → x.com
3. Copy the values of `auth_token` and `ct0`
4. Paste them into the Actor's Advanced fields

Cookies are encrypted in transit and discarded after the run.

***

### 📦 Output & Export

After each run, the **Output** tab in Apify Console shows results in a table view. Available exports:

- **JSON** — full structured output
- **CSV** — Excel/Sheets compatible
- **Excel** — formatted xlsx with headers
- **JSONL** — newline-delimited for streaming pipelines

Items are typed by `item_type` so you can filter in your code:

```python
users = [i for i in items if i["item_type"] == "user"]
tweets = [i for i in items if i["item_type"] == "tweet"]
followers = [i for i in items if i["item_type"] == "follower"]
```

***

### ⚡ Performance Notes

- **One profile = ~5–15 seconds** with default switches
- **Followers list scales linearly**: 100 followers ≈ 8s, 1000 followers ≈ 60s, 5000 followers ≈ 5min
- **Proxies rotate automatically** for anonymous operation
- **Concurrent runs supported** — you can launch multiple runs in parallel for batch jobs

***

### 🆚 How It Compares

| Capability | This Actor | Typical alternatives |
|---|---|---|
| One-call profile + tweets + media | ✅ | ❌ usually separate calls |
| Multi-format input (URL/handle/user\_id) | ✅ | partial |
| Bio email auto-extraction | ✅ | ❌ |
| Followers list without API approval | ✅ (with cookie) | requires paid X API tier |
| Pay-per-event pricing | ✅ | ❌ usually monthly subscription |
| Dataset with typed items | ✅ | partial |
| No OAuth approval | ✅ | ❌ |

***

### 📞 Support

- Issues: open a ticket on the Actor's Issues tab in Apify Console
- Documentation: see this README + the Actor's Input/Output tabs
- Status: run the Actor with empty input to get a health-check response

# Actor input Schema

## `profileUrls` (type: `string`):

Paste full X/Twitter profile URLs, one per line. Example: https://x.com/NASA, https://twitter.com/elonmusk. ⚠️ One of the 6 target fields must be non-empty.

## `handles` (type: `string`):

Comma- or newline-separated @handles. The @ symbol is optional. Example: NASA, elonmusk, SpoxCHN\_MaoNing. ⚠️ One of the 6 target fields must be non-empty.

## `userIds` (type: `string`):

Numeric X/Twitter user IDs (rest\_id), comma- or newline-separated. Find one from a profile URL like x.com/user/status/ID. Example: 44196397. ⚠️ One of the 6 target fields must be non-empty.

## `searchQuery` (type: `string`):

Search X/Twitter users by keyword. Returns matching user accounts. Example: AI researcher, marketing director. Note: tweet search is currently disabled by X.com. ⚠️ One of the 6 target fields must be non-empty.

## `tweetUrls` (type: `string`):

Paste full tweet URLs, one per line. Example: https://x.com/user/status/2090877991228264814. ⚠️ One of the 6 target fields must be non-empty.

## `tweetIds` (type: `string`):

Numeric tweet IDs, comma- or newline-separated. Find from tweet URL: x.com/user/status/ID. Example: 2090877991228264814. ⚠️ One of the 6 target fields must be non-empty.

## `getProfile` (type: `boolean`):

Bio, followers, following, verified status, profile image, account age. Always enabled.

## `getRecentTweets` (type: `boolean`):

Pull the user's latest 20 tweets with text, media URLs, likes, retweets, replies, views.

## `recentTweetCount` (type: `integer`):

How many of the user's most recent tweets to pull (default 20, max 200). Requires getRecentTweets.

## `getRecentMedia` (type: `boolean`):

Pull the user's latest image and video posts as separate items.

## `recentMediaCount` (type: `integer`):

How many recent media posts to pull (default 5, max 50). Requires getRecentMedia.

## `getFollowers` (type: `boolean`):

Pull the list of accounts following the target user. Requires auth cookie (auth\_token + ct0).

## `getFollowing` (type: `boolean`):

Pull the list of accounts the target user follows. Requires auth cookie.

## `followListCount` (type: `integer`):

How many accounts to pull from the followers or following list (default 100, max 5000).

## `includeBlueVerifiedFollowers` (type: `boolean`):

Restrict the followers list to blue-checkmark subscribers. Requires getFollowers + auth cookie.

## `getRetweeters` (type: `boolean`):

Pull the list of accounts who retweeted a specific tweet. Provide a tweet URL or ID. Requires auth cookie.

## `includeTweetsForFollowers` (type: `boolean`):

For each follower, also pull their most recent tweet. Adds context to lead lists. Increases cost.

## `auth_token` (type: `string`):

X.com auth\_token cookie value. Required only for followers, following, retweeters, and bookmarks endpoints. Public profiles and tweets work without it.

## `ct0` (type: `string`):

X.com ct0 (csrf) cookie value. Required together with auth\_token for authenticated endpoints.

## `proxyUrl` (type: `string`):

HTTP/SOCKS5 proxy URL if you need a specific exit IP. Leave empty for default rotation.

## Actor input object example

```json
{
  "getProfile": true,
  "getRecentTweets": true,
  "recentTweetCount": 20,
  "getRecentMedia": false,
  "recentMediaCount": 5,
  "getFollowers": false,
  "getFollowing": false,
  "followListCount": 100,
  "includeBlueVerifiedFollowers": false,
  "getRetweeters": false,
  "includeTweetsForFollowers": false
}
```

# Actor output Schema

## `data` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("nourishing_fort/x-twitter-api").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("nourishing_fort/x-twitter-api").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 '{}' |
apify call nourishing_fort/x-twitter-api --silent --output-dataset

```

## MCP server setup

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

```

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/7aVQYR4P86AUB5dFs/builds/aDhWxhpMgcdAk9MRH/openapi.json
