# X Twitter Video Downloader (`automation-lab/x-twitter-public-tweet-video-downloader`) Actor

Download authorized public X/Twitter post videos as bounded MP4 files or inspect MP4 variants, author, caption and thumbnail metadata from supplied tweet links.

- **URL**: https://apify.com/automation-lab/x-twitter-public-tweet-video-downloader.md
- **Developed by:** [Automation Lab](https://apify.com/automation-lab) (community)
- **Categories:** Videos, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 item extracteds

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 Twitter Video Downloader

Archive authorized videos from public X/Twitter post links. This x twitter video downloader resolves each supplied post to public MP4 variants, returns the author, caption, thumbnail, dimensions and available duration, and optionally stores the highest-bitrate MP4 in the run's key-value store. It does not search X, access private posts, bypass DRM, or require your X account.

### Who is it for?

Creators can back up their own public clips. Archivists with permission to retain media can process a list of post links into a dataset of provenance and video files. Media teams can first inspect variants without downloading anything, then rerun with downloads enabled for the clips they are authorized to preserve.

### Why use this downloader?

Each record ties a video to its original post and exposes the available MP4 variants, not just an opaque file. A bounded download option prevents a single oversized video from consuming unlimited transfer or storage. A failed or oversized download is explicitly marked `download_failed` while still returning the variant URL when metadata is available. The Actor checks that the returned tweet ID matches the requested post ID; it does not silently substitute another post.

### Get started

1. Paste one or more public `https://x.com/user/status/123...` or `https://twitter.com/user/status/123...` URLs into **Tweet URLs**.
2. Leave **Store MP4 files** enabled to save an MP4, or disable it to inspect metadata only.
3. Set **Maximum video records** and **Maximum file size (MB)** for your budget.
4. Start the Actor. Open its default dataset for metadata and the `fileUrl` link for each stored video.

For a small real public animated-video post, try:

```json
{"startUrls":[{"url":"https://x.com/nenkosyt/status/2030555563021471749"}],"maxItems":1,"maxFileMb":1}
```

### Input fields

| Field | Default | Meaning |
| --- | --- | --- |
| `startUrls` | Required | 1–100 public X/Twitter post URLs, each containing a username and numeric status ID. |
| `maxItems` | 10 | Stop after 1–100 emitted video records across the supplied posts. |
| `download` | `true` | Store the best available MP4 in the run key-value store; `false` returns metadata and direct source URL only. |
| `maxFileMb` | 10 | Per-video transfer/storage cap, 1–25 MB; only used when downloading. |

Duplicate tweet IDs are processed once. Posts are processed in supplied order. Multiple videos in one post may produce multiple records. `maxItems` limits records, not source posts; this Actor has no search, feed discovery or pagination mode.

### Output fields

| Field | Meaning |
| --- | --- |
| `tweetUrl`, `tweetId` | Canonical post link and checked status ID. |
| `author`, `caption` | Public author handle and post text, nullable. |
| `mediaId`, `mediaType` | Media identity and `video` or `gif` classification. |
| `thumbnailUrl`, `durationSeconds`, `width`, `height` | Available public video metadata; missing measurements are null. |
| `variants` | MP4 URLs and optional bitrates, sorted by descending bitrate. |
| `mediaUrl`, `format` | Selected source MP4 link and MIME type. |
| `fileUrl`, `fileBytes` | Run-storage link and downloaded byte count; null unless stored successfully. |
| `status` | `downloaded`, `metadata_only`, or `download_failed`. |

An animated-video example returns the selected `video.twimg.com` MP4, its public thumbnail, and a `downloaded` record with an 84,378-byte stored file when downloading is enabled. The exact media URL and availability may change upstream; use the dataset's live output rather than caching source links indefinitely.

### How much does it cost to download X Twitter post videos?

Pay-per-event pricing has one start event per run and one item event for each emitted video record (including metadata-only and failed-download records). At the current price, the one-time `start` event is **$0.005** and each emitted `item` event costs **$0.004** at BRONZE spend tier (FREE $0.0046, SILVER $0.00312, GOLD/PLATINUM/DIAMOND $0.0024). A BRONZE run returning one, five or ten videos is approximately $0.009, $0.025 or $0.045 in Actor event charges. Tiers reflect qualifying **monthly Apify Store spend**, not the number of videos in this Actor; check the live Apify pricing panel for your applicable tier. Invoicing and any publisher payout are estimates, subject to platform adjustments, refunds, fraud, disputes, taxes, corrections and clawbacks. Video storage and transfer may consume platform resources even when a video exceeds the requested cap late in the stream. Keep inputs and file caps small for initial tests.

### Integrations and repeat workflows

Schedule the Actor with your authorized list of public links for recurring backups. Pass dataset rows to a spreadsheet or data pipeline keyed on `tweetId` plus `mediaId` to avoid duplicating saved media. If your workflow needs to avoid downloading video, set `download: false` and review direct variant URLs before deciding which clips to retain. A scheduled run reprocesses the supplied links; it does **not** find newly published posts or detect changes automatically.

### API: cURL

Replace `APIFY_TOKEN` in your shell and inspect the returned run/dataset IDs:

```bash
curl -X POST 'https://api.apify.com/v2/acts/automation-lab~x-twitter-public-tweet-video-downloader/runs?token='"$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"startUrls":[{"url":"https://x.com/nenkosyt/status/2030555563021471749"}],"maxItems":1,"download":false}'
```

### API: JavaScript

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/x-twitter-public-tweet-video-downloader').call({
  startUrls: [{ url: 'https://x.com/nenkosyt/status/2030555563021471749' }],
  maxItems: 1, download: false,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### API: Python

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/x-twitter-public-tweet-video-downloader').call(run_input={
    'startUrls': [{'url': 'https://x.com/nenkosyt/status/2030555563021471749'}],
    'maxItems': 1, 'download': False,
})
print(client.dataset(run['defaultDatasetId']).list_items().items)
```

### Use with MCP

Connect Claude Code to this Actor's tools:

```bash
claude mcp add --transport http apify \
  'https://mcp.apify.com?tools=automation-lab/x-twitter-public-tweet-video-downloader'
```

For Claude Desktop, Cursor, or VS Code with an HTTP MCP server configuration, add this server entry in the client's MCP settings (the exact enclosing configuration file depends on the client):

```json
{"mcpServers":{"apify":{"url":"https://mcp.apify.com?tools=automation-lab/x-twitter-public-tweet-video-downloader"}}}
```

Example prompts: “Inspect MP4 variants for my authorized public post https://x.com/nenkosyt/status/2030555563021471749 without downloading” and “Archive the MP4 from that post with a 1 MB limit.” Authenticate with Apify as required by your MCP client.

### Legality and responsible use

Only download media you own or are authorized to archive. A public URL does not by itself grant redistribution rights. Respect source terms, copyright, privacy and retention obligations. No private posts, account cookies, login, protected videos, HLS conversion or DRM circumvention are supported. Metadata comes from the independent, unaffiliated FxTwitter public API: the Actor sends each public tweet ID (never account credentials) to `api.fxtwitter.com`, then optionally fetches one file from X's `video.twimg.com` CDN. These providers' availability, field completeness, terms, and handling of request data are outside our control. Direct variant links can expire. This Actor accepts only X/Twitter post URLs and only downloads HTTPS MP4s from `video.twimg.com` without redirects. X and Twitter are used descriptively; this Actor is not affiliated with or endorsed by X, Twitter, or FxTwitter.

### Data handling and retention

The default Apify dataset contains public tweet links, IDs, author handles, captions and video metadata. With `download: true`, the run key-value store also contains each successfully downloaded MP4. Run input and logs may contain tweet IDs; no X credentials are requested or logged. The Actor does not run AI or send inputs to an AI provider, maintain its own external archive, or schedule deletion. Apify retains run inputs, logs, datasets and files according to your account and storage settings; manage and delete them from your Apify account when no longer needed. FxTwitter independently handles the public tweet-ID lookup; we cannot promise its region or retention period. Do not submit links or retain media unless you have permission and an appropriate retention basis.

### Support

Use the Actor's Store issues tab to report an inaccessible public post, a failed download, or a schema mismatch. Include the public tweet URL and run ID only when sharing them is authorized; do not post account secrets or private personal data. A source outage or removed post cannot be repaired by increasing `maxFileMb`.

### Troubleshooting

- **Unsupported post URL:** supply an HTTPS `x.com` or `twitter.com` user/status/ID link, not a search URL, tracking redirect or shortlink.
- **No usable public MP4 variants:** check that the post is anonymously accessible and contains video. Text-only and image-only posts do not produce a video record.
- **`download_failed`:** the source file might exceed `maxFileMb`, the CDN may be unavailable, or the response might not be an MP4. Inspect `mediaUrl` only when permitted to access it, or retry later with an appropriate cap (maximum 25 MB).
- **Some posts skipped:** a multi-post run logs failures per post; inspect run logs for source-side errors. A single inaccessible post fails the run rather than reporting false success.

### FAQ

**Can it find videos by keyword or author?** No. Supply exact public post URLs. It does not search X timelines.

**Can it save every resolution?** It lists supported MP4 variants and stores only the highest-bitrate one per video. To choose a different variant, consume the returned variant URL under the source's terms.

**Does a metadata-only run save an MP4?** No. It returns variant URLs and null `fileUrl`/`fileBytes`.

### Related Actors

For authorized public video workflows on another platform, see [Reddit Public Video Downloader](https://apify.com/automation-lab/reddit-public-video-downloader) or [Instagram Public Media Downloader](https://apify.com/automation-lab/instagram-public-media-downloader). Neither substitutes for a public X post link.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation-lab/x-twitter-public-tweet-video-downloader/changelog.md

# Actor input Schema

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

Public x.com or twitter.com post URLs containing video or animated MP4 media (1–100).

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

Maximum video assets to emit (across all posts).

## `download` (type: `boolean`):

Download the best available MP4 to run storage. Disable for metadata and direct media URLs only.

## `maxFileMb` (type: `integer`):

Per-video size cap for stored MP4 files. Oversize files retain metadata and a source URL.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://x.com/nenkosyt/status/2030555563021471749"
    }
  ],
  "maxItems": 10,
  "download": true,
  "maxFileMb": 10
}
```

# Actor output Schema

## `overview` (type: `string`):

Structured public post video metadata and download status in the default dataset.

## `files` (type: `string`):

Stored MP4 objects in this run's default key-value store, when download is enabled and succeeds.

# 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": [
        {
            "url": "https://x.com/nenkosyt/status/2030555563021471749"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/x-twitter-public-tweet-video-downloader").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": [{ "url": "https://x.com/nenkosyt/status/2030555563021471749" }] }

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/x-twitter-public-tweet-video-downloader").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": [
    {
      "url": "https://x.com/nenkosyt/status/2030555563021471749"
    }
  ]
}' |
apify call automation-lab/x-twitter-public-tweet-video-downloader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/x-twitter-public-tweet-video-downloader"
        }
    }
}
```

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/ALfFsg1TZDbPPlSpH/builds/9N5ceOK81ToUHzodw/openapi.json
