All guides
Developers5 min readBy DrummerduckJul 17, 2026

TikTok Video Downloader API (REST)

You're building something that needs the video out of a TikTok. Maybe a bot that mirrors clips to another platform, a research script archiving public posts, or a feature that lets your users save a video without leaving your app. TikTok's own developer program can get you there in theory, but you're now looking at an application review, scope approvals, and a Content Posting API aimed at publishing rather than pulling. All you wanted was the no-watermark MP4 behind a URL.

This is a plain JSON API for exactly that. Give it a public TikTok link and it hands back the author, the caption, the cover image, and direct URLs for the clean video and the audio track. 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=<TIKTOK_URL> for the media metadata and direct links, or GET /api/download?url=<TIKTOK_URL> to stream the no-watermark 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 TikTok 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 access logs.

curl "https://download-tiktok-video.drummerduck.com/api/extract?url=https://www.tiktok.com/@tiktok/video/7106594312292453675"

From JavaScript, the same call with a POST body:

const res = await fetch(
  "https://download-tiktok-video.drummerduck.com/api/extract",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      url: "https://www.tiktok.com/@tiktok/video/7106594312292453675",
    }),
  },
);
const { ok, data } = await res.json();
const clean = data.media[0].variants[0]; // no-watermark video first

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

{
  "source": "tiktok",
  "id": "7106594312292453675",
  "url": "https://www.tiktok.com/@tiktok/video/7106594312292453675",
  "author": { "name": "TikTok", "handle": "tiktok", "avatar": "https://..." },
  "text": "the caption text",
  "createdAt": "2024-01-01T00:00:00.000Z",
  "thumbnail": "https://p16-sign.tiktokcdn-us.com/.../cover.jpg",
  "media": [
    {
      "type": "video",
      "poster": "https://.../cover.jpg",
      "durationMs": 15000,
      "width": 1080,
      "height": 1920,
      "variants": [
        {
          "quality": "no-watermark",
          "width": 1080,
          "height": 1920,
          "container": "mp4",
          "mimeType": "video/mp4",
          "url": "https://v16.tiktokcdn.com/.../video.mp4"
        }
      ]
    },
    {
      "type": "audio",
      "container": "mp3",
      "mimeType": "audio/mpeg",
      "url": "https://.../audio.mp3"
    }
  ],
  "engine": "tiktok"
}

The variants array comes back with the clean, no-watermark video first, so data.media[0].variants[0].url is usually the file you want. A post can carry more than one media item: media[].type is one of "video", "image" (a frame from a photo-mode carousel), or "audio" (the sound track, covered in the MP3 guide). Check the type before you assume there's a video to pull, since photo-mode posts return images plus audio rather than a single clip.

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 HTTP client writes it straight to disk with a sensible filename. It defaults to the no-watermark video.

curl -L -o video.mp4 \
  "https://download-tiktok-video.drummerduck.com/api/download?url=https://www.tiktok.com/@tiktok/video/7106594312292453675"

The parameters:

| Parameter | Required | Meaning | | --- | --- | --- | | url | yes | The TikTok post URL (short vm.tiktok.com links work too) | | quality | no | A variant label; defaults to the clean no-watermark video. Use mp3 for audio only | | n | no | Media index for photo-mode posts with several attachments; defaults to the best video |

Pass -L to curl so it follows the redirect to the CDN 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-tiktok-video.drummerduck.com/api/extract?url=https://www.tiktok.com/@tiktok/video/7106594312292453675"

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 nears 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": "Video not found" } }

| Code | Meaning | | --- | --- | | INVALID_URL | The URL isn't a valid TikTok link | | NOT_FOUND | The post doesn't exist or was deleted | | NO_MEDIA | The post has no downloadable media | | PRIVATE | The account or post is private or friends-only | | REGION_LOCKED | The video is restricted in the server's region | | RATE_LIMITED | You hit a rate limit (HTTP 429) | | UPSTREAM_ERROR | TikTok returned an error |

Troubleshooting

Getting NO_MEDIA on a post that clearly has a video. Confirm you're passing the URL of the post itself, not a profile link or a sound page that only references it. The video has to live on the post you send.

PRIVATE on a public-looking account. Private and friends-only posts gate their media behind a login, so no anonymous request can reach them. A key doesn't change that.

REGION_LOCKED even though it plays for you. Some clips only play in certain countries. If the server sits where the video is blocked, extraction fails while it still works on your own device.

Intermittent UPSTREAM_ERROR. TikTok 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 the audio and photo-mode images through the API?

Yes. Read media[].type: "audio" items are MP3 tracks and "image" items are photo-carousel frames. Both include direct URLs the same way videos do.

Is every video really watermark-free?

The default video variant is the clean, no-watermark source. That's the file /api/download returns unless you ask for the mp3 audio instead.

Is there a version for AI agents?

Yes. An MCP server wraps the same engine so assistants 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 the creator's rights and copyright.