# TikTok Public Video Downloader (`automation-lab/tiktok-public-video-downloader`) Actor

Download authorized public TikTok videos, covers, and audio to Apify storage with creator, format, size, source, and retrieval metadata.

- **URL**: https://apify.com/automation-lab/tiktok-public-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 $1.56 / 1,000 media-result 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

## TikTok Public Video Downloader

Download authorized public TikTok videos, cover images, and exposed audio from supplied URLs.
This **TikTok video downloader** saves the selected files to the run's Apify key-value store and returns a structured dataset record with video identity, creator, format, byte size, source URL, storage key, storage URL, and retrieval status.

It is designed for repeatable creator backups, campaign asset archives, rights-managed media libraries, and downstream workflows that need stored files rather than short-lived playback links.

### What does this Actor do?

For every supported public TikTok video URL, the Actor:

1. validates that the URL belongs to TikTok;
2. resolves short mobile links to the public video;
3. reads public video and creator metadata;
4. resolves currently accessible TikTok CDN media;
5. downloads the requested MP4, cover, and/or audio;
6. checks HTTP status, content type, and file-size limits;
7. stores files in the run key-value store;
8. writes one typed record to the default dataset.

A result is created only when at least one requested file is actually stored.
Metadata-only responses are not billed as successful media results.

### Who is it for?

- **Creators and agencies** backing up authorized campaign assets.
- **Social media teams** assembling reusable media libraries.
- **Rights holders** archiving public copies of their own content.
- **Researchers** collecting a bounded set of authorized media files with provenance.
- **Automation builders** moving TikTok assets into cloud storage, review queues, or transcription pipelines.
- **Developers** who need a URL-to-file API without maintaining download and storage logic.

### Why use this TikTok video downloader?

The Actor combines media retrieval and Apify storage in one run.
It returns durable run-storage references instead of making callers depend only on expiring TikTok CDN URLs.

Useful differentiators include:

- independent selection of video, cover, and audio assets;
- one record per supplied TikTok video;
- deterministic file keys based on TikTok video IDs;
- exact file sizes and detected content types;
- explicit `downloaded` versus `partial` status;
- source and resolver provenance in every result;
- fail-closed behavior when no requested media is stored;
- no login, cookies, or user account input;
- no automatic residential proxy or browser charges.

### Supported URLs and media

The input accepts public HTTPS URLs on:

- `www.tiktok.com`;
- `m.tiktok.com`;
- `vm.tiktok.com`;
- `vt.tiktok.com`;
- `tiktok.com`.

Private, deleted, region-restricted, login-only, photo/slideshow, and inaccessible posts may not produce downloadable video media.
Only assets anonymously exposed for the supplied public post are processed.

Available `mediaTypes` are:

| Value | Stored content | Typical format |
| --- | --- | --- |
| `video` | Public video rendition | MP4 |
| `cover` | Public cover image | JPEG, PNG, or WebP |
| `audio` | Audio exposed for the video | M4A or MP3 |

The Actor does not transcode files.
The detected response content type determines the stored extension.

### Input parameters

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `startUrls` | array | required | Public TikTok video URLs or request-list source objects. |
| `mediaTypes` | array | video, cover, audio | Assets to download for each URL. |
| `maxItems` | integer | 10 | Maximum unique supplied URLs to process; range 1–50. |
| `maxFileSizeMb` | integer | 20 | Per-file byte safety limit; range 1–80 MB. |
| `maxRetries` | integer | 2 | Retries for transient TikTok page failures; range 0–4. |

Duplicate normalized URLs are processed once.
Processing is serial to keep memory and transfer bounded while files are buffered for storage.

### Getting started

1. Open the Actor in Apify Console.
2. Add one or more public TikTok video URLs to **Public TikTok video URLs**.
3. Choose video, cover, audio, or a combination under **Media to download**.
4. Keep the file-size limit appropriate for your storage workflow.
5. Click **Start**.
6. Open **Media records** for structured metadata.
7. Open **Downloaded files** to inspect the stored MP4, image, and audio objects.
8. Export the dataset or connect it to your next automation step.

Start with one known public URL when evaluating the Actor.
Then increase `maxItems` only after confirming typical file sizes for your content.

### Example input

```json
{
  "startUrls": [
    {
      "url": "https://www.tiktok.com/@on_todays_bake/video/7618942237535194390"
    }
  ],
  "mediaTypes": ["video", "cover", "audio"],
  "maxItems": 1,
  "maxFileSizeMb": 20,
  "maxRetries": 2
}
```

For an audio-only workflow:

```json
{
  "startUrls": [
    {
      "url": "https://www.tiktok.com/@hescooks/video/7522563578969214216"
    }
  ],
  "mediaTypes": ["audio"],
  "maxItems": 1
}
```

### Output fields

| Field | Meaning |
| --- | --- |
| `inputUrl` | URL supplied by the caller. |
| `canonicalUrl` | Resolved canonical TikTok URL. |
| `videoId` | Stable TikTok video identifier. |
| `caption` | Public post caption. |
| `creatorUsername` | Public creator username. |
| `creatorName` | Public display name when available. |
| `createdAt` | Public creation timestamp when available. |
| `durationSeconds` | Video duration reported by TikTok. |
| `width`, `height` | Source dimensions reported by TikTok. |
| `video`, `cover`, `audio` | Stored file metadata or `null` when not requested/unavailable. |
| `status` | `downloaded` when all requested assets succeeded; otherwise `partial`. |
| `failedAssets` | Requested asset types that were not stored. |
| `mediaResolver` | Media URL resolution route used for provenance. |
| `scrapedAt` | Retrieval timestamp. |

Each stored asset object includes `sourceUrl`, `storageKey`, `storageUrl`, `contentType`, `bytes`, and `format`.
Fields may be null when TikTok does not expose the corresponding metadata or when that media type was not requested.

### Example output

```json
{
  "inputUrl": "https://www.tiktok.com/@on_todays_bake/video/7618942237535194390",
  "canonicalUrl": "https://www.tiktok.com/@on_todays_bake/video/7618942237535194390",
  "videoId": "7618942237535194390",
  "caption": "Hassle back potatoes with creamy Cajun chicken...",
  "creatorUsername": "on_todays_bake",
  "creatorName": "Ontodaysbake",
  "createdAt": "2026-03-19T12:27:12.000Z",
  "durationSeconds": 61,
  "width": 576,
  "height": 1024,
  "video": {
    "storageKey": "video-7618942237535194390.mp4",
    "storageUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/video-7618942237535194390.mp4",
    "contentType": "video/mp4",
    "bytes": 15880616,
    "format": "mp4"
  },
  "cover": {
    "storageKey": "cover-7618942237535194390.jpg",
    "contentType": "image/jpeg",
    "bytes": 28956,
    "format": "jpg"
  },
  "audio": {
    "storageKey": "audio-7618942237535194390.m4a",
    "contentType": "audio/mp4",
    "bytes": 492230,
    "format": "m4a"
  },
  "status": "downloaded",
  "failedAssets": [],
  "mediaResolver": "tikwm-public-api",
  "scrapedAt": "2026-09-15T14:08:30.036Z"
}
```

Temporary source URLs are included for provenance, not as durable download links.
Use each asset's `storageUrl` or `storageKey` for downstream access.

### How much does it cost to download public TikTok videos?

This Actor uses pay per event pricing:

- one `start` event at **$0.007 per run**;
- one `media-result` event for each supplied video that saves at least one requested file;
- no result event for invalid URLs or URLs where every requested file fails.

| Plan tier | Price per media result |
| --- | ---: |
| Free | $0.00299 |
| Bronze | $0.0026 |
| Silver | $0.002028 |
| Gold | $0.00156 |
| Platinum | $0.00156 |
| Diamond | $0.00156 |

For example, one successful Free-tier video costs $0.00999 in Actor events; five cost $0.02195. One successful Bronze-tier video costs $0.0096; ten cost $0.033.

The price is intentionally below the ordinary median of two exact TikTok download comparables at 1–25 items because their effective starts differ sharply; it remains above the 0.3× market floor at every required volume and reaches 0.76× at 100 results.
Your infrastructure usage and key-value-store retention are billed by Apify separately under your platform plan.
Large media files primarily affect transfer and storage usage, so use `mediaTypes` and `maxFileSizeMb` to avoid retrieving assets you do not need.

Examples:

- an audio-only request incurs one start and one media-result event if the audio is stored;
- a full video + cover + audio request still incurs one media-result event, not three;
- a two-URL batch with two useful stored records incurs one start and two media-result events.

### File storage and retention

Files are stored in the run's default key-value store under these prefixes:

- `video-<videoId>`;
- `cover-<videoId>`;
- `audio-<videoId>`.

Apify storage retention depends on your account and storage settings.
The Actor itself does not promise permanent hosting.
Move files to your own long-term bucket when your archival policy requires longer retention.

Dataset exports do not embed the binary files.
They contain references and metadata that your integration can follow.

### Partial results and failures

A record has `status: "partial"` when at least one requested file is stored but another requested file is unavailable, too large, has an unexpected content type, or fails retrieval.
Check `failedAssets` before treating a record as complete.

The run fails when:

- `startUrls` is empty;
- a URL is malformed or belongs to another domain;
- numeric limits are outside their documented range;
- no supplied URL produces any stored requested media.

When a mixed batch contains both successes and failures, useful records are preserved and failures are logged.

### Reliability and limitations

TikTok delivery behavior and signed CDN URLs can change without notice.
The Actor currently validates public post metadata from TikTok and uses the anonymous TikWM public endpoint to resolve current TikTok CDN media URLs.
The selected route appears in `mediaResolver` so downstream users can audit provenance.

Important limitations:

- no private, friends-only, age-gated, or login-only posts;
- no account credentials or CAPTCHA solving;
- no photo/slideshow extraction;
- no transcoding, clipping, merging, or quality conversion;
- no guarantee that TikTok exposes separate audio for every post;
- no automatic browser or residential-proxy fallback;
- upstream outages can cause clear failures;
- availability may vary by geography or creator restrictions.

### Tips for efficient runs

- Request only the media types your workflow needs.
- Use audio-only mode before transcription pipelines.
- Use video + cover for asset catalogs that do not need separate audio.
- Keep `maxFileSizeMb` below your downstream upload limit.
- Split very large URL lists into bounded Tasks.
- Inspect `bytes` before copying files to another service.
- Treat source CDN URLs as temporary.
- Schedule retries later rather than repeatedly retrying deterministic private/deleted posts.

### Automation workflows

#### Creator backup

Schedule a Task with URLs for assets you are authorized to archive.
Copy successful storage keys to your long-term object store and record the TikTok canonical URL alongside each file.

#### Campaign asset library

Download video and cover files, then send dataset records into Airtable, Google Sheets, or a digital asset management system.
Use `videoId` as a stable deduplication key.

#### Audio transcription

Select only `audio`, then pass the stored M4A/MP3 URL to an authorized transcription workflow.
Audio-only retrieval reduces unnecessary video transfer.

#### Quality-control queue

Filter dataset rows where `status` is `partial` or `failedAssets` is non-empty.
Route those rows to manual review without discarding successful assets.

### Run via the Apify API with cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~tiktok-public-video-downloader/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "startUrls": [{"url": "https://www.tiktok.com/@on_todays_bake/video/7618942237535194390"}],
    "mediaTypes": ["video", "cover", "audio"],
    "maxItems": 1
  }'
```

Poll the returned run, then read its default dataset and key-value store IDs.
Do not expose your Apify token in source control or browser-side code.

### Run via JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/tiktok-public-video-downloader').call({
  startUrls: [
    { url: 'https://www.tiktok.com/@on_todays_bake/video/7618942237535194390' },
  ],
  mediaTypes: ['video', 'cover'],
  maxItems: 1,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].video.storageUrl);
```

### Run via Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/tiktok-public-video-downloader').call(run_input={
    'startUrls': [
        {'url': 'https://www.tiktok.com/@hescooks/video/7522563578969214216'},
    ],
    'mediaTypes': ['audio'],
    'maxItems': 1,
})

items = client.dataset(run['defaultDatasetId']).list_items().items
print(items[0]['audio']['storageUrl'])
```

### Use with MCP and AI agents

#### Claude Code

Add the Actor through Apify MCP:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/tiktok-public-video-downloader"
```

#### Claude Desktop

Use this JSON configuration in Claude Desktop:

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

#### Cursor and VS Code

Use the same HTTP MCP server URL in Cursor or VS Code's MCP server settings:

`https://mcp.apify.com?tools=automation-lab/tiktok-public-video-downloader`

#### Example prompts

- "Download the video and cover from this authorized public TikTok URL and return the stored file links."
- "Extract only the audio from these public TikTok videos and list byte sizes."
- "Archive these campaign TikToks and flag partial downloads."

Always include explicit URLs and media types so the agent does not retrieve unnecessary files.

### Is it legal to download public TikTok videos?

Use this Actor only where your download and reuse are lawful. Public availability alone does not grant copyright or redistribution rights.

### Responsible use

Use this Actor only for content you own, are authorized to archive, or may lawfully process.
Respect copyright, privacy, publicity rights, TikTok's terms, and applicable laws.
Do not use it to bypass access controls, retrieve private content, impersonate creators, or redistribute media without permission.

The user is responsible for establishing a lawful purpose, choosing appropriate retention, and honoring deletion requests.
Public accessibility does not automatically grant reuse rights.

### Troubleshooting

#### Why did the run fail with no media records?

Confirm that the URL is a public TikTok video page and opens anonymously.
Private, deleted, slideshow, login-only, or region-restricted content may not expose downloadable media.
Try one known public URL before running a larger batch.

#### Why is the result partial?

Read `failedAssets`.
A requested asset may be absent, larger than `maxFileSizeMb`, temporarily blocked, or returned with an unexpected content type.
Successful requested assets remain stored.

#### Why is a storage URL unavailable later?

Run key-value stores follow your Apify retention settings.
Copy files to long-term storage before their retention period expires.

#### Does the Actor remove watermarks?

The Actor stores the public rendition returned by the current media resolver and does not edit or transcode it.
It does not promise watermark removal for every post or future TikTok delivery format.

#### Can it download profile feeds automatically?

No.
This Actor intentionally accepts explicit video URLs only.
Use a discovery Actor first, review authorization and scope, then pass selected public video URLs to this downloader.

### Related Actors

- [TikTok Video Records Scraper](https://apify.com/automation-lab/tiktok-video-records-scraper) for metadata and engagement records without downloading binary files.
- [TikTok Scraper](https://apify.com/automation-lab/tiktok-scraper) for supported creator/profile and video discovery workflows.
- [Video to Text Transcriber](https://apify.com/automation-lab/video-to-text-transcriber) for authorized transcription after media retrieval.

### FAQ

**Does it require a TikTok account?**\
No. It processes only anonymously reachable public video URLs.

**Can I choose just one media type?**\
Yes. Set `mediaTypes` to `video`, `cover`, or `audio` alone.

**Are failed URLs charged as media results?**\
No. `media-result` is emitted only after at least one requested file is stored.

**Can I process duplicate URLs?**\
Duplicates are normalized and processed once per run.

**Where are files stored?**\
In the run's default Apify key-value store. Structured metadata is in the default dataset.

**Does it convert audio to MP3?**\
No. It preserves the exposed response format and reports the detected content type and extension.

**Can it process private TikToks?**\
No. The Actor does not accept credentials or bypass access controls.

**What happens when a file exceeds the limit?**\
That asset is skipped. If another requested asset succeeds, the record is `partial`; otherwise the URL fails.

# Changelog

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

# Actor input Schema

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

TikTok video URLs to archive. Canonical, mobile, vm.tiktok.com, and vt.tiktok.com links are accepted.

## `mediaTypes` (type: `array`):

Choose which exposed assets to save for each public video.

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

Maximum number of unique supplied URLs to process.

## `maxFileSizeMb` (type: `integer`):

Skip any individual media file larger than this safety limit.

## `maxRetries` (type: `integer`):

Retries for temporary TikTok page or network failures. Media downloads are not retried blindly.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.tiktok.com/@on_todays_bake/video/7618942237535194390"
    }
  ],
  "mediaTypes": [
    "video",
    "cover",
    "audio"
  ],
  "maxItems": 10,
  "maxFileSizeMb": 20,
  "maxRetries": 2
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing video, creator, file size, format, provenance, and retrieval status metadata.

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

Key-value store containing downloaded video, cover, and audio files.

# 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://www.tiktok.com/@on_todays_bake/video/7618942237535194390"
        }
    ],
    "mediaTypes": [
        "video",
        "cover",
        "audio"
    ],
    "maxItems": 10,
    "maxFileSizeMb": 20,
    "maxRetries": 2
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/tiktok-public-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://www.tiktok.com/@on_todays_bake/video/7618942237535194390" }],
    "mediaTypes": [
        "video",
        "cover",
        "audio",
    ],
    "maxItems": 10,
    "maxFileSizeMb": 20,
    "maxRetries": 2,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/tiktok-public-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://www.tiktok.com/@on_todays_bake/video/7618942237535194390"
    }
  ],
  "mediaTypes": [
    "video",
    "cover",
    "audio"
  ],
  "maxItems": 10,
  "maxFileSizeMb": 20,
  "maxRetries": 2
}' |
apify call automation-lab/tiktok-public-video-downloader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/tiktok-public-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/0ThpAAnywBRJVgNWm/builds/P0C3KeuPiXhqK3fD5/openapi.json
