X (Twitter) Video Downloader
Download the video from public X and Twitter posts as MP4, or the sound as MP3. No login or cookies. Pay per megabyte of file delivered.
How it works
- 1Open it on Apify
Hit Run on Apify — it opens the tool in the cloud, no install.
- 2Set the inputs
Adjust
urls,quality,audioOnly(sensible defaults are pre-filled). - 3Click Run
The tool runs on Apify’s cloud and collects the data for you.
- 4Export the results
Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.
Pricing
$0.00045 per megabyte downloaded = $0.45 per 1,000
| You are charged for | When | Price |
|---|---|---|
| Megabyte downloaded | Each 1 MB of media actually delivered, rounded up per file. Failed, refused or skipped downloads are not charged. | $0.00045 |
Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-09-13, and they are what you are actually charged.
Inputs
| Field | What it does | Type |
|---|---|---|
urls | One link per line, each to an X post with a video in it (x.com/name/status/...); twitter.com links work the same. A post holding several videos gives the first one; end the link with /video/2 for the second. Links from other sites are refused, with a pointer to the downloader that takes them. | array |
quality | Measured on the short side of the picture, so 1080 means 1920x1080 for a landscape video and 1080x1920 for a vertical one. If a video doesn't come in that quality you get the closest one it has. You pay per megabyte, so a higher quality costs more. | string |
audioOnly | Save just the video's sound, as a 128 kbit/s MP3, instead of the video. | boolean |
maxMegabytes | A video bigger than this is skipped before it is downloaded, and you are not charged for it. One run can hold files up to about 70% of its memory (716 MB at the default 1024 MB), so for anything bigger raise the run's memory as well. | integer |
What you get
A structured dataset — each result includes fields like:
titleauthordurationSecondsresolutionformatfileSizeBytesbilledMegabytesmediaUrlurlhostmediaKeyExport every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.
Related tools in Developer & Research Tools
Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.
GitHub Scraper
Search GitHub repos and users: stars, forks, language, topics, licence, plus user bio, company and followers. No token needed. $0.90 per 1,000 rows.
Stack Overflow / Stack Exchange Scraper
Search Stack Overflow and Stack Exchange by keyword or tag. Score, answer count, views, reputation and body text. $2 per 1,000 questions.
Package Registry Scraper (npm + PyPI)
Get npm and PyPI package metadata as JSON. Version, license, author, repo, keywords and npm monthly downloads. $2 per 1,000 packages.
arXiv Scraper
Search arXiv papers by title, author, abstract or category. Get full abstracts, authors, categories, DOI, dates and PDF links. $2 per 1,000 papers.
OpenAlex Scholarly Works Scraper
Search 250M+ OpenAlex papers with no API key. Get titles, authors, venue, year, citations, DOI, OA links and full abstracts. $2.00 per 1,000 papers.
Crossref Scholarly Works Scraper
Search 150M+ papers on Crossref: DOI, title, authors, journal, publisher, date, citations and abstract. No API key. $1.00 per 1,000 works.
Where this tool sits
- Categories
- Developer & Research Tools
X (Twitter) Video Downloader: save the video from a public post as MP4, or its sound as MP3
Paste links to public X or Twitter posts, one per line. Each video is saved into the run's key-value store as a real file, and the dataset row that goes with it carries a direct download link, the title, the author, the resolution and the exact file size.
The part worth knowing first: this only reaches posts anyone can open signed out. A protected account, a post behind a login, or a deleted one comes back as a sentence in the run's ERRORS record and costs nothing.
| Input | Public x.com or twitter.com post links |
| Output | An MP4 or MP3 file per link, plus one dataset row listing it |
| Ceiling | 500 MB per video by default, 4,000 MB at most |
| Account needed | None |
| Price | $0.00045 per megabyte delivered, flat on every plan |
🎬 What X Video Downloader does
You give it post links. For each one it reads the post, picks the format, checks the file size before a single media byte moves, downloads it, checks the file actually decodes, stores it, and only then lists it in the dataset.
X publishes the same picture twice, as one ready-made MP4 and as a streaming version split into picture and sound. This takes the ready-made MP4, so the file arrives whole with its audio already in it and its size known in advance. Nothing is stitched together afterwards.
With Audio only on you get a 128 kbit/s MP3 of the same post instead.
No login, no cookies, nothing to paste in besides the link.
📥 What you give it
{
"urls": [
"https://x.com/historyinmemes/status/1790637656616943991",
"https://twitter.com/someone/status/1234567890123456789"
],
"quality": "1080",
"audioOnly": false,
"maxMegabytes": 500
}
| Field | Default | What it is |
|---|---|---|
urls | required | One link per line. x.com and twitter.com both work, with or without www. or mobile.. Query strings are ignored. |
quality | 1080 | best, 1080, 720, 480 or 360, measured on the short side of the picture. A video that does not come in that size gives you the closest it has. |
audioOnly | false | An MP3 of the sound instead of the video. |
maxMegabytes | 500 | 1 to 4,000. A video bigger than this is skipped before it is downloaded. |
A post with several videos gives you the first one. End the link with /video/2 to ask for the second instead.
Duplicates are dropped, and a link that points somewhere else is refused with a note telling you which actor takes it. A t.co short link is refused too: open it, and paste the address it lands on.
File size is bounded by the run's memory. A run can hold a file of roughly 70% of the memory it was given, so about 716 MB at the default 1,024 MB. If you want something bigger than that, raise the run's memory as well as maxMegabytes.
📤 What you get back
Two things per link: the file in the run's key-value store, and a row in the dataset pointing at it.
A real row, from run 4kPIloPIN7IwX9npC, with the signed link trimmed:
{
"url": "https://x.com/historyinmemes/status/1790637656616943991",
"host": "x",
"title": "Historic Vids - One of the most intense moments in history",
"author": "Historic Vids",
"durationSeconds": 15.56,
"resolution": "728x720",
"format": "mp4",
"fileSizeBytes": 1404023,
"billedMegabytes": 2,
"mediaKey": "x-1790637589910654976.mp4",
"mediaUrl": "https://api.apify.com/v2/key-value-stores/E2Boy2HNCFDNWIzez/records/x-...?signature=..."
}
| Field | What it is |
|---|---|
mediaUrl | A ready-to-use download link to the stored file. This is what you hand to whatever comes next. |
mediaKey | The record name in the run's key-value store. It uses the media id, which is not the post id. |
fileSizeBytes | The size of the stored file, read back after it was written. |
billedMegabytes | What that file counted as, in whole megabytes. |
title | The account name, then the post's text. |
resolution, durationSeconds | Read off the finished file, not off the post. |
🧾 Reading the output
A failure never reaches the dataset. Every row in there is a file that exists and was stored.
Links that did not work go into a key-value record called ERRORS, each as {url, error} with the reason written in plain words. It is saved as each failure happens, so a run that runs out of time still tells you what it managed and what it did not.
The sentences you will actually see:
| What you read | What it means |
|---|---|
| "This post is gone, or its video was removed." | The post or its media is no longer there. |
| "This post is only visible to signed-in accounts." | Protected or otherwise not public. Only public posts can be read. |
| "This post has no video in it." | A photo or text post, or a GIF with no video stream. |
| "X is limiting requests right now." | Too many in a short time. Come back in a few minutes. |
| "t.co is X's link shortener." | Open it in a browser and paste the address it lands on. |
| "This video has no sound to turn into an MP3." | Audio-only was asked for on a silent video. |
If every link in a run fails, the run ends as failed and the status message points at ERRORS.
▶️ How to run it
1. Open X (Twitter) Video Downloader and click Try for free. 2. Paste your post links into X post links, one per line. 3. Pick a Max quality, or tick Audio only (MP3). 4. Set Max megabytes per video if you want a tighter cap than 500. 5. Click Start, then take mediaUrl from each dataset row, or open the run's Storage tab.
💰 How much does it cost?
$0.00045 for every megabyte delivered, counted in whole megabytes and the same on every Apify plan. The 15-second clip in the example above counted as 2 MB.
You are billed only after a file is stored and listed, so a link that fails, a post that is private or gone, a link to another site, and a video skipped for being over maxMegabytes all add no megabytes. A run that delivers no files has none to bill.
Higher quality means a bigger file, and a bigger file costs more. audioOnly is much smaller than video on the same post.
💡 What people use it for
- Keeping a copy of a clip before the post that carries it disappears.
- Pulling the audio out of an interview or a speech to transcribe it somewhere else.
- Feeding
mediaUrlinto an editor, a captioner or an uploader as the next step in a pipeline. - Archiving a set of posts at a fixed quality so file sizes stay predictable.
🚧 What it does not do
- Public posts only. Protected accounts and anything behind a login fail with a sentence saying so.
- No photos, no GIF-only posts, no Spaces and no broadcasts.
- The first video of a multi-video post unless you ask for another with
/video/<n>. - No post text, likes, replies or metrics. The
titlecarries the post's text and that is all.
For the post as data, use a scraper instead.
- No
t.colinks. They are refused with an instruction rather than followed. - No subtitles or captions.
- Files live in the run's key-value store, which is not permanent. Copy anything you want to
keep, and treat mediaUrl as a link to fetch now rather than store for later.
- One file per link, so a run's total is bounded by what the run can hold in memory.
🧭 Which downloader do you need?
| If you want | Use |
|---|---|
| The video from an X or Twitter post | This one |
| A YouTube video, up to 8K, or its audio or captions | YouTube Downloader Pro |
| A TikTok video | TikTok Video Downloader |
| A Facebook video or reel | Facebook Video Downloader |
| Posts as data rather than as files | Tweet Scraper |
❓ Questions people ask
Do I need an X account or cookies? No. Nothing to paste in and nothing that expires.
Where is my file? In the run's key-value store. The fastest way to it is mediaUrl on the dataset row; the Storage tab of the run shows the same records under mediaKey.
Can I download a whole account's videos? Not from here. This takes links you supply. Use a scraper to collect the post links first, then feed them in.
Why is my video smaller than 1080p? Because the post does not have a 1080p version. You get the closest size X published.
What happens if one link is dead? It goes to ERRORS with a reason, adds nothing to your bill, and the run carries on with the rest.
Is downloading these videos legal? The post being public does not make the video yours. Copyright still applies, and so does data-protection law where a person is identifiable. Have a reason for what you are collecting. Apify's write-up on scraping and the law is a fair start, and we are not lawyers.
🆘 If something breaks
Open the Issues tab on the actor page. Send the run ID and the exact post link, and paste the ERRORS record from the run's key-value store: it carries the sentence for every link that failed.