# TikTok Video Downloader API (`lance_api/tiktok-video-downloader-api`) Actor

Download watermark-free TikTok videos from individual URLs or entire creator profiles. Supports bulk downloads, profile expansion, and structured TikTok metadata.

- **URL**: https://apify.com/lance\_api/tiktok-video-downloader-api.md
- **Developed by:** [LanceAPI](https://apify.com/lance_api) (community)
- **Categories:** AI, Social media, Agents
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $2.00 / 1,000 successful video results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## TikTok Video Downloader API

Download **watermark-free** TikTok videos and collect structured public video, creator, engagement, hashtag, and music data from individual links or complete profiles.

TikTok Video Downloader API is built for developers, data teams, creators, agencies, researchers, and AI workflows that need reliable TikTok video extraction without operating a browser or storing video files. Submit one video, process a large URL list, or turn a public creator profile into clean dataset records ready for your application, archive, or analysis pipeline.

The Actor provides **two input modes**:

- **Video URL mode** — extract one or many specific TikTok videos.
- **User / Profile mode** — retrieve matching videos from public TikTok creator profiles.

Use either mode independently or combine both in one run. Get one structured dataset item per unique successful video and **pay only for successful results**. The Actor processes **public content only** and returns **temporary download URLs** without downloading, transcoding, or permanently storing the video files.

### Perfect for

Developers building TikTok integrations, creators backing up public work, agencies monitoring accounts, researchers analyzing content and engagement, data teams creating creator datasets, and AI agents that need structured TikTok video data through Apify.

### Features

- Extracts a watermark-free video download URL
- Processes individual and shortened TikTok video links
- Expands public TikTok profiles into individual video results
- Supports handles, usernames, profile URLs, and numeric user IDs
- Paginates through profile videos until the requested result limit is reached
- Filters profile videos by publication date
- Optionally skips videos explicitly marked as pinned
- Returns video, creator, engagement, hashtag, and music metadata
- Deduplicates repeated users and videos across both input modes
- Keeps large TikTok video and user IDs as strings
- Isolates failures so one unavailable video or profile does not stop the complete run
- Charges only for unique successful video results

The Actor does not download or store video files. It returns a temporary public download URL that can be used by your application or download tool.

### Quick Start

1. Open the Actor in Apify Console.
2. Add one or more links under **TikTok video URLs**, or add a handle, username, profile URL, or numeric user ID under **TikTok users**.
3. For profile collection, choose a result limit and optional date or pinned-video filters.
4. Click **Start**.
5. Open the Dataset to copy or export the watermark-free URLs and structured TikTok metadata.

Minimal input for one video:

```json
{
  "videoUrls": [
    "https://www.tiktok.com/@pushingpistons/video/7656455579707264270"
  ]
}
```

### Common Use Cases

#### Single Video Download

Submit one standard or shortened TikTok URL and receive one **watermark-free** download URL together with public video, creator, engagement, hashtag, and music metadata.

#### Bulk Download

Process up to 1,000 TikTok video URLs in one run. Each URL is isolated, so an unavailable video does not stop the rest of the batch.

#### Creator Archive

Turn a public TikTok profile into a structured archive of creator videos. Control the maximum number of results and export the dataset for storage or further processing.

#### Creator Monitoring

Use profile inputs with rolling or absolute UTC date filters to collect recently published videos for account tracking, campaign monitoring, and competitive intelligence.

#### AI Workflows

Provide AI agents and automation pipelines with consistent TikTok video records instead of unstructured profile pages. The Actor can be called through Apify MCP Server for agent-driven data collection.

#### Content Research

Collect public descriptions, timestamps, hashtags, music details, creator information, and engagement statistics for trend discovery, media research, and content analysis.

### Input

At least one of `videoUrls` or `userInputs` must contain a value.

#### Video URL mode

Use `videoUrls` to process specific videos. Each submitted URL is handled independently.

Supported URL forms include:

```text
https://www.tiktok.com/@username/video/1234567890123456789
https://m.tiktok.com/.../video/1234567890123456789
https://vm.tiktok.com/...
https://vt.tiktok.com/...
https://www.tiktok.com/t/...
```

Example:

```json
{
  "videoUrls": [
    "https://www.tiktok.com/@pushingpistons/video/7656455579707264270",
    "https://vm.tiktok.com/ZMExample/"
  ]
}
```

Profile handles, usernames, profile URLs, and numeric user IDs must be provided in `userInputs`, not `videoUrls`.

#### User / Profile mode

Use `userInputs` to retrieve videos published by public TikTok profiles.

Supported values:

```text
@tiktok
tiktok
https://www.tiktok.com/@tiktok
107955
```

Purely numeric values in `userInputs` are treated as user IDs, not video IDs.

Available profile settings:

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `userInputs` | `string[]` | — | Handles, usernames, profile URLs, or numeric user IDs. Maximum 100 inputs. |
| `resultsLimit` | `integer` | `20` | Maximum number of matching videos returned for each user after filtering. Range: 1–1,000. |
| `onlyVideosNewerThan` | `string \| null` | `null` | Absolute UTC date such as `2026-07-01`, or a rolling period such as `30 days`, `2 weeks`, `3 months`, or `1 year`. Relative periods are measured back from the Actor run start time. |
| `onlyVideosOlderThan` | `string \| null` | `null` | Inclusive absolute UTC date in `YYYY-MM-DD` format. |
| `skipPinnedVideos` | `boolean` | `false` | When enabled, skips videos only when the profile response explicitly marks them as pinned. When disabled, the Actor does not actively filter pinned videos, but the profile feed may not return pinned videos or preserve the TikTok website's pinned-first order. |

Example:

```json
{
  "userInputs": [
    "@tiktok",
    "https://www.tiktok.com/@billieeilish",
    "107955"
  ],
  "resultsLimit": 50,
  "onlyVideosNewerThan": "3 months",
  "onlyVideosOlderThan": null,
  "skipPinnedVideos": true
}
```

#### Combined mode

Both modes can be processed in one run:

```json
{
  "videoUrls": [
    "https://www.tiktok.com/@pushingpistons/video/7656455579707264270"
  ],
  "userInputs": [
    "@tiktok",
    "107955"
  ],
  "resultsLimit": 20,
  "onlyVideosNewerThan": "30 days",
  "skipPinnedVideos": true
}
```

Profile filters do not affect videos submitted directly through `videoUrls`.

### Output

Every dataset item uses the same field set. A successful result looks like this:

```json
{
  "status": "success",
  "inputType": "profile",
  "inputUrl": "@tiktok",
  "videoUrl": "https://www.tiktok.com/@tiktok/video/7050551461734042926",
  "videoId": "7050551461734042926",
  "downloadUrl": "https://temporary-cdn.example/video.mp4",
  "fileSizeBytes": 16715359,
  "fileSizeMB": 16.72,
  "duration": 65.75,
  "width": 720,
  "height": 1280,
  "description": "TikTok video description",
  "coverUrl": "https://temporary-cdn.example/cover.jpeg",
  "authorUsername": "tiktok",
  "authorNickname": "TikTok",
  "authorId": "107955",
  "authorProfileUrl": "https://www.tiktok.com/@tiktok",
  "authorAvatarUrl": "https://temporary-cdn.example/avatar.jpeg",
  "authorVerified": true,
  "authorBio": "Public creator biography",
  "followerCount": 1000000,
  "followingCount": 50,
  "authorVideoCount": 500,
  "authorTotalLikes": 50000000,
  "viewsCount": 100000,
  "likesCount": 5000,
  "commentsCount": 100,
  "sharesCount": 50,
  "collectCount": 200,
  "hashtags": [
    "tiktok"
  ],
  "musicTitle": "Original sound",
  "musicAuthor": "TikTok",
  "isOriginalSound": true,
  "createdAt": "2026-06-28T12:38:46.000Z",
  "regionCode": "US",
  "isAd": false,
  "processedAt": "2026-08-02T13:55:09.000Z",
  "errorMessage": null
}
```

#### Important output fields

| Field | Description |
| --- | --- |
| `inputType` | `direct_video` when submitted as a video URL, or `profile` when discovered from a user profile. |
| `inputUrl` | The original value submitted by the user. One profile input can produce multiple results. |
| `videoUrl` | Standard TikTok URL for the current video. |
| `videoId` | TikTok video ID returned as a string to prevent precision loss. |
| `downloadUrl` | One selected watermark-free video URL. |
| `fileSizeBytes` | File size associated with the selected video version, when available. |
| `fileSizeMB` | Decimal megabytes calculated as bytes divided by 1,000,000. |
| `duration` | Video duration in seconds. |
| `createdAt` | Video publication time in ISO 8601 UTC format. |
| `processedAt` | Time when the result was processed, in ISO 8601 UTC format. |

Missing numeric information is returned as `null`, not automatically converted to zero. Hashtags are returned without the `#` prefix.

### Failure results

Invalid or unavailable inputs produce a structured failure item without stopping other work in the run:

```json
{
  "status": "profile_not_found",
  "inputType": "profile",
  "inputUrl": "@missing-user",
  "videoUrl": null,
  "videoId": null,
  "downloadUrl": null,
  "fileSizeBytes": null,
  "fileSizeMB": null,
  "duration": null,
  "width": null,
  "height": null,
  "description": "",
  "coverUrl": null,
  "authorUsername": "",
  "authorNickname": "",
  "authorId": null,
  "authorProfileUrl": null,
  "authorAvatarUrl": null,
  "authorVerified": null,
  "authorBio": "",
  "followerCount": null,
  "followingCount": null,
  "authorVideoCount": null,
  "authorTotalLikes": null,
  "viewsCount": null,
  "likesCount": null,
  "commentsCount": null,
  "sharesCount": null,
  "collectCount": null,
  "hashtags": [],
  "musicTitle": "",
  "musicAuthor": "",
  "isOriginalSound": null,
  "createdAt": null,
  "regionCode": null,
  "isAd": null,
  "processedAt": "2026-08-02T13:55:09.000Z",
  "errorMessage": "The TikTok profile could not be found."
}
```

Possible status values:

| Status | Meaning |
| --- | --- |
| `success` | A watermark-free download URL was found. |
| `invalid_input` | The submitted user value is unsupported. |
| `invalid_url` | The submitted TikTok video URL could not be resolved. |
| `profile_not_found` | The public profile could not be found. |
| `private_profile` | The profile is private. |
| `profile_videos_unavailable` | Profile information was available, but its public video list could not be retrieved. |
| `private_video` | The video is private or restricted. |
| `deleted_video` | The video has been deleted or does not exist. |
| `unsupported_post` | The post is not a supported standard video, such as an image carousel. |
| `download_unavailable` | Video metadata exists, but no compatible watermark-free URL was available. |
| `error` | A temporary or unclassified processing error occurred. |

### Date filtering behavior

- Date filters apply only to User / Profile mode.
- All date and time comparisons use UTC.
- Relative values are rolling periods measured back from the Actor run start time, which is used as one stable reference point for the complete run.
- `1 day` means the previous 24 hours, `2 days` means the previous 48 hours, and `2 weeks` means the previous 14 days. Relative values do not represent a set of local calendar dates.
- An absolute lower date such as `2026-08-02` is interpreted as `2026-08-02T00:00:00.000Z` and includes videos from the beginning of that UTC day.
- An absolute upper date such as `2026-08-02` includes videos through `2026-08-02T23:59:59.999Z`.
- Users in the United States or other time zones should convert their intended local boundary to the appropriate UTC date before using an absolute `YYYY-MM-DD` filter.
- The Actor keeps paginating after filtering until it reaches `resultsLimit`, the profile has no more videos, or an older chronological boundary is reached.
- A pinned old video does not by itself cause pagination to stop.

### Pinned video behavior

- Pinned videos are filtered only when `skipPinnedVideos` is enabled and the profile response explicitly marks a video as pinned.
- When `skipPinnedVideos` is disabled, the Actor does not actively remove pinned videos.
- The public profile feed can return videos in publication-time order instead of the pinned-first order shown on the TikTok website.
- Disabling the option therefore does not guarantee that pinned videos will be returned or appear before newer videos.

### Deduplication

Deduplication is applied at several levels:

- Repeated input strings are processed once.
- Different profile inputs that resolve to the same public account are expanded once.
- A video found through both direct URL mode and profile mode is returned once.
- Short and standard URLs resolving to the same video are returned once.

The first submitted source that discovers a video is retained as `inputUrl`.

### Pricing

**Only successful unique results are charged.** Failed inputs, duplicate videos, empty responses, and videos removed by filters are free.

The Actor uses pay-per-result pricing. Only a unique result with `status: "success"` triggers the `result` billing event, so you **pay only for successful results**.

- Free users: **$5 per 1,000 successful results** ($0.005/result)
- Paid Apify plans: membership discounts from **$3 to $2 per 1,000 successful results**
- Lowest member price: **$2 per 1,000 successful results** ($0.002/result)
- Invalid inputs, failures, empty results, filtered videos, and duplicates are not charged as successful results

The applicable membership discount is displayed by Apify before the run.

### AI Agent

This Actor supports AI-assisted TikTok data extraction through **Apify MCP Server**. An agent can run the Actor with video URLs or public profile inputs and work with the resulting structured dataset.

Example prompt:

> Run TikTok Video Downloader API for the public profile @tiktok, return up to 10 videos from the last 7 days, and summarize the descriptions, hashtags, and engagement data.

### Important notes

#### Temporary download URLs

Download and image URLs are delivered by public TikTok infrastructure and can expire. Save or consume a URL soon after the run. If an old URL no longer works, run the Actor again to obtain a fresh result.

#### Public content only

The Actor processes only publicly accessible TikTok videos and profiles. It does not bypass private accounts, private videos, geographic restrictions, login requirements, or other access controls.

#### Video files are not stored

The Actor does not download, transcode, re-upload, or permanently store video files. The dataset contains metadata and one selected download URL.

#### Supported content

The current version supports standard TikTok video posts. Image carousels, audio extraction, music downloads, and video conversion are not supported.

#### Metadata availability

Some metadata is not available for every video. Missing values are returned as `null` or an empty string according to the output schema. Engagement counts represent public values available when the run was performed and can change later.

#### Responsible use

Use downloaded content and public metadata in accordance with applicable laws, TikTok's terms, and the rights of content owners. You are responsible for how the returned data and download URLs are used.

### Support

Questions, feedback, or an issue with a run? Contact <lanceapi2026@hotmail.com>. When reporting a problem, include the public input format, Run ID, and returned status or error message, but never send private credentials.

# Actor input Schema

## `videoUrls` (type: `array`):

Add one or more TikTok video URLs. Each URL is processed independently and produces one video result.

## `userInputs` (type: `array`):

Add handles, usernames, profile URLs, or numeric user IDs.

## `resultsLimit` (type: `integer`):

Maximum number of matching videos to return for each user input after all filters have been applied.

## `onlyVideosNewerThan` (type: `string`):

Return only profile videos published on or after the specified time. Relative values such as 2 days are rolling periods measured back from the Actor run start time (2 days means the previous 48 hours, not two calendar dates). Absolute YYYY-MM-DD values start at 00:00 UTC. All comparisons use UTC. Direct video URLs are unaffected.

## `onlyVideosOlderThan` (type: `string`):

Return only profile videos published on or before the selected YYYY-MM-DD date. The complete UTC date is included through 23:59:59.999 UTC. All comparisons use UTC. Direct video URLs are unaffected.

## `skipPinnedVideos` (type: `boolean`):

Skip videos explicitly marked as pinned when pinned status is available in the profile video response. The profile feed may not include pinned videos in the same order as the TikTok website. When disabled, the Actor does not actively filter pinned videos, but pinned videos are not guaranteed to be returned. Direct video URLs are unaffected.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.tiktok.com/@pushingpistons/video/7656455579707264270"
  ],
  "resultsLimit": 20,
  "onlyVideosNewerThan": null,
  "onlyVideosOlderThan": null,
  "skipPinnedVideos": false
}
```

# 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 = {
    "videoUrls": [
        "https://www.tiktok.com/@pushingpistons/video/7656455579707264270"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lance_api/tiktok-video-downloader-api").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 = { "videoUrls": ["https://www.tiktok.com/@pushingpistons/video/7656455579707264270"] }

# Run the Actor and wait for it to finish
run = client.actor("lance_api/tiktok-video-downloader-api").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 '{
  "videoUrls": [
    "https://www.tiktok.com/@pushingpistons/video/7656455579707264270"
  ]
}' |
apify call lance_api/tiktok-video-downloader-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lance_api/tiktok-video-downloader-api"
        }
    }
}

```

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/i1wBxAR0BzUdIKEhX/builds/ifi1qcx4A8eUu6zpk/openapi.json
