All guides
Developers5 min readBy DrummerduckJul 17, 2026

Twitter Video Downloader API (REST)

You're building something that needs the video out of a tweet. Maybe a bot that reposts clips to another platform, a research script archiving public posts, or a side project that lets people save a video without leaving your app. The official Twitter API can technically do it, but you're now staring at a developer application form, an approval wait, OAuth token juggling, and a media endpoint that changes terms every few months. All you wanted was the MP4 behind a URL.

This is a plain JSON API for exactly that. Give it a public tweet link and it hands back the author, the text, the thumbnail, and every downloadable video, GIF, and image variant with direct URLs. There are two endpoints, no OAuth dance, and an anonymous tier you can call right now with curl. The full reference lives on the developers page; this guide is the practical walkthrough.

Short answer: call GET /api/extract?url=<TWEET_URL> for the media metadata and direct links, or GET /api/download?url=<TWEET_URL>&quality=1080p to stream the MP4 straight back as a file.

Try it now

Paste a Twitter/X link and download in seconds — free, no login.

Open the downloader

GET /api/extract

This is the endpoint you'll use most. Pass a tweet URL as the url query parameter and it returns everything the post contains. You can also POST a JSON body of {"url":"..."} if you'd rather keep the link out of your logs.

curl "https://download-twitter-video.drummerduck.com/api/extract?url=https://x.com/SpaceX/status/1919172303709184350"

From JavaScript, the same call with a POST body:

const res = await fetch(
  "https://download-twitter-video.drummerduck.com/api/extract",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ url: "https://x.com/i/status/1919172303709184350" }),
  },
);
const { ok, data } = await res.json();
const best = data.media[0].variants[0]; // highest quality first

A success response is { "ok": true, "data": <result> }. The data object looks like this, trimmed for readability:

{
  "source": "twitter",
  "id": "1919172303709184350",
  "url": "https://x.com/SpaceX/status/1919172303709184350",
  "author": { "name": "SpaceX", "handle": "SpaceX", "avatar": "https://..." },
  "text": "the tweet text",
  "createdAt": "2024-01-01T00:00:00.000Z",
  "thumbnail": "https://pbs.twimg.com/.../thumb.jpg",
  "media": [
    {
      "type": "video",
      "poster": "https://.../poster.jpg",
      "durationMs": 30000,
      "width": 1920,
      "height": 1080,
      "variants": [
        {
          "quality": "1080p",
          "width": 1920,
          "height": 1080,
          "bitrate": 2176000,
          "container": "mp4",
          "mimeType": "video/mp4",
          "url": "https://video.twimg.com/.../1920x1080.mp4"
        }
      ]
    }
  ],
  "engine": "syndication"
}

The variants array comes back sorted with the highest quality first, so data.media[0].variants[0].url is usually the file you want. A tweet can carry several media items, and each media[].type is one of "video", "gif" (a silent MP4, covered in the GIF guide), or "image". Check the type before you assume there's a video to pull.

GET /api/download

When you want the bytes rather than a link, /api/download streams the chosen variant back with a Content-Disposition header, so a browser or an HTTP client writes it straight to disk with a sensible filename.

curl -L -o video.mp4 \
  "https://download-twitter-video.drummerduck.com/api/download?url=https://x.com/SpaceX/status/1919172303709184350&quality=1080p&n=0"

The parameters:

| Parameter | Required | Meaning | | --- | --- | --- | | url | yes | The tweet URL | | quality | no | A variant label like 1080p or 720p; defaults to the best video. More in the 1080p guide | | n | no | Media index for tweets with more than one attachment; defaults to the best video |

Pass -L to curl so it follows the redirect to the media host, and -o to name the output file.

Authentication

Auth is optional. Every endpoint works anonymously inside the per-IP limits below. Send an API key when you need higher throughput, either as a bearer token or an X-API-Key header:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://download-twitter-video.drummerduck.com/api/extract?url=https://x.com/i/status/1919172303709184350"

Rate limits

Without a key you get 30 requests per hour and 100 per day, counted per IP. A key raises that, defaulting to 300 per hour and 2000 per day. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset so you can throttle before you hit the wall. Go over and you get an HTTP 429 with a Retry-After header telling you how long to wait. In a script, read X-RateLimit-Remaining and back off as it approaches zero rather than retrying into a 429.

Errors

Failures come back as { "ok": false, "error": { "code": "...", "message": "..." } }, so you can branch on code without parsing prose:

{ "ok": false, "error": { "code": "NOT_FOUND", "message": "Tweet not found" } }

| Code | Meaning | | --- | --- | | INVALID_URL | The URL isn't a valid tweet link | | NOT_FOUND | The tweet doesn't exist or was deleted | | NO_MEDIA | The tweet has no downloadable media | | PROTECTED | The account is protected or private | | RATE_LIMITED | You hit a rate limit (HTTP 429) | | UPSTREAM_ERROR | Twitter returned an error |

Troubleshooting

Getting NO_MEDIA on a tweet that clearly has a video. Confirm you're passing the URL of the post itself, not a quote-tweet or a reply that only references it. The video has to live on the tweet you send.

PROTECTED on a public-looking account. Protected accounts gate their media behind a login, so no anonymous request can reach it. There's nothing a key can do here either.

Intermittent UPSTREAM_ERROR. Twitter occasionally rate-limits or hiccups upstream. Retry once after a short pause before treating it as a hard failure.

Frequently asked questions

Do I need an API key?

No. The API works anonymously within the per-IP limits. A key only raises them.

Can I download GIFs and images through the API?

Yes. Read media[].type: "gif" items are silent MP4s and "image" items are photos. Both include direct URLs the same way videos do.

Is there a version for AI agents?

Yes. An MCP server wraps the same engine so agents can call it conversationally. Everything is documented together on the developers page. Non-developers can use the web downloader or the how-to guide.

Try it now

Paste a Twitter/X link and download in seconds — free, no login.

Open the downloader

Only download public content you have the right to use, and respect copyright.