# Tweet Scraper — X search, $0.15 per 1,000 tweets (`tweetpipe/tweet-scraper`) Actor

Tweets from X (Twitter) search by keyword, URL, handle or filters, newest first. Same input and output as apidojo/tweet-scraper — switch by changing the actor id. Pay only per tweet.

- **URL**: https://apify.com/tweetpipe/tweet-scraper.md
- **Developed by:** [V](https://apify.com/tweetpipe) (community)
- **Categories:** Social media
- **Stats:** 19 total users, 12 monthly users, 99.8% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.15 / 1,000 tweets

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

## Tweet Scraper — Twitter (X) search scraper, $0.15 per 1,000 tweets

Scrape tweets from X (Twitter) search: keywords, hashtags, search URLs,
handles, advanced search operators, filters and date ranges. Newest first
(Latest) or as X ranks them (Top). No X API key, no login, no proxy setup —
pay only for the tweets you get.

- **$0.15 per 1,000 tweets** — less than half of apidojo/tweet-scraper's $0.40.
- **Drop-in apidojo alternative** — the same input fields and the same tweet
  object, so switching is changing one actor id.
- **Fast** — 1,000 tweets in about 2½ minutes (measured on "netflix down",
  Latest).
- **Newest first, no gaps** — a Latest search is read in parallel time
  windows and delivered in order, without holes between them.

### Switching from apidojo/tweet-scraper

Change the actor id; keep your input and your parsing code.

```js
import { ApifyClient } from 'apify-client'

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' })
// was: client.actor('apidojo/tweet-scraper')
const run = await client.actor('tweetpipe/tweet-scraper').call({
  searchTerms: ['netflix down'],
  maxItems: 1000,
  sort: 'Latest',
})
const { items } = await client.dataset(run.defaultDatasetId).listItems()
```

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("tweetpipe/tweet-scraper").call(
    run_input={"searchTerms": ["netflix down"], "maxItems": 1000, "sort": "Latest"}
)
items = client.dataset(run["defaultDatasetId"]).list_items().items
```

### What people use it for

- Brand and product monitoring: every tweet mentioning you, newest first.
- Outage and incident tracking: "is X down" spikes as they happen.
- Sentiment analysis, market and crypto research, academic datasets.
- Lead generation: who tweets about your niche, with their follower counts.
- Feeding tweets into an LLM, a dashboard or a spreadsheet.

### Input

```json
{
  "searchTerms": ["netflix down", "#outage lang:en"],
  "maxItems": 1000,
  "sort": "Latest"
}
```

- `searchTerms` — any X search, advanced search operators included
  (`from:`, `to:`, `"exact phrase"`, `OR`, `-filter:replies`, `since:`, …).
- `startUrls` — X / Twitter search URLs (profile URLs are searched as
  `from:handle`).
- `twitterHandles` — tweets from these accounts.
- `maxItems` — stop after this many tweets (empty = no limit, within your
  maximum charge per run).
- `sort` — `Latest`, `Top`, or `Latest + Top`.
- Filters: `tweetLanguage`, `onlyVerifiedUsers`, `onlyTwitterBlue`,
  `onlyImage`, `onlyVideo`, `onlyQuote`, `minimumRetweets`,
  `minimumFavorites`, `minimumReplies`, `author`, `inReplyTo`, `mentioning`,
  `geotaggedNear`, `withinRadius`, `geocode`, `placeObjectId`, `start`, `end`.
- `includeSearchTerms` adds a `searchTerm` field; `customMapFunction` reshapes
  each tweet.

### Output

One dataset item per tweet — JSON, CSV, Excel or the API:

```json
{
  "type": "tweet",
  "id": "2106518220979200001",
  "url": "https://x.com/example/status/2106518220979200001",
  "twitterUrl": "https://twitter.com/example/status/2106518220979200001",
  "text": "is netflix down for anyone else?",
  "retweetCount": 2,
  "replyCount": 5,
  "likeCount": 14,
  "quoteCount": 0,
  "viewCount": 830,
  "bookmarkCount": 0,
  "createdAt": "Sat Oct 03 22:54:15 +0000 2026",
  "lang": "en",
  "isReply": false,
  "isRetweet": false,
  "isQuote": false,
  "author": {
    "type": "user",
    "userName": "example",
    "url": "https://x.com/example",
    "twitterUrl": "https://twitter.com/example",
    "id": "303570001",
    "name": "Example User",
    "isBlueVerified": false,
    "profilePicture": "https://pbs.twimg.com/profile_images/…_normal.jpg",
    "followers": 210,
    "following": 182
  },
  "entities": { "hashtags": [], "symbols": [], "urls": [], "user_mentions": [] }
}
```

Also on every tweet: `inReplyToId`, `inReplyToUsername`, `conversationId`,
`quoteId` and the quoted tweet, `source`, `extendedEntities` (media), and
the author's bio, location, account age and counts.

### Pricing

Pay per result: **$0.15 per 1,000 tweets**, platform usage included. You are
charged only for tweets in the dataset, and a run stops at your maximum
charge. On Apify's free plan a run is a demo of up to 10 tweets; any paid
plan gets full results.

### FAQ

**Do I need an X (Twitter) API key or account?** No.

**How many tweets can I get?** As many as the search has: runs of a few
thousand tweets finish in minutes, bigger ones take proportionally longer.
Latest goes back as far as X search does; Top returns what X's Top tab shows
(usually a few hundred).

**Is scraping X legal?** This actor reads public tweets only. Check the rules
that apply to how you use the data (for example GDPR for personal data).

### Limits

- Search only in this version: list URLs, single-tweet URLs and reply threads
  are not supported yet.

# Actor input Schema

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

X search URLs (x.com or twitter.com). A profile URL is searched as from:handle. List and single-tweet URLs are not supported yet.

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

What to search for, one per line. Any X search operator works (from:, -filter:replies, "exact phrase", OR, …).

## `twitterHandles` (type: `array`):

Tweets from these accounts (searched as from:handle).

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

Tweets in these conversations (searched as conversation_id:).

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

Stop after this many tweets in total. Empty = as many as the search returns (within your maximum run charge).

## `sort` (type: `string`):

Latest = newest first. Top = what X ranks most relevant. Latest + Top runs both.

## `tweetLanguage` (type: `string`):

Only tweets in this language (ISO 639-1 code).

## `onlyVerifiedUsers` (type: `boolean`):

Only tweets from verified accounts.

## `onlyTwitterBlue` (type: `boolean`):

Only tweets from X Premium subscribers.

## `onlyImage` (type: `boolean`):

Only tweets that contain images.

## `onlyVideo` (type: `boolean`):

Only tweets that contain video.

## `onlyQuote` (type: `boolean`):

Only tweets that quote another tweet.

## `author` (type: `string`):

Only tweets posted by this handle.

## `inReplyTo` (type: `string`):

Only replies to this handle.

## `mentioning` (type: `string`):

Only tweets that mention this handle.

## `geotaggedNear` (type: `string`):

Only tweets geotagged near this place.

## `withinRadius` (type: `string`):

Radius around the place above, e.g. 15km.

## `geocode` (type: `string`):

latitude,longitude,radius — e.g. 37.78,-122.41,1km.

## `placeObjectId` (type: `string`):

Only tweets tagged with this X place ID.

## `minimumRetweets` (type: `integer`):

Only tweets with at least this many reposts.

## `minimumFavorites` (type: `integer`):

Only tweets with at least this many likes.

## `minimumReplies` (type: `integer`):

Only tweets with at least this many replies.

## `start` (type: `string`):

Only tweets posted on or after this date.

## `end` (type: `string`):

Only tweets posted before this date.

## `includeSearchTerms` (type: `boolean`):

Adds a searchTerm field with the term, URL or handle that found the tweet.

## `customMapFunction` (type: `string`):

A JavaScript function applied to every tweet before it is saved: (tweet) => ({ ...tweet }). For reshaping only — never for filtering.

## Actor input object example

```json
{
  "startUrls": [
    "https://twitter.com/apify",
    "https://twitter.com/search?q=apify%20&src=typed_query",
    "https://twitter.com/i/lists/78783491",
    "https://twitter.com/elonmusk/with_replies"
  ],
  "searchTerms": [
    "web scraping",
    "scraping from:apify"
  ],
  "twitterHandles": [
    "elonmusk",
    "taylorswift13"
  ],
  "maxItems": 1000,
  "sort": "Latest",
  "tweetLanguage": "en",
  "customMapFunction": "(object) => { return {...object} }"
}
```

# Actor output Schema

## `tweets` (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 = {
    "startUrls": [
        "https://twitter.com/apify",
        "https://twitter.com/search?q=apify%20&src=typed_query",
        "https://twitter.com/i/lists/78783491",
        "https://twitter.com/elonmusk/with_replies"
    ],
    "searchTerms": [
        "web scraping",
        "scraping from:apify"
    ],
    "twitterHandles": [
        "elonmusk",
        "taylorswift13"
    ],
    "maxItems": 1000,
    "sort": "Latest",
    "tweetLanguage": "en",
    "customMapFunction": (object) => { return {...object} }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tweetpipe/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 = {
    "startUrls": [
        "https://twitter.com/apify",
        "https://twitter.com/search?q=apify%20&src=typed_query",
        "https://twitter.com/i/lists/78783491",
        "https://twitter.com/elonmusk/with_replies",
    ],
    "searchTerms": [
        "web scraping",
        "scraping from:apify",
    ],
    "twitterHandles": [
        "elonmusk",
        "taylorswift13",
    ],
    "maxItems": 1000,
    "sort": "Latest",
    "tweetLanguage": "en",
    "customMapFunction": "(object) => { return {...object} }",
}

# Run the Actor and wait for it to finish
run = client.actor("tweetpipe/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 '{
  "startUrls": [
    "https://twitter.com/apify",
    "https://twitter.com/search?q=apify%20&src=typed_query",
    "https://twitter.com/i/lists/78783491",
    "https://twitter.com/elonmusk/with_replies"
  ],
  "searchTerms": [
    "web scraping",
    "scraping from:apify"
  ],
  "twitterHandles": [
    "elonmusk",
    "taylorswift13"
  ],
  "maxItems": 1000,
  "sort": "Latest",
  "tweetLanguage": "en",
  "customMapFunction": "(object) => { return {...object} }"
}' |
apify call tweetpipe/tweet-scraper --silent --output-dataset

```

## MCP server setup

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