# X (Twitter) Scraper - Tweets, Search & Profiles | No Login (`clover_folktale/twitter-scraper`) Actor

Scrape X (Twitter) tweets by keyword, from any profile, or by tweet link. Strict date window, direct MP4 video links, retweet, quote and reply flags, views, likes and author data. No login, cookies or API keys. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/clover_folktale/twitter-scraper.md
- **Developed by:** [Silkline](https://apify.com/clover_folktale) (community)
- **Categories:** Social media, Lead generation
- **Features:** Limited permissions
- **Stats:** 4 total users, 2 monthly users, 94.7% 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/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

**You put in:** `{"mode": "search", "searchTerms": ["bitcoin"], "sort": "Latest", "maxResults": 10}`

**You get back:** one record per tweet with 49 fields. Three records from a real run on 2026-11-03, some of the fields:

| `text` | `viewCount` | `likeCount` | `retweetCount` | `createdAt` |
|---|---|---|---|---|
| “Bitcoin is a scam” So what is thi… | 119307 | 2515 | 431 | 2026-11-01T20:36:41Z |
| Bitcoin is at the SAME price as in… | 39469 | 177 | 11 | 2026-11-01T13:29:19Z |
| This girl bought 23,000 Bitcoin in… | 149255 | 656 | 62 | 2026-10-31T17:01:59Z |

**You pay:** 1,000 tweets cost about $0.25 on the Bronze plan. Free Apify accounts get 2 trial runs of up to 10 results each, nothing charged.

X (Twitter) Scraper is an X API alternative that collects public tweets as clean, flat JSON. Search tweets by keyword, read the latest tweets of any profile, or fetch single tweets by link or ID. You get text, dates, views, likes, retweets, replies, quotes, bookmarks, hashtags, mentions, media and author data, with direct MP4 links for videos and GIFs. It is made for brand and market monitoring, social listening, research, and AI and data teams. No X account, API keys, proxies or cookies are needed.

### What is X (Twitter)?

X, formerly Twitter, is a public social network where people post short messages called tweets (or posts). Tweets can carry pictures, videos and links, and they can be replies, retweets or quotes of other tweets. Because most of it is public and time-stamped, X is a leading place to follow news, public opinion and brand mentions.

### What data can you get?

The Actor has three modes.

| Mode | Give it | You get |
|---|---|---|
| `search` | keywords or X search queries (optional: Latest or Top, date window) | tweets matching each keyword, 20 per page, as many pages as `maxResults` needs |
| `userTweets` | handles (`@name`, `name`) or profile links | each profile's tweets from newest to oldest, including its retweets and replies |
| `tweets` | tweet links or IDs | one record per tweet |

All modes share `maxResults` (default 50, up to 10,000 per run, counted across all inputs), an optional date window (`startDate`, `endDate`, as YYYY-MM-DD in UTC) and the optional tweet filters described under Input.

#### Tweet fields

| Field | Meaning |
|---|---|
| `tweetId`, `url`, `text`, `lang`, `createdAt` | the tweet, its link, text, language and post time (ISO 8601 UTC) |
| `viewCount`, `likeCount`, `retweetCount`, `replyCount`, `quoteCount`, `bookmarkCount` | counters at the time of the run |
| `conversationId` | ID of the first tweet of the conversation |
| `isRetweet` | the tweet is a plain repost of someone else's tweet; `retweetedTweetId`, `retweetedAuthorHandle` and `retweetedText` describe the original |
| `isQuote` | the tweet quotes another tweet; `quotedTweetId`, `quotedAuthorHandle` and `quotedText` describe it. Empty (null) in `search` mode, because search results carry no quote data |
| `isReply` | the tweet is a reply to another tweet, including a reply to your own tweet in a thread; `inReplyToTweetId` names it when the data does |
| `sensitive`, `source` | X's sensitive-content mark and the posting app, when X gives them |
| `hashtags`, `mentions`, `urls` | hashtags (without #), mentioned handles (without @) and full link addresses |
| `mediaType` | `photo`, `video`, `gif`, `mixed` or empty |
| `imageUrls`, `videoUrl`, `mediaUrls` | picture links; the direct MP4 of a video or GIF (highest bitrate); every downloadable media link |
| `videoThumbnailUrl`, `videoDurationMs` | preview picture and length of the video |
| `authorHandle`, `authorName`, `authorId`, `authorFollowers`, `authorVerified`, `authorAvatarUrl` | the author's public profile data |
| `authorBio`, `authorLocation`, `authorUrl`, `authorCoverUrl` | the author's bio, location, website link and banner picture |
| `authorFollowing`, `authorLikeCount`, `authorCreatedAt`, `authorVerifiedType` | how many accounts the author follows, how many tweets the author liked, when the account was created (ISO 8601 UTC) and the kind of verification (for example `Business`) |

Author fields are empty (null) when X does not give them; nothing is guessed.
| `searchTerm` / `sourceHandle` | which keyword (`search`) or profile (`userTweets`) produced the tweet |

### How to use X (Twitter) Scraper

1. Open the Actor in the Apify Console.
2. Choose a **Mode** and fill in its list: search terms, profiles, or tweet links.
3. Optionally set **From date** and **Until date**, the tweet filters, and **Max results** to cap how many tweets (and how much money) the run can use.
4. Click **Start** and wait for the run to finish.
5. Open the dataset and export it as JSON, CSV, Excel or another format, or read it through the API.

An empty input `{}` also works: it searches X for "bitcoin".

### Input

```json
{
  "mode": "search",
  "searchTerms": ["bitcoin", "from:nasa moon"],
  "sort": "Latest",
  "startDate": "2026-10-30",
  "endDate": "2026-11-02",
  "minLikes": 100,
  "media": "images",
  "language": "en",
  "excludeReplies": true,
  "maxResults": 500
}
```

- `searchTerms` are passed to X search as typed, so X search operators such as `"exact phrase"`, `#hashtag` or `from:name` can be used.
- Tweet filters, all optional: `minLikes`, `minReplies`, `minRetweets` (whole numbers), `media` (`any`, `images`, `videos` or `media` for either), `onlyVerified` (true/false), `language` (a code such as `en` or `zh`), `excludeReplies` and `excludeRetweets` (true/false). A tweet that does not pass is neither delivered nor charged, and the status message counts it.
- `handles` (for `userTweets`) accept `@name`, `name`, `https://x.com/name` and `https://twitter.com/name`.
- `tweetUrls` (for `tweets`) accept `https://x.com/name/status/123`, twitter.com links and bare IDs.

### Output example

```json
{
  "type": "tweet",
  "tweetId": "2116715279053127861",
  "url": "https://x.com/1096361BTC/status/2116715279053127861",
  "text": "18 years ago, Satoshi Nakamoto published a 9-page paper. ...",
  "lang": "en",
  "createdAt": "2026-11-01T02:13:43Z",
  "viewCount": 68427,
  "likeCount": 6159,
  "retweetCount": 2250,
  "replyCount": 1206,
  "quoteCount": 61,
  "bookmarkCount": 14,
  "conversationId": "2116715279053127861",
  "isRetweet": false,
  "isQuote": null,
  "isReply": false,
  "hashtags": [],
  "mentions": [],
  "urls": [],
  "mediaType": "video",
  "imageUrls": [],
  "videoUrl": "https://video.twimg.com/amplify_video/2116714617254920192/vid/avc1/1920x1080/MYaxIpal4Pb3ri7m.mp4?tag=29",
  "mediaUrls": ["https://video.twimg.com/amplify_video/2116714617254920192/vid/avc1/1920x1080/MYaxIpal4Pb3ri7m.mp4?tag=29"],
  "authorHandle": "1096361BTC",
  "authorName": "MemeBitcoin",
  "authorId": "1984251466136301568",
  "authorFollowers": 65026,
  "authorVerified": true,
  "authorBio": null,
  "authorLocation": "Internet",
  "authorFollowing": null,
  "authorLikeCount": 1177,
  "authorCreatedAt": "2025-10-31T13:29:57Z",
  "authorVerifiedType": null,
  "authorCoverUrl": null,
  "authorUrl": null,
  "searchTerm": "bitcoin"
}
```

The example is shortened (`text` cut, some empty fields left out).

### How much does it cost?

The Actor uses pay-per-event pricing. The result price falls with your Apify plan:

| Event | Bronze | Silver | Gold and above |
|---|---|---|---|
| Run start | $0.00005 | $0.00005 | $0.00005 |
| Result (per tweet from `search` or `userTweets`) | $0.00025 | $0.000226 | $0.000188 |
| Detail (per tweet looked up by URL or ID in `tweets`) | $0.0025 | $0.00226 | $0.00204 |

That is $0.25, $0.23 and $0.19 per 1,000 tweets from searches and timelines. Looking tweets up one by one costs more because each one is a separate request. Examples at the Bronze price:

- 100 tweets: $0.00005 + 100 × $0.00025 = **$0.02505**
- 1,000 tweets: $0.00005 + 1,000 × $0.00025 = **$0.25005**
- 10,000 tweets: $0.00005 + 10,000 × $0.00025 = **$2.50005**
- 50 tweets by URL (`tweets` mode): $0.00005 + 50 × $0.0025 = **$0.12505**

You are charged only for tweets delivered to your dataset. Tweets outside your date window, duplicates and searches or profiles that return nothing are not charged as results. The run-start fee is charged once per run, when the first request succeeds. The run stops by itself if your spending limit is reached.

On the free Apify plan you get 2 free trial runs of this Actor with your own input, up to 10 results each, and nothing is charged; after that, runs return a stored sample dataset (a real result of the prefilled input). Use any paid Apify plan for full runs.

### Use cases

- **Brand and product monitoring**: search your brand name every day with `sort` set to `Latest` and a date window for yesterday.
- **Social listening and research**: collect tweets on a topic for a fixed period, with views, likes and replies to rank them.
- **Account tracking**: read what a competitor, journalist or public figure posts with `userTweets`.
- **Media collection**: get direct MP4 links of videos and GIFs in `videoUrl` and all picture links in `imageUrls`.
- **AI and data projects**: flat JSON with clean metadata for sentiment analysis, trend models and search indexes.

### Why use this X (Twitter) scraper

- **The date window is enforced.** Tweets outside `startDate` and `endDate` are checked on every record: they are neither delivered nor charged, and the status message says how many were skipped.
- **It pages until you have enough.** Pages are read until `maxResults` or the end of the results. For Latest search and profiles, paging stops once the tweets are older than `startDate`.
- **It tells you why it stopped.** The final status message gives, per keyword or profile, how many pages were read and why it stopped: no more results, date window passed, or `maxResults` reached.
- **Empty is clear and free.** A search or profile that returns nothing is named in the status message, and no result fee is charged.
- **Videos you can download.** Video and GIF tweets carry `videoUrl`, a direct MP4 link of the highest bitrate, and `mediaUrls` with all media links.
- **Retweet, quote and reply flags**: `isRetweet`, `isQuote` and `isReply`, with the original tweet's text for retweets and quotes.
- **No duplicates.** Each tweet is delivered once per run, even if several keywords find it.
- **Try before paying.** On a free Apify plan you get 2 free trial runs with your own input, up to 10 results each, nothing charged.

### Integrations and API

If you are looking for an X (Twitter) API alternative, you can use this Actor like one. It is not an official X API and is not affiliated with X Corp. You can start runs through the Apify API, schedule them in the Apify Console (for example a daily brand search), and connect the results to webhooks and the integrations available on the Apify platform.

Python example with `apify-client`:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("clover_folktale/twitter-scraper").call(run_input={
    "mode": "search",
    "searchTerms": ["bitcoin"],
    "sort": "Latest",
    "startDate": "2026-11-01",
    "maxResults": 200,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["createdAt"], item["authorHandle"], item["text"])
```

#### Use it from AI agents (MCP, n8n, Make)

This Actor works as a tool for AI agents through the [Apify MCP server](https://docs.apify.com/mcp). Add it to Claude, Cursor or any MCP client with `https://mcp.apify.com?tools=clover_folktale/twitter-scraper`, and the agent can search X and read the results itself. It also has ready-made integrations for n8n, Make and Zapier on the Apify platform.

### Tips and limits

- **Page size.** Each request returns about 20 tweets. Large runs make many requests; expect a few seconds per page.
- **Several inputs.** Keywords, profiles or tweets in one list are read at the same time; `maxResults` counts across all of them.
- **Date window.** Dates are UTC; `endDate` includes the whole day. In `search`, the window is also added to the query as `since:` and `until:` so fewer pages are read, unless your keyword already has its own `since:`/`until:`, an `OR` or brackets. Either way every tweet is checked again. `userTweets` reads a profile from newest to oldest, so a window far in the past reads the newer pages first (not charged) before it reaches the window.
- **Filters.** In `search`, X applies `minLikes` (`min_faves:`), `minReplies` (`min_replies:`), `minRetweets` (`min_retweets:`), `media` (`filter:images`, `filter:native_video`, `filter:media`), `onlyVerified` (`filter:blue_verified`), `language` (`lang:`), `excludeReplies` (`-filter:replies`) and `excludeRetweets` (`-filter:nativeretweets`) itself, like the date window: they are added to the query unless your keyword has an `OR` or brackets. Whatever X does, the Actor re-checks every tweet against each filter you set, in all three modes (`userTweets` and `tweets` have no X-side filtering, only this check). A tweet with a value the data does not carry cannot pass that filter. Tweets that fail are not delivered and not charged. With strict filters a run reads more pages than it delivers.
- **Latest and Top.** Latest is not strictly ordered by time inside a page; paging stops only when a whole page is older than `startDate`. Top is ranked by relevance and is read to the end of its results.
- **Retweets.** In `userTweets`, a retweet is a record with `isRetweet` true; its `text` is X's shortened "RT @name: ..." form and the full original is in `retweetedText`. Counters belong to the retweet record.
- **Ads.** There is no `isAd` field: the data does not say whether a tweet is an ad, so the Actor does not guess.
- **Quotes in search.** Search results carry no quote data, so `isQuote` is empty there; use `userTweets` or `tweets` for quote information.
- **Pinned tweets** are not added to a profile's list; they appear in it only when they are in the timeline.
- **Avatar.** `authorAvatarUrl` is the small version X lists.
- **Unreadable entries.** If one entry of an ID or link list cannot be read (a typo, a stray cell, a link to the wrong kind of page), it is skipped and named in the log, and the status message says how many were skipped; the other entries still run and nothing is charged for a skipped one. Only a list with no readable entry stops the run with an input error.
- **Free plan.** On the free Apify plan you get 2 free trial runs of this Actor with your own input, up to 10 results each, and nothing is charged; after that, runs return a stored sample dataset (a real result of the prefilled input). Use any paid Apify plan for full runs.

### FAQ

#### Do I need an X account, cookies or API keys?

No. You do not need an X account, API keys, proxies or cookies.

#### Is it legal to scrape X?

The Actor returns only public data, including the public profile data of tweet authors. Private messages, protected accounts and non-public details are never part of the output. You are responsible for how you use the data and for following the laws and platform terms that apply to you.

#### How fresh is the data?

Data is read when the run happens. Counters such as `viewCount` and `likeCount` are the values at that time.

#### How many tweets can I get?

Up to 10,000 per run via `maxResults`. How far back a search or profile goes depends on what X shows for it; the status message tells you why a source ended.

#### Why did my run return fewer tweets than maxResults?

The keyword or profile has no more results, the date window was passed, or tweets were outside the window. The status message of the run lists pages read and the reason per input.

#### What happens with a wrong handle or deleted tweet?

It is skipped and named in the status message, and no result fee is charged for it. The $0.00005 run-start fee may still apply.

#### What permissions does the Actor need?

It runs with Apify's limited permissions and only writes to its own run storage (the dataset and key-value store of the run). It does not read or change anything else in your account.

#### A field or mode is missing. What can I do?

Open an issue from the Actor page and it will be looked at.

### Support

Found a bug, a missing field or a mode you need? Open an issue on the **Issues** tab. We reply within 24 hours, and a mode that stops working is fixed within 24 hours. What changed and when is listed on the **Changelog** tab.

### Other tools by Silkline

Every tool below charges per result and needs no login or cookies.

- [TikTok Scraper - Video Search, Hashtags, Profiles & Sounds](https://apify.com/clover_folktale/tiktok-scraper)
- [Reddit Scraper - Posts, Comments, Subreddits & Users](https://apify.com/clover_folktale/reddit-scraper)
- [Threads Scraper (Meta) - Posts, Replies, Profiles & Search](https://apify.com/clover_folktale/threads-scraper)
- [Instagram Scraper - Posts, Reels, Profiles & Followers](https://apify.com/clover_folktale/instagram-scraper)
- [YouTube Shorts Scraper - Search, Channel Shorts & Videos](https://apify.com/clover_folktale/youtube-scraper)

# Changelog

This Actor's version history is a separate document: https://apify.com/clover_folktale/twitter-scraper/changelog.md

# Actor input Schema

## `mode` (type: `string`):

What to scrape: search (tweets matching keywords), userTweets (the latest tweets of profiles) or tweets (single tweets by link or ID).

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

Keywords or X search queries, one per line. The text is passed to X search as typed, so X search operators such as "exact phrase", #hashtag or from:name can be used. Each term is read separately and the results are merged.

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

Latest returns the newest tweets first; Top returns the most relevant ones.

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

X handles (@name or name) or profile links (https://x.com/name or https://twitter.com/name). Each profile returns its tweets from newest to oldest, including retweets and replies the profile shows.

## `tweetUrls` (type: `array`):

Tweet links (https://x.com/name/status/123 or twitter.com) or bare tweet IDs. One tweet per entry.

## `startDate` (type: `string`):

Optional. Only tweets posted on or after this day are returned, as YYYY-MM-DD. Tweets outside the date window are not delivered and not charged.

## `endDate` (type: `string`):

Optional. Only tweets posted on or before this day are returned, as YYYY-MM-DD. Tweets outside the date window are not delivered and not charged.

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

Optional. Only tweets with at least this many likes. In search mode X applies it (min_faves) and the Actor checks every tweet again; in all modes a tweet that does not pass is not delivered and not charged.

## `minReplies` (type: `integer`):

Optional. Only tweets with at least this many replies. In search mode X applies it (min_replies) and the Actor checks every tweet again; in all modes a tweet that does not pass is not delivered and not charged.

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

Optional. Only tweets with at least this many retweets. In search mode X applies it (min_retweets) and the Actor checks every tweet again; in all modes a tweet that does not pass is not delivered and not charged.

## `media` (type: `string`):

Optional. Keep only tweets with pictures, with videos (native video and GIFs), or with either. 'Any tweet' applies no media filter. Tweets that do not match are not delivered and not charged.

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

Optional. Keep only tweets from verified accounts (blue check). Tweets from other accounts are not delivered and not charged.

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

Optional. Keep only tweets X detects in this language, as a code such as en, zh, ja or es. Tweets in other languages are not delivered and not charged.

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

Optional. Leave out tweets that are replies to other tweets. They are not delivered and not charged.

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

Optional. Leave out plain reposts of other people's tweets. They are not delivered and not charged.

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

Maximum number of tweets to return in total across all inputs of the run. You are charged per tweet returned.

## Actor input object example

```json
{
  "mode": "search",
  "searchTerms": [
    "bitcoin"
  ],
  "sort": "Latest",
  "media": "any",
  "onlyVerified": false,
  "excludeReplies": false,
  "excludeRetweets": false,
  "maxResults": 50
}
```

# Actor output Schema

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

All scraped tweets (JSON, CSV, Excel via the dataset API).

# 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 = {
    "searchTerms": [
        "bitcoin"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("clover_folktale/twitter-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 = { "searchTerms": ["bitcoin"] }

# Run the Actor and wait for it to finish
run = client.actor("clover_folktale/twitter-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 '{
  "searchTerms": [
    "bitcoin"
  ]
}' |
apify call clover_folktale/twitter-scraper --silent --output-dataset

```

## MCP server setup

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