# X (Twitter) Tweet Scraper API – Likes, Replies, Media, No Login (`k-data-lab/x-tweet-scraper`) Actor

Get X (Twitter) tweet data and MP4 video download links from tweet URLs or IDs, no login or cookies: text, likes, replies, author, photos, every video quality, quoted tweet, threads, polls, Community Notes. $0.09 per 1,000 tweets, 500 free a month.

- **URL**: https://apify.com/k-data-lab/x-tweet-scraper.md
- **Developed by:** [K-Data Lab](https://apify.com/k-data-lab) (community)
- **Categories:** Social media, Automation, Videos
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.07 / 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.
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

## X Tweet Scraper & Twitter Video Downloader API: Likes, Replies, MP4 Links, No Login

**Paste tweet links or IDs and get one clean row per tweet: text, likes, replies, author, photos, direct MP4 video download links in every quality, the quoted tweet, the tweet it replies to, link cards, polls and Community Notes.** No X account, no cookies, no API key, no browser.

**$0.09 per 1,000 tweets on the Bronze plan, and your first 500 tweets every month are free.** Deleted, private and unsupported links are never charged. Each run has a $0.005 start fee, so put many links in one run. The prefilled run finishes in about 3 seconds.

**Built for tweets you already know about.** Typical uses: tracking likes and replies on campaign or influencer posts, checking a list of links from a spreadsheet, **getting MP4 download links for X videos in bulk** (tick *Only tweets with a video* and pay only for tweets that have one), archiving tweets with their media, or enriching tweet IDs from a research dataset. It does **not** search X and does not read profile timelines (X shows those only to logged-in users). See [what it doesn't do](#-what-it-doesnt-do).

Real rows from the prefilled run on 8 November 2026 (Korea time):

| Tweet | Author | Likes | Replies | Media | Extra |
|---|---|---:|---:|---|---|
| [just setting up my twttr](https://x.com/jack/status/20) | @jack | 324,984 | 19,253 | none | affiliation: Square |
| [A ‘hello world’ milestone for Project Suncatcher 🚀…](https://x.com/sundarpichai/status/2116214866444943853) | @sundarpichai | 26,666 | 1,483 | 1 video, 1920×1080 MP4 link | affiliation: Google |
| [A mobile comparison test…](https://x.com/discord/status/2118755849367896539) | @discord | 12,893 | 367 | none | quotes another tweet (with its retweet count) |
| [A new era is coming…](https://x.com/Microsoft/status/1791613922727911762) | @Microsoft | 4,727 | 323 | 1 photo | verified business |

#### 🚀 Pick your starting point

| You want | Paste this input |
|---|---|
| Likes and replies for a list of tweets | `{ "tweets": ["https://x.com/jack/status/20", "https://x.com/Microsoft/status/1791613922727911762"] }` |
| MP4 download links for X / Twitter videos | `{ "tweets": ["https://x.com/sundarpichai/status/2116214866444943853"], "videoOnly": true }` |
| Bare IDs from a dataset | `{ "tweets": ["20", "1791613922727911762"] }` |
| A reply plus the conversation above it | `{ "tweets": ["https://x.com/MarathonFusion/status/2113001085912895846"], "threadDepth": 5 }` |
| A daily engagement snapshot | the same list on an Apify **Schedule**; each row has `scrapedAt` |
| Only tweets that still exist | `{ "tweets": [...], "skipMissing": true }` |

Links from x.com, twitter.com, mobile.twitter.com, fxtwitter, vxtwitter and `x.com/i/web/status/…` all work, with or without `?s=20` tracking bits. Duplicate links are read once.

#### 📦 What you get per tweet

| Field | Example | Notes |
|---|---|---|
| `url`, `id` | `https://x.com/jack/status/20` | |
| `text` | `just setting up my twttr` | t.co links expanded to the real URL |
| `isTextTruncated` | `false` | `true` for long posts over 280 characters, see FAQ |
| `createdAt`, `language` | `2006-03-21T20:50:14.000Z`, `en` | UTC |
| `likeCount`, `replyCount` | `324984`, `19253` | live numbers at `scrapedAt` |
| `author` | `{ name, handle, id, isBlueVerified, verifiedType, affiliation, avatarUrl, profileUrl }` | affiliation is the badge under the name (e.g. "Google") |
| `videoUrl` | `https://video.twimg.com/…/1920x1080/….mp4` | direct MP4 link of the first video or GIF, best quality |
| `media[]` | `{ type, imageUrl, width, height, altText, durationMs, videoUrl, videoVariants, hlsUrl }` | `videoVariants` lists every MP4 quality (`url`, `bitrate`, `width`, `height`), best first |
| `quotedTweet` | `{ id, url, text, authorHandle, likeCount, replyCount, retweetCount, … }` | includes the quoted tweet's **retweet count** |
| `replyTo` | same shape as `quotedTweet` | the tweet it answers, with its retweet count |
| `hashtags`, `cashtags`, `mentions`, `links` | `["AI"]`, `["TSLA"]` | |
| `card` | `{ type, url, title, description, domain, imageUrl, poll }` | link previews; polls include each option's votes |
| `communityNote` | `{ title, text, url, noteId }` | the reader context shown under the tweet |
| `article` | `{ title, previewText }` | X Articles |
| `isEdited`, `editedVersionIds`, `possiblySensitive`, `replyRestriction`, `place` | | |
| `status`, `message` | `OK` | see below |

A row for a video tweet (shortened):

```json
{
  "status": "OK",
  "url": "https://x.com/sundarpichai/status/2116214866444943853",
  "text": "A ‘hello world’ milestone for Project Suncatcher 🚀\n\nAfter launching our prototype satellite a few weeks ago, …",
  "createdAt": "2026-10-30T17:05:16.000Z",
  "likeCount": 26666,
  "replyCount": 1483,
  "author": { "name": "Sundar Pichai", "handle": "sundarpichai", "isBlueVerified": true, "affiliation": "Google" },
  "media": [{
    "type": "video", "width": 1920, "height": 1080, "durationMs": 16021,
    "videoUrl": "https://video.twimg.com/amplify_video/2116214727835828224/vid/avc1/1920x1080/pEIO6vAh51GKep_W.mp4",
    "imageUrl": "https://pbs.twimg.com/amplify_video_thumb/2116214727835828224/img/b4pQhbjRd5EDKtkl.jpg",
    "videoVariants": [
      { "url": "https://video.twimg.com/amplify_video/2116214727835828224/vid/avc1/1920x1080/pEIO6vAh51GKep_W.mp4", "bitrate": 10368000, "width": 1920, "height": 1080 },
      { "url": "https://video.twimg.com/amplify_video/2116214727835828224/vid/avc1/1280x720/zG1J8hKWLBVeO2Wl.mp4", "bitrate": 2176000, "width": 1280, "height": 720 },
      { "url": "https://video.twimg.com/amplify_video/2116214727835828224/vid/avc1/640x360/U9KH9sdF6YE6rJsG.mp4", "bitrate": 832000, "width": 640, "height": 360 },
      { "url": "https://video.twimg.com/amplify_video/2116214727835828224/vid/avc1/480x270/e8jmsZmdNof2yy8U.mp4", "bitrate": 256000, "width": 480, "height": 270 }
    ]
  }],
  "videoCount": 1,
  "videoUrl": "https://video.twimg.com/amplify_video/2116214727835828224/vid/avc1/1920x1080/pEIO6vAh51GKep_W.mp4",
  "quotedTweet": null,
  "scrapedAt": "2026-11-07T18:23:07Z"
}
```

**Every link gets an answer.** A link that has no data still gets a short, uncharged row, so a monitor can tell what disappeared:

| `status` | Meaning | Charged |
|---|---|---|
| `OK` | tweet data | yes |
| `NOT_FOUND` | deleted, never existed, or from a protected account | no |
| `UNAVAILABLE` | X shows a notice instead, e.g. "This Post is from a suspended account"; the notice is in `message` | no |
| `DUPLICATE` | a retweet ID that resolves to a tweet already in the dataset | no |
| `NO_VIDEO` | no video or GIF in this tweet, while *Only tweets with a video* is on | no |
| `PROFILE_NOT_SUPPORTED`, `SEARCH_NOT_SUPPORTED`, `NOT_A_TWEET_LINK` | not a tweet link | no |
| `NO_ANSWER` | X didn't answer after several tries (0 in over 4,000 lookups in our tests) | no |

#### 💰 Pricing

| | Free plan | Bronze | Silver | Gold+ |
|---|---:|---:|---:|---:|
| Tweet | $0.10 / 1,000 | **$0.09 / 1,000** | $0.08 / 1,000 | $0.07 / 1,000 |
| Run start | $0.005 | $0.005 | $0.005 | $0.005 |

- **500 tweets free every month** per Apify account, counted across all your runs.
- Thread rows (`threadDepth`) are normal tweet rows. The first parent inside `replyTo` is free.
- Set **Maximum cost per run** and the run stops cleanly at that amount. 10,000 tweets cost about $0.90 on Bronze.

How it compares, from each actor's public Store page on 8 November 2026:

| | This actor | apidojo/tweet-scraper | apidojo/twitter-scraper-lite | kaitoeasyapi tweet scraper | xquik/x-tweet-scraper |
|---|---|---|---|---|---|
| Price per 1,000 tweets (Bronze) | **$0.09** | $0.40 | $0.40–2.00 by batch size, + $0.05 per tweet URL query | $0.22 | $0.15 |
| Free tweets every month | **500** | none | none | none | none |
| Look up tweets by link or ID | yes | yes | yes | yes | yes |
| Keyword search, profiles, lists | **no** | yes | yes | yes | yes |
| Retweet, quote, view, bookmark counts of the tweet itself | **no** (retweets only for quoted / replied-to tweets) | yes | yes | yes | yes |

For **video links only**, the Twitter video downloaders on the Store charged, on the same date: igview-owner/twitter-x-video-downloader $5.00 per 1,000 results, epctex/twitter-video-downloader $0.40 per 1,000 seconds of 720p video (it also stores the files). This actor returns the MP4 links (not the files) at $0.09 per 1,000 tweets, and with *Only tweets with a video* on, tweets without a video are free.

If you need search or full timelines, use one of the others. If you need fast, cheap numbers and media for tweets you already have, this one costs less and needs nothing from you.

#### ❓ FAQ

**Where does the data come from?** From X's public tweet-embed data: the same JSON that loads when a news site or blog shows an embedded tweet to a visitor who isn't logged in. We don't use accounts, cookies, a browser or signed requests, and we read nothing a logged-out visitor can't see. This is an unofficial tool, not affiliated with X Corp.

**Why are long posts cut off?** X's embed data carries the first ~280 characters of a long post (X Premium "show more" posts), so `isTextTruncated` is `true` for those rows and the text ends where X cuts it. In our tests about a third of recent tweets from tech and news accounts were long posts.

**Why no retweet or view counts?** X doesn't put them in the embed data for the tweet itself. It does include retweets for the quoted tweet and the replied-to tweet, so those are in `quotedTweet.retweetCount` and `replyTo.retweetCount`.

**Can it search X or read a profile's latest tweets?** No. X shows search, hashtags, lists and profile timelines only to logged-in users, and we don't log in. Profile and search links come back as an uncharged row that explains this.

**How fast is it?** About 2,000 tweets in 16 seconds in our tests, with no proxy needed. Old tweets (2020 and earlier) answer more slowly than recent ones.

**Are the numbers live?** Yes. Each run reads them fresh, so scheduling the same list daily gives you an engagement history (use `scrapedAt` as the time).

**Private accounts?** Tweets from protected accounts are not public, so they come back as `NOT_FOUND`.

**Does it download the video file?** It gives you the direct MP4 link on X's video server (`video.twimg.com`), in every quality X offers. Open it in a browser or fetch it with any HTTP client to save the file. Files are not copied into Apify storage, which keeps it cheap. Only download videos you have the right to use.

**Can I use it from code, n8n, Make or Zapier?** Yes. Use the Apify API (`run-sync-get-dataset-items`) with `{ "tweets": [...] }`; see the next section for AI agents.

#### 🤖 Use it from AI agents (MCP)

Add `https://mcp.apify.com?tools=actors,k-data-lab/x-tweet-scraper` to Claude, ChatGPT, Cursor or any MCP client (sign in with Apify), and the agent gets this actor as a named tool. Prompts that work:

- "Get the likes and replies for these 20 tweet links."
- "Give me the MP4 download link for this X video: https://x.com/…/status/…"
- "Which of these tweets were deleted?" (look for `status` other than `OK`)

Agent input is one array, `tweets`, of links or IDs. Optional: `videoOnly` (true = only tweets with a video), `threadDepth` (0–25), `skipMissing`. The output is one JSON row per tweet with the fields above. A 10-tweet call costs under $0.01, and the first 500 tweets each month are free.

#### 🙅 What it doesn't do

- No keyword search, hashtag pages, lists, profile timelines, followers or likes lists (all logged-in only on X).
- No retweet, quote, bookmark or view counts for the tweet itself.
- Video files are not stored, only their MP4 links.
- Long posts are truncated to the part X's embed shows (`isTextTruncated: true`).
- No replies *below* a tweet. `threadDepth` walks *up* a conversation, to the tweets a reply answers.

#### 🧰 More from K-Data Lab

**Social and apps**

- [TikTok Scraper API](https://apify.com/k-data-lab/tiktok-scraper): video stats, transcripts and exact follower counts, no login
- [YouTube Scraper API](https://apify.com/k-data-lab/youtube-scraper): video stats, channels and search, no login
- [Telegram Scraper API](https://apify.com/k-data-lab/telegram-channel-scraper): channels and keyword search, no login
- [Google Play Scraper API](https://apify.com/k-data-lab/google-play-scraper): app details and reviews, any country
- [Google Maps Scraper](https://apify.com/k-data-lab/google-maps-scraper): places, ratings and contact details
- [Google Ads Transparency & Ad Library Scraper](https://apify.com/k-data-lab/google-ad-library-scraper): every Google ad a competitor runs

**Amazon**

- [Amazon Seller Central Review Scraper](https://apify.com/k-data-lab/amazon-seller-central-review-scraper): brand reviews and monitoring
- [Amazon ASIN Rating & Review Count Lookup](https://apify.com/k-data-lab/amazon-asin-rating-scraper): ratings, review counts and BSR, no login

**Travel**

- [Agoda Scraper API](https://apify.com/k-data-lab/agoda-scraper): hotel prices, rooms and reviews
- [Airline Award Seat Scraper](https://apify.com/k-data-lab/airline-award-seat-scraper): live miles, taxes and seats left
- [Uber Eats & Deliveroo Scraper](https://apify.com/k-data-lab/uber-eats-deliveroo-scraper): restaurants and menus

**Korean data**

- [Korean Music Chart API](https://apify.com/k-data-lab/korean-music-chart-scraper): Melon, Genie, Bugs, FLO and VIBE in one chart
- Korea apartment prices: [KB Land](https://apify.com/k-data-lab/kbland-scraper), [R114](https://apify.com/k-data-lab/r114-scraper)

#### 💬 Feedback

Missing a field, or found a tweet that doesn't come through? Open an issue on the **Issues** tab. We answer the same day.

Tags: twitter scraper, x scraper, tweet scraper, x.com scraper, twitter api alternative, tweet likes, tweet engagement tracker, tweet by id, tweet url scraper, twitter video downloader, x video downloader, tweet video mp4 link, twitter video download api, community notes, twitter no login

# Changelog

This Actor's version history is a separate document: https://apify.com/k-data-lab/x-tweet-scraper/changelog.md

# Actor input Schema

## `tweets` (type: `array`):

Tweet (post) links like https://x.com/NASA/status/1234567890123456789, twitter.com, mobile.twitter.com, fxtwitter/vxtwitter links, or bare numeric IDs. One per line, up to 20,000 per run. Video tweets return direct MP4 links. Profile, search and hashtag links are not supported (X shows those only to logged-in users) and come back as an uncharged row with an explanation.

## `videoOnly` (type: `boolean`):

Tick this to get MP4 video links only: tweets with a video or GIF are saved (each with videoUrl, the best-quality MP4, and every other quality in media\[].videoVariants); tweets without one get a short uncharged NO_VIDEO row (or none, with "Leave out deleted / unavailable tweets"). Off = every tweet is saved.

## `threadDepth` (type: `integer`):

For replies: walk up the conversation and save each tweet it answers, up to this many levels (0 = off). Each extra tweet is a normal charged row with foundVia = thread and threadOf = the tweet you asked for. The first parent is always included for free inside replyTo.

## `skipMissing` (type: `boolean`):

By default a deleted, private or unsupported link still gets a short uncharged row with status and message, so monitors can see what disappeared. Tick this to leave those rows out.

## Actor input object example

```json
{
  "tweets": [
    "https://x.com/jack/status/20",
    "https://x.com/sundarpichai/status/2116214866444943853",
    "https://x.com/discord/status/2118755849367896539",
    "https://x.com/Microsoft/status/1791613922727911762"
  ],
  "videoOnly": false,
  "threadDepth": 0,
  "skipMissing": false
}
```

# Actor output Schema

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

No description

## `videos` (type: `string`):

No description

## `all` (type: `string`):

No description

## `summary` (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 = {
    "tweets": [
        "https://x.com/jack/status/20",
        "https://x.com/sundarpichai/status/2116214866444943853",
        "https://x.com/discord/status/2118755849367896539",
        "https://x.com/Microsoft/status/1791613922727911762"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("k-data-lab/x-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 = { "tweets": [
        "https://x.com/jack/status/20",
        "https://x.com/sundarpichai/status/2116214866444943853",
        "https://x.com/discord/status/2118755849367896539",
        "https://x.com/Microsoft/status/1791613922727911762",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("k-data-lab/x-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 '{
  "tweets": [
    "https://x.com/jack/status/20",
    "https://x.com/sundarpichai/status/2116214866444943853",
    "https://x.com/discord/status/2118755849367896539",
    "https://x.com/Microsoft/status/1791613922727911762"
  ]
}' |
apify call k-data-lab/x-tweet-scraper --silent --output-dataset

```

## MCP server setup

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