# X API - Twitter API: Real-Time Tweets, Users & Trends (`apidojo/x-api`) Actor

Call X (Twitter) like a REST API. Search tweets, get profiles, followers, replies, retweeters, list members and trends with one GET request. Live JSON in seconds, $0.004 per successful request on every endpoint. No X developer account, no login, no runs to wait for.

- **URL**: https://apify.com/apidojo/x-api.md
- **Developed by:** [API Dojo](https://apify.com/apidojo) (community)
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 api requests

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## 🐦 X (Twitter) API: Real-Time Tweets, Users, Lists & Trends Over HTTP

Call X (formerly Twitter) data like any REST API. This **X API** is an always-on Apify Standby Actor: send a `GET` request, get JSON back in seconds. No runs to start, no datasets to poll, no X developer account.

Search tweets, look up profiles, page through followers, replies, retweeters, list members and trending topics. All through 15 simple endpoints.

**💰 Pricing:** $0.004 per successful request | **⚡ Response:** live JSON, seconds | **🔓 No X login or API key**

***

### 📋 Table of Contents

1. [How It Works](#-how-it-works)
2. [Quick Start](#-quick-start)
3. [Pricing](#-pricing)
4. [Endpoints](#-endpoints)
5. [Pagination](#-pagination)
6. [Response Format](#-response-format)
7. [Errors & Status Codes](#-errors--status-codes)
8. [Code Examples](#-code-examples)
9. [Free Plan](#-free-plan)
10. [Related Actors](#-related-actors)
11. [FAQ](#-frequently-asked-questions)
12. [Contact](#-contact)

***

### 🧭 How It Works

This Actor runs in [Apify Standby mode](https://docs.apify.com/platform/actors/running/standby). Instead of starting a run and waiting for a dataset, you call an HTTP endpoint and get the result in the response.

| | Classic Actor run | This X API (Standby) |
| --- | --- | --- |
| **How you call it** | Start a run, wait, read the dataset | Plain `GET` request |
| **Latency** | Run startup + scraping | Live response, no startup |
| **Result** | Dataset items | JSON in the HTTP response |
| **Billing** | Per run / per item | **Per request** |
| **Best for** | Large batch jobs | Apps, bots, agents, dashboards |

Every endpoint returns one object or one page of results. Use the `cursor` to get the next page.

***

### 🚀 Quick Start

**1. Get your Apify API token** from [Console → Settings → API & Integrations](https://console.apify.com/settings/integrations?fpr=yhdrb).

**2. Call an endpoint:**

```bash
curl "https://apidojo--x-api.apify.actor/handle/elonmusk" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN"
```

**3. Get JSON back:**

```json
{
  "status": 200,
  "message": "OK",
  "data": {
    "type": "user",
    "userName": "elonmusk",
    "id": "44196397",
    "name": "Elon Musk",
    "followers": 1728,
    "...": "..."
  }
}
```

That's it. That request cost $0.004.

**Authentication:** send your Apify token in the `Authorization: Bearer <token>` header (recommended) or as a `?token=<token>` query parameter. Your token is never forwarded to the upstream service.

***

### 💰 Pricing

One flat price, every endpoint.

| Event | Price | When it fires |
| --- | --- | --- |
| **Request** (`request-event`) | **$0.004** per call | Every successful request that returns data |

- **Same price for every endpoint.** A profile lookup and a page of 20 search results cost the same.
- **You only pay for successful responses.** Invalid requests (`400`), not-found results, rate-limit refusals and upstream errors are **not charged**.
- **No platform fees, no compute units, no runs.** Just the per-request price.

#### Cost Examples

| Scenario | Requests | Cost |
| --- | --- | --- |
| Look up 1 profile | 1 | **$0.004** |
| Fetch 100 tweets by ID | 100 | **$0.40** |
| Search a keyword, 50 pages deep | 50 | **$0.20** |
| Look up 1,000 profiles | 1,000 | **$4.00** |
| 10,000 calls in a month | 10,000 | **$40.00** |

> Paginated endpoints are charged per page. Following a `cursor` is a new request, so 10 pages = 10 requests = $0.04.

***

### 📚 Endpoints

All endpoints are `GET`. Base URL: `https://apidojo--x-api.apify.actor`

#### 👤 Users

| Endpoint | Description | Params |
| --- | --- | --- |
| `/handle/{handle}` | Full profile by handle | `handle` (e.g. `elonmusk`) |
| `/handle/{handle}/about` | "About this account" data: country, account source, username changes, verified since | `handle` |
| `/user/{id}` | Full profile by user ID | `id` (e.g. `44196397`) |
| `/user/{id}/tweets` | A user's tweets | `id`, `cursor` |
| `/user/{id}/replies` | A user's replies | `id`, `cursor` |
| `/user/{id}/followers` | A user's followers | `id`, `cursor` |
| `/user/{id}/followings` | Accounts a user follows | `id`, `cursor` |
| `/search/users` | Search users by keyword | `query` (required), `cursor` |

#### 🐦 Tweets

| Endpoint | Description | Params |
| --- | --- | --- |
| `/search` | Search tweets, supports [X advanced search](https://github.com/igorbrigadir/twitter-advanced-search) operators | `query` (required), `sort` (`Latest` or `Top`), `cursor` |
| `/tweet/{id}` | Full tweet by ID, including quotes, retweets, media and articles | `id` |
| `/tweet/{id}/replies` | Replies to a tweet | `id`, `cursor` |
| `/tweet/{id}/retweeters` | Users who retweeted a tweet | `id`, `cursor` |

#### 📃 Lists

| Endpoint | Description | Params |
| --- | --- | --- |
| `/list/{id}/tweets` | Tweets from a list | `id`, `cursor` |
| `/list/{id}/members` | Members of a list | `id`, `cursor` |

#### 📈 Trends

| Endpoint | Description | Params |
| --- | --- | --- |
| `/trends` | Trending topics for a country | `country` (required, two uppercase letters, e.g. `US`, `GB`) |

> **Tip:** The list ID is the last part of the list URL. In `https://x.com/i/lists/78783491` the ID is `78783491`.

The full OpenAPI spec is available on the Actor's **API** tab in Apify Console.

***

### 🔄 Pagination

Paginated endpoints return a `cursor` with each page. Pass it back to get the next page.

```bash
## Page 1
curl "https://apidojo--x-api.apify.actor/search?query=apify&sort=Latest" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN"

## Page 2
curl "https://apidojo--x-api.apify.actor/search?query=apify&sort=Latest&cursor=CURSOR_FROM_PAGE_1" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN"
```

Stop when the response has no `cursor` or the page comes back empty. Each page is one request ($0.004).

***

### 📊 Response Format

Every response has the same envelope:

```json
{
  "status": 200,
  "message": "OK",
  "data": { }
}
```

| Endpoint type | `data` contains |
| --- | --- |
| Single profile / tweet / about | One object |
| Tweet lists (search, user tweets, replies, list tweets) | `{ "tweets": [...], "cursor": "..." }` |
| User lists (followers, followings, retweeters, user search) | `{ "users": [...], "cursor": "..." }` |
| List members | `{ "tweets": [...] }` (array of user objects) |
| Trends | Array of trend objects |

#### Tweet Object

```json
{
  "type": "tweet",
  "id": "1757983181972930764",
  "url": "https://x.com/ESPNStatsInfo/status/1757983181972930764",
  "twitterUrl": "https://twitter.com/ESPNStatsInfo/status/1757983181972930764",
  "text": "Anthony Davis and Rui Hachimura are the 1st @Lakers duo with 35 points each...",
  "retweetCount": 58,
  "replyCount": 10,
  "likeCount": 158,
  "quoteCount": 8,
  "viewCount": 41230,
  "bookmarkCount": 7,
  "createdAt": "Thu Feb 15 04:20:26 +0000 2024",
  "lang": "en",
  "isReply": false,
  "isRetweet": false,
  "isQuote": false,
  "media": ["https://pbs.twimg.com/media/GGWb69-a0AAj1iA.jpg"],
  "author": {
    "type": "user",
    "userName": "ESPNStatsInfo",
    "id": "53120768",
    "name": "ESPN Stats & Info",
    "isVerified": true,
    "followers": 1828908,
    "following": 61
  }
}
```

Tweets can also include `quote`, `retweet`, `extendedEntities` and `article` (title, preview text, cover image and content blocks for X articles).

#### User Object

Key fields: `id`, `userName`, `name`, `url`, `description`, `location`, `followers`, `following`, `listedCount`, `statusesCount`, `mediaCount`, `favouritesCount`, `isVerified`, `protected`, `profilePicture`, `coverPicture`, `createdAt`, `canDm`.

#### About Object

`accountBasedIn`, `locationAccurate`, `accountSource`, `accountCreatedAt`, `usernameChangeCount`, `usernameLastChangedAt`, `verifiedSince`, `avatarUrl`, `profileImageShape`.

#### Trend Object

`name`, `url`, `query`, `tweetVolume`, `promotedContent`.

***

### ⚠️ Errors & Status Codes

Errors use the same envelope, without `data`. **Requests that return no data are not charged.**

| Status | Meaning | Charged? |
| --- | --- | --- |
| `200` | Success | ✅ $0.004 |
| `400` | Invalid parameters. `errors` lists what's wrong | ❌ |
| `404` | Unknown endpoint or nothing found | ❌ |
| `403` | Access not available on your plan or account | ❌ |
| `429` | Monthly free request limit reached | ❌ |
| `502` | Upstream error, safe to retry | ❌ |
| `503` | Plan check temporarily unavailable, retry shortly | ❌ |

Example `400`:

```json
{
  "status": 400,
  "message": "Bad request",
  "errors": ["query.country: country must be a two-letter uppercase code (e.g. US, GB)"]
}
```

***

### 💻 Code Examples

#### cURL

```bash
curl "https://apidojo--x-api.apify.actor/tweet/1859663799319769336" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN"
```

#### Python

```python
import requests

BASE = "https://apidojo--x-api.apify.actor"
HEADERS = {"Authorization": "Bearer YOUR_APIFY_TOKEN"}

def search_tweets(query, pages=5):
    tweets, cursor = [], None
    for _ in range(pages):
        params = {"query": query, "sort": "Latest"}
        if cursor:
            params["cursor"] = cursor
        res = requests.get(f"{BASE}/search", headers=HEADERS, params=params, timeout=300).json()
        data = res.get("data") or {}
        tweets += data.get("tweets", [])
        cursor = data.get("cursor")
        if not cursor or not data.get("tweets"):
            break
    return tweets

print(len(search_tweets("from:apify", pages=3)))  # max 3 requests = $0.012
```

#### JavaScript / Node.js

```javascript
const BASE = 'https://apidojo--x-api.apify.actor';
const headers = { Authorization: `Bearer ${process.env.APIFY_TOKEN}` };

const res = await fetch(`${BASE}/handle/elonmusk`, { headers });
const { data: user } = await res.json();

const followers = await fetch(`${BASE}/user/${user.id}/followers`, { headers }).then((r) => r.json());
console.log(followers.data.users.length, followers.data.cursor);
```

#### Trending Topics

```bash
curl "https://apidojo--x-api.apify.actor/trends?country=US" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN"
```

***

### 🆓 Free Plan

Apify Free plan users can try this API with a limited number of free requests each month. When the monthly limit is reached, the API answers `429` until the next month. [Subscribe to a paid Apify plan](https://apify.com/pricing?fpr=yhdrb) for unlimited requests.

***

### 🌴 Related Actors

Need bulk exports to a dataset, CSV or Excel instead of live calls? Use our batch scrapers:

| Tool | Best For |
| --- | --- |
| 🐦 **[Tweet Scraper](https://apify.com/apidojo/tweet-scraper?fpr=yhdrb)** | Large keyword, hashtag and profile tweet exports |
| ⚡ **[Twitter Scraper Lite](https://apify.com/apidojo/twitter-scraper-lite?fpr=yhdrb)** | Smaller, quick tweet searches |
| 👤 **[Twitter User Scraper](https://apify.com/apidojo/twitter-user-scraper?fpr=yhdrb)** | Bulk profiles, followers and followings |
| 🏯 **[Twitter List Scraper](https://apify.com/apidojo/twitter-list-scraper?fpr=yhdrb)** | Bulk list tweets and members |
| 💬 **[Twitter Replies Scraper](https://apify.com/apidojo/twitter-replies-scraper?fpr=yhdrb)** | Full reply threads |
| 🪪 **[Twitter Profile Scraper](https://apify.com/apidojo/twitter-profile-scraper?fpr=yhdrb)** | Profile timelines |

***

### ❓ Frequently Asked Questions

#### What is a Standby Actor?

A Standby Actor is an always-running web server on Apify. You call it over HTTP like any API and get the response directly. No runs to start or datasets to read. [Learn more](https://docs.apify.com/platform/actors/running/standby).

#### How much does it cost?

**$0.004 per successful request**, the same for every endpoint. 1,000 requests = $4. Failed and invalid requests are free.

#### Am I charged per tweet or per request?

Per request. A page of search results costs the same as a single profile lookup.

#### Do I need an X (Twitter) developer account?

No. You only need an Apify API token.

#### How do I get more than one page of results?

Pass the `cursor` from the previous response as a query parameter. Each page is a separate $0.004 request. See [Pagination](#-pagination).

#### Can I use X advanced search operators?

Yes. `/search` accepts the same query syntax as X search, e.g. `from:elonmusk since:2025-01-01 min_faves:100`. Test your query on X first. The API returns what X returns and adds no extra filtering.

#### How fast is it?

Responses come back live, usually within seconds. There is no run startup time.

#### Can I use it from an AI agent or bot?

Yes. It's a plain HTTP API with an OpenAPI spec, so it fits LLM tool calls, bots, backends and no-code tools that can make HTTP requests.

#### Where is the data stored?

Nowhere. Results are returned in the HTTP response only. For dataset, CSV or Excel exports, use one of the [batch scrapers](#-related-actors).

#### Can I access private accounts or lists?

No. Only publicly available data is returned.

***

### 📞 Contact

If you need any sort of support, please send an email to **apidojo10@gmail.com**. You name it, we get it.

***

**Ready to call X data like an API?** One endpoint per question, $0.004 per answer, live JSON in seconds. Grab your Apify token and send your first request. 🐦

# Actor input Schema

## Actor input object example

```json
{}
```

# Actor output Schema

## `overview` (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("apidojo/x-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("apidojo/x-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 apidojo/x-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,apidojo/x-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/dVsKL9ViAVYTebPcN/builds/FAie0DDBKoKZjBGU5/openapi.json
