# TikTok Video Scraper - Video Details & Profile Feeds (`khadinakbar/tiktok-video-scraper`) Actor

Scrape TikTok video details, captions, metrics, direct video URLs, transcripts, music, hashtags, and creator profile videos. Provider-backed, no cookies required, perfect for SEO and AI agents, MCP optimized.

- **URL**: https://apify.com/khadinakbar/tiktok-video-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Social media, Lead generation, Automation
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 scraped tiktok videos

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Scraper - Video Details & Profile Feeds

Scrape TikTok video details from direct video URLs and creator profile feeds. This Apify Actor returns one normalized record per video with captions, engagement metrics, author fields, music metadata, hashtags, direct video URLs, transcript text when requested, and provider-hosted media URLs when enabled. The dataset is designed for AI agents, SEO workflows, social listening, creator research, and structured downstream processing through Apify or Apify MCP.

Accepted input includes one or more TikTok video URLs, creator profile handles, or profile URLs. For each returned video, one dataset item represents a single TikTok record, including fields such as `videoUrl`, `caption`, `authorUsername`, `playCount`, `likeCount`, `commentCount`, `shareCount`, `musicTitle`, and `scrapedAt`. The outcome is a clean dataset of TikTok video rows plus a run summary with provider usage and billing counters.

### Best fit and connected workflows

This Actor fits workflows that start with a known TikTok video or a known creator profile and need structured video details.

Common routing patterns:

- Start with [TikTok Search Scraper - \[Videos, Hashtags & Users\]](https://apify.com/khadinakbar/tiktok-search-scraper) when you need discovery by query, hashtag, or user search, then pass the verified video URL into this Actor for detailed extraction.
- Start with [TikTok Trending Videos Scraper](https://apify.com/khadinakbar/tiktok-trending-videos-scraper) when you need trending discovery, then hand selected video URLs to this Actor for normalized records.
- Use this Actor when the workflow already has a direct video URL or a creator feed and the next step is enrichment for analytics, content review, or agent reasoning.

### Practical scenario

Maya, a social media analyst, already has a TikTok video URL from a campaign report and a creator handle from the same account. She runs this Actor with the video URL, the profile handle, `getTranscript` enabled, and `sortBy` set to `latest`.

The returned row includes the caption, author username, verified status, views, likes, comments, shares, music title, and transcript text when available. Maya uses the `caption`, `transcript`, and `engagementRate` fields to compare messaging across posts, then sends the most relevant video URL to a content team for review.

### Input

#### Input fields

| Field | Type | Default | Purpose |
| --- | --- | --- | --- |
| `videoUrls` | array | `[]` | Direct TikTok video URLs to inspect one by one. |
| `profileHandles` | array | `[]` | Creator handles or profile URLs for recent or popular profile-feed videos. |
| `providerOrder` | string | `scrapecreators-first` | Provider order for public-data lookup. |
| `maxVideosPerProfile` | integer | `50` | Cap for saved videos from each profile. |
| `maxPagesPerProfile` | integer | `10` | Pagination cap for provider-backed profile feeds. |
| `maxTotalVideos` | integer | `10000` | Whole-run safety and billing guard. |
| `sortBy` | string | `latest` | Profile sorting when supported by the provider. |
| `region` | string | `US` | Alpha-2 region code used in provider requests. |
| `getTranscript` | boolean | `false` | Include transcript text for direct video URLs when available. |
| `downloadMedia` | boolean | `false` | Request provider-hosted permanent media URLs. |
| `trim` | boolean | `true` | Request a smaller provider payload. |
| `includeRawData` | boolean | `false` | Attach the original provider payload to each dataset row. |

#### Focused input example

```json
{
  "videoUrls": [
    "https://www.tiktok.com/@stoolpresidente/video/7324105620095765765"
  ],
  "profileHandles": [
    "stoolpresidente"
  ],
  "providerOrder": "scrapecreators-first",
  "maxVideosPerProfile": 5,
  "maxPagesPerProfile": 1,
  "maxTotalVideos": 100,
  "sortBy": "latest",
  "region": "US",
  "getTranscript": true,
  "downloadMedia": false,
  "trim": true,
  "includeRawData": false
}
```

### Output

Each dataset item is one normalized TikTok video record. The overview dataset view highlights `videoUrl`, `authorUsername`, `caption`, views, likes, comments, shares, `noWatermarkUrl`, `musicTitle`, and `createdAt`.

#### Output fields

| Field | Description |
| --- | --- |
| `recordType` | Record category, such as `video`. |
| `sourceType` | `direct` for video URLs, `profile` for creator feeds. |
| `provider` | Provider that returned the source data. |
| `input` | Original URL or handle that produced the row. |
| `profileHandle` | Creator handle for profile-feed rows. |
| `sortBy` | Sort order used for the profile-feed row. |
| `resultPosition` | Position in the returned result set. |
| `page` | Provider page number for the row. |
| `videoId` | TikTok video ID. |
| `videoUrl` | Canonical TikTok video page URL. |
| `caption` | TikTok caption text. |
| `createdAt` | Published timestamp when returned. |
| `authorUsername` | TikTok creator handle. |
| `authorNickname` | TikTok creator display name. |
| `authorVerified` | Verified status returned by TikTok. |
| `authorFollowerCount` | Creator follower count when provided. |
| `region` | Region code returned for the video. |
| `durationMs` | Video duration in milliseconds when available. |
| `coverUrl` | Static cover image URL. |
| `playUrl` | Direct signed play URL. |
| `downloadUrl` | Direct signed download URL when returned. |
| `noWatermarkUrl` | No-watermark video URL when returned. |
| `downloadedMediaUrls` | Provider-hosted permanent media URLs when enabled. |
| `transcript` | Transcript text, usually WEBVTT, for direct URL requests when enabled. |
| `isAd` | Ad marker returned by TikTok. |
| `isPhotoPost` | Indicates a photo carousel. |
| `imageUrls` | Image URLs for photo posts. |
| `playCount` | Views. |
| `likeCount` | Likes. |
| `commentCount` | Comments. |
| `shareCount` | Shares. |
| `collectCount` | Saves. |
| `engagementRate` | Approximate engagement rate. |
| `hashtags` | Hashtags attached to the video. |
| `musicId` | Sound or music ID. |
| `musicTitle` | Sound or song title. |
| `musicAuthor` | Music artist or sound owner. |
| `scrapedAt` | Timestamp when the row was normalized. |

#### Illustrative output record

```json
{
  "recordType": "video",
  "sourceType": "direct",
  "provider": "scrapecreators",
  "input": "https://www.tiktok.com/@stoolpresidente/video/7324105620095765765",
  "profileHandle": null,
  "sortBy": null,
  "resultPosition": 1,
  "page": 1,
  "videoId": "7324105620095765765",
  "videoUrl": "https://www.tiktok.com/@stoolpresidente/video/7324105620095765765",
  "caption": "All right. Pizza review time",
  "createdAt": "2024-01-14T23:51:05.000Z",
  "authorUsername": "stoolpresidente",
  "authorNickname": "Dave Portnoy",
  "authorVerified": true,
  "authorFollowerCount": 3900000,
  "region": "US",
  "durationMs": 210155,
  "coverUrl": "https://p16-sign.tiktokcdn-us.com/...",
  "playUrl": "https://v45.tiktokcdn-eu.com/...",
  "downloadUrl": "https://v45.tiktokcdn-eu.com/...",
  "noWatermarkUrl": "https://v45.tiktokcdn-eu.com/...",
  "downloadedMediaUrls": [],
  "transcript": "WEBVTT\n\n00:00:00.140 --> 00:00:04.020\nAll right. Pizza review time",
  "isAd": false,
  "isPhotoPost": false,
  "imageUrls": [],
  "playCount": 589745,
  "likeCount": 62522,
  "commentCount": 618,
  "shareCount": 3585,
  "collectCount": 1633,
  "engagementRate": 0.1132,
  "hashtags": ["pizza", "review"],
  "musicId": "7324105763793668870",
  "musicTitle": "Never Gonna Give You Up",
  "musicAuthor": "Rick Astley",
  "scrapedAt": "2026-06-12T10:30:00.000Z"
}
```

### How it works

This Actor uses provider-backed public-data APIs rather than browser scraping. The live contract shows these provider options:

- `scrapecreators-first`
- `sociavault-first`
- `scrapecreators-only`
- `sociavault-only`

The default execution behavior prefers ScrapeCreators and falls back to SociaVault. The Actor supports:

- direct video URL requests,
- creator profile feed pagination,
- transcript retrieval for direct video URLs when enabled,
- optional permanent media URLs,
- optional raw provider payloads for debugging.

Normalized rows are written to the default dataset. Run-level diagnostics are stored in the key-value store under `RUN_SUMMARY`, including provider usage, counts, billing counters, and stop reason.

### Pricing

This Actor uses Pay per event plus Apify platform usage.

Charged events from the live contract:

- `apify-actor-start` - charged once per run, scaled by allocated memory
- `video-scraped` - charged for each normalized TikTok video row saved
- `media-downloaded` - charged when permanent provider-hosted media URLs are returned

Example in words: if a run saves twenty video rows and no permanent media URLs are returned, the billing includes twenty `video-scraped` events plus one actor start event. If permanent media URLs are returned for some rows, each of those rows also adds a `media-downloaded` event.

For current pricing details, always check the live Pricing tab on the Apify Actor page.

### Use with AI agents (MCP)

This Actor is available through Apify MCP as a tool for retrieving structured TikTok video data from known video URLs and creator profile feeds.

Exact Actor identity: `khadinakbar/tiktok-video-scraper`

Tool description:

- Input: direct TikTok video URLs and creator profile handles or profile URLs
- Output: normalized TikTok video rows with metadata, metrics, media URLs, transcript text when requested, and source fields for provenance
- Scope: public TikTok data returned by the configured provider order
- Pagination: creator feeds can page through provider results up to `maxPagesPerProfile`
- Cost guidance: each saved row triggers a `video-scraped` event; returned permanent media URLs trigger `media-downloaded`

> Collect the video details for these TikTok URLs, include transcript text when available, and return the dataset rows in a structured format for downstream analysis.

When used by agents, the most useful interpretation is:

- `videoUrl` and `input` identify provenance,
- `sourceType` distinguishes direct URLs from profile-feed rows,
- `page` and `resultPosition` show how the row was produced,
- `scrapedAt` marks normalization time,
- `RUN_SUMMARY` provides run-level diagnostics and billing context.

### Apify API example

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

const client = new ApifyClient({
  token: process.env.APIFY_TOKEN,
});

const actorId = "khadinakbar/tiktok-video-scraper";

const input = {
  videoUrls: ["https://www.tiktok.com/@stoolpresidente/video/7324105620095765765"],
  profileHandles: ["stoolpresidente"],
  getTranscript: true,
  providerOrder: "scrapecreators-first",
  maxVideosPerProfile: 5,
  maxPagesPerProfile: 1,
  region: "US",
};

const run = await client.actor(actorId).call(input);

const datasetId = run.defaultDatasetId;
const { items } = await client.dataset(datasetId).listItems({ clean: true, limit: 100 });

console.log("Run ID:", run.id);
console.log("Rows:", items.length);
console.log(items);
```

### Best results and outcome guidance

Use direct video URLs when the target video is already known. Use `profileHandles` when you want recent or popular videos from a creator feed. Set `sortBy` to `latest` for recency or `popular` when the provider supports popularity ordering. Use `getTranscript` for direct URL rows when transcript text helps with analysis or agent reasoning. Keep `trim` enabled for faster, smaller payloads, and enable `includeRawData` only when you need original provider payloads for debugging or field inspection.

For media work, `playUrl`, `downloadUrl`, and `noWatermarkUrl` are signed URLs and can expire. Permanent provider-hosted media URLs are returned only when `downloadMedia` is enabled and the provider returns them. `region` is an alpha-2 code used to localize provider requests.

### Design note

I found that the live dataset contract returns one normalized video record per dataset item, and that the required fields are `recordType`, `sourceType`, `provider`, `resultPosition`, `page`, and `scrapedAt`. That shape makes the output easy to read in tables and easy for agents to process row by row.

### Related Actors

- [TikTok Search Scraper - \[Videos, Hashtags & Users\]](https://apify.com/khadinakbar/tiktok-search-scraper) - Use this for discovery by query, hashtag, or user search before sending verified video URLs into this Actor.
- [TikTok Trending Videos Scraper](https://apify.com/khadinakbar/tiktok-trending-videos-scraper) - Use this for trending discovery, then pass selected video URLs or creator references into this Actor for detail enrichment.

### FAQ

#### When should I use videoUrls versus profileHandles?

Use `videoUrls` when you already have the exact TikTok video page. Use `profileHandles` when you want a creator's feed, recent videos, or popular videos from a public profile.

#### Which provider order should I choose?

The default `scrapecreators-first` order is the standard path in the live contract. You can switch to `sociavault-first`, `scrapecreators-only`, or `sociavault-only` when you want a specific provider path.

#### How are direct video URLs different from profile feeds?

Direct video URLs return one row per requested video. Profile feeds return multiple rows, one for each saved video from the creator profile, controlled by `maxVideosPerProfile` and `maxPagesPerProfile`.

#### What output should AI agents use first?

Agents usually start with `videoUrl`, `caption`, `authorUsername`, `playCount`, `likeCount`, `commentCount`, `shareCount`, `musicTitle`, and `transcript` when transcript text is enabled.

#### Where is run-level billing and provider information stored?

The output schema points to `RUN_SUMMARY` in the key-value store. The live contract describes that summary as holding provider usage, counts, cost estimate, and stop reason.

### Responsible use

Use this Actor for public TikTok data returned by the configured providers and for workflows that respect applicable laws, platform terms, privacy obligations, and content rights. Review the returned fields before republishing media or using the output in regulated or rights-sensitive workflows.

# Actor input Schema

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

Use this when you already have one or more TikTok video URLs to inspect. Accepts full URLs such as https://www.tiktok.com/@stoolpresidente/video/7324105620095765765. Defaults to an empty list. Not for TikTok profile URLs; put creator handles in Profile Handles.

## `profileHandles` (type: `array`):

Use this when you want recent or popular videos from TikTok creators. Accepts handles like stoolpresidente, @stoolpresidente, or profile URLs. Defaults to an empty list. Not for keyword search; use the TikTok Search Scraper for search queries.

## `providerOrder` (type: `string`):

Use this to choose which public-data provider is tried first. ScrapeCreators is the recommended primary and SociaVault is the fallback. Defaults to ScrapeCreators first. Not a browser scraping mode and does not use TikTok cookies.

## `maxVideosPerProfile` (type: `integer`):

Use this to cap how many videos are saved from each creator profile. Accepts integers from 1 to 10000. Defaults to 50. Does not limit direct Video URLs, which are processed one by one.

## `maxPagesPerProfile` (type: `integer`):

Use this as a safety cap for provider pagination on creator feeds. Accepts integers from 1 to 500. Defaults to 10. Not used for direct Video URLs.

## `maxTotalVideos` (type: `integer`):

Use this to cap the whole run across direct URLs and profile feeds. Accepts integers from 1 to 50000. Defaults to 10000. This is a billing and safety guard, not a request for more provider pages by itself.

## `sortBy` (type: `string`):

Use this to sort creator profile videos when the provider supports it. Accepted values are latest and popular. Defaults to latest. Not used for direct Video URLs.

## `region` (type: `string`):

Use this to localize provider requests with an alpha-2 country code. Example: US, GB, FR, or PH. Defaults to US. This is not a language filter and does not translate captions.

## `getTranscript` (type: `boolean`):

Use this when direct video URL rows should include TikTok transcript text where available. The transcript is usually WEBVTT. Defaults to false to keep runs cheaper and faster. Not applied to profile-feed pagination.

## `downloadMedia` (type: `boolean`):

Use this only when you need provider-hosted permanent media URLs from direct video URL requests. ScrapeCreators may charge extra provider credits for this path and this actor charges a media-downloaded event when media is returned. Defaults to false. Not needed for normal direct signed TikTok play URLs.

## `trim` (type: `boolean`):

Use this to request smaller provider payloads when supported. The normalized dataset fields stay the same. Defaults to true for speed and lower memory use. Turn off only when debugging with Include Raw Provider Data.

## `includeRawData` (type: `boolean`):

Use this when you need the original provider response attached to each dataset row. It is useful for debugging field drift or custom parsing. Defaults to false. Not recommended for AI-agent runs because raw payloads are large.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.tiktok.com/@stoolpresidente/video/7324105620095765765"
  ],
  "profileHandles": [
    "stoolpresidente"
  ],
  "providerOrder": "scrapecreators-first",
  "maxVideosPerProfile": 5,
  "maxPagesPerProfile": 1,
  "maxTotalVideos": 100,
  "sortBy": "latest",
  "region": "US",
  "getTranscript": false,
  "downloadMedia": false,
  "trim": true,
  "includeRawData": false
}
```

# Actor output Schema

## `results` (type: `string`):

Normalized TikTok video records with captions, metrics, media URLs, music, author, transcript, and source metadata.

## `runSummary` (type: `string`):

Run-level summary with provider diagnostics, counts, billing counters, and stop reason.

# 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/@stoolpresidente/video/7324105620095765765"
    ],
    "profileHandles": [
        "stoolpresidente"
    ],
    "maxVideosPerProfile": 5,
    "maxPagesPerProfile": 1,
    "maxTotalVideos": 100,
    "region": "US"
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/tiktok-video-scraper").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/@stoolpresidente/video/7324105620095765765"],
    "profileHandles": ["stoolpresidente"],
    "maxVideosPerProfile": 5,
    "maxPagesPerProfile": 1,
    "maxTotalVideos": 100,
    "region": "US",
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/tiktok-video-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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/@stoolpresidente/video/7324105620095765765"
  ],
  "profileHandles": [
    "stoolpresidente"
  ],
  "maxVideosPerProfile": 5,
  "maxPagesPerProfile": 1,
  "maxTotalVideos": 100,
  "region": "US"
}' |
apify call khadinakbar/tiktok-video-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=khadinakbar/tiktok-video-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/x7Kmg4VQllhVcSndG/builds/gwc7PSZdd7UMpSJ3D/openapi.json
