# TikTok Profile & Video Scraper (`arabiainsights/tiktok-profile-video-scraper`) Actor

Scrape public TikTok profiles and video URLs for video statistics, author details, music and available media metadata. Export data for research and reporting.

- **URL**: https://apify.com/arabiainsights/tiktok-profile-video-scraper.md
- **Developed by:** [Arabia Insights](https://apify.com/arabiainsights) (community)
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 delivered videos

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 video scraper for public profiles and posts

Scrape TikTok profiles and individual video URLs into structured records for creator research, content reporting, and TikTok video statistics. Combine profiles and posts, filter by publication date, and prepare a bulk TikTok data export. Duplicate video IDs are delivered once per run.

#### Get your first result

1. Enter a public username or profile URL in **Profiles**, or post links in **Videos**.
2. Start with a small result limit and the default country setting.
3. Open **Results** and check **Run summary** for failures or partial collection before exporting.

```json
{ "profiles": ["tiktok"], "maxVideosPerProfile": 10 }
```

### What this Actor does

Collect available descriptions, publication dates, video dimensions and duration, engagement counts, author profiles, hashtags, mentions, and music information. When supplied by TikTok, records can include slideshow images, subtitle tracks, audio links, effects, and detailed mentions. The Actor does not transcribe audio or generate subtitles. Use the results to compare posts, track engagement over time, and identify mentioned creators. Counts reflect collection time and can change later.

### Input

| Setting               | Purpose                                                                                                                                           |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `profiles`            | Up to 100 usernames, @handles, or public profile URLs.                                                                                            |
| `videos`              | Up to 1,000 canonical video URLs, vt.tiktok.com or vm.tiktok.com share links, tiktok.com/t/ links, or supported /v/ links.                        |
| `maxVideosPerProfile` | 1–500 results per profile after filtering; default 100.                                                                                           |
| `excludePinnedPosts`  | Excludes pinned posts from profile listings. Directly requested pinned videos remain eligible; date filters still apply.                          |
| `profileSorting`      | `latest` uses the available listing order; pinned posts may affect chronology. `oldest` scans available posts and returns the oldest found first. |
| `fromDate`, `toDate`  | Inclusive UTC dates in YYYY-MM-DD form. Unknown publication dates are excluded when filtering.                                                    |
| `proxyCountry`        | Access country, default US. Availability varies by country.                                                                                       |
| `locale`              | Preferred locale, such as en-US.                                                                                                                  |
| `maxConcurrency`      | Simultaneous tasks, 1–5; default 2.                                                                                                               |
| `proxyConfiguration`  | Apify Residential Proxy only. Custom proxies and other groups are rejected. A selected country must match `proxyCountry`.                         |

Provide at least one profile or video. Both lists can be combined. Unsupported options are rejected; remove them and use the current form. No login or cookies are accepted.

### Output

One row represents one unique video. This shortened, invented example shows common fields; Details and JSON export include all retained fields:

```json
{
    "videoId": "7400000000000000001",
    "videoUrl": "https://www.tiktok.com/@example_creator/video/7400000000000000001",
    "description": "An example public post",
    "postedAt": "2026-08-01T12:30:00.000Z",
    "viewCount": 1200,
    "likeCount": 0,
    "commentCount": null,
    "pinned": false,
    "requestedUsername": "example_creator",
    "requestedProfileUrl": "https://www.tiktok.com/@example_creator",
    "scrapedAt": "2026-09-22T12:00:00.000Z"
}
```

| Fields                                                                                      | Meaning                                                                                                                    |
| ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `videoId`, `videoUrl`, `description`, `postedAt`                                            | Post identity, text and publication time; IDs are strings.                                                                 |
| `viewCount`, `likeCount`, `commentCount`, `shareCount`, `favoriteCount`                     | Available engagement counts. Unknown is null; observed zero remains zero.                                                  |
| `durationSeconds`, `width`, `height`                                                        | Available video duration and dimensions.                                                                                   |
| `author`                                                                                    | Username, display name, profile URL, avatar, bio, verification and public account counts.                                  |
| `hashtags`, `mentions`, `detailedMentions`                                                  | Hashtags and mentioned accounts.                                                                                           |
| `music`                                                                                     | Sound identity, title, artist, album, duration, cover, audio link and original-audio flag when available.                  |
| `pinned`, `isAd`, `isSlideshow`                                                             | Post flags. Unknown pinned/ad flags are null; slideshow is false when none is identified.                                  |
| `slideshowImageUrls`, `slideshowImageCount`                                                 | Up to 50 image links and the reported slide count.                                                                         |
| `subtitles`, `effectStickers`                                                               | Up to 20 caption tracks and effects. Caption `source: "ASR"` means automatic speech recognition; unknown origins are null. |
| `thumbnailUrl`, `dynamicThumbnailUrl`, `originCoverUrl`, `videoPlayUrl`, `videoDownloadUrl` | Available media links subject to expiry and access restrictions.                                                           |
| `requestedUsername`, `requestedProfileUrl`, `scrapedAt`                                     | Target correlation and collection time. Direct-video identity is resolved from the post.                                   |

#### Exports

Use JSON or the Dataset API to preserve nested objects and arrays. Apify also offers CSV and Excel exports for spreadsheet workflows; select fields and check how your spreadsheet handles nested values. Retain JSON alongside spreadsheets when you need the full nested record. Overview is compact; Details includes all public fields.

#### Contract migration

Version 1.0 removes top-level `source` and `author.secUid` from new results. Run summary schema version 2 removes `sourceCounts` and uses `AVAILABLE_LIST_ENDED`, `COLLECTION_STALLED` and `SCAN_LIMIT_REACHED` for corresponding collection outcomes. Update integrations using those fields or outcome names. Existing datasets are unchanged.

### Partial results and reason codes

**Run summary** reports delivered totals, skipped duplicates and filters, per-target outcomes, retries and failures. An interruption or spending limit is reported as a partial outcome when shutdown can complete. A successful platform run does not prove all posts were available. Check partial outcomes such as `LIST_TRUNCATED` or `SCAN_LIMIT_REACHED`. Private accounts, missing posts, country restrictions, login requirements, access challenges and rate limits can reduce results or stop collection.

### Pricing and limits

**$3 per 1,000 delivered videos ($0.003 per video), pay per event.** There is no Actor startup fee. Each unique video or slideshow post saved to Results counts once; duplicate inputs do not create another result fee. A run that delivers no videos has no result fee. Failed or interrupted runs still charge for videos already delivered.

**Apify platform usage is additional**, including compute, storage, transfer and Residential Proxy usage according to your account plan. Set a maximum run cost before starting. Run summary includes result-charge totals when available; Apify run usage details show the platform charges.

Oldest sorting may examine many posts before returning a small result set, increasing time and platform usage. Collection can stop short of the requested cap. A 500-result limit is a maximum, not a promise of 500 available posts. Resurrecting a run from this version preserves delivered video IDs and per-profile caps. A hard stop can leave a summary unfinished until the run resumes; check the platform run status and dataset too. Compare video IDs when combining separate runs.

### What this Actor does not do

This Actor is not an official TikTok API integration. It does not log in, does not solve CAPTCHAs, and does not download media into storage. Media URLs can expire or be session-bound and may fail outside the run. `videoDownloadUrl` does not guarantee a downloadable or watermark-free file.

### Scheduling, API, webhooks, and integrations

Save an Apify task to reuse inputs and attach a schedule for periodic collection. You can start runs through the Apify API and retrieve results using the run's dataset ID. Webhooks and integrations can trigger downstream processing. Keep API credentials private and check Run summary before treating a run as a successful refresh.

### Troubleshooting

#### Why did I receive fewer results?

Check date filters, pinned exclusion, duplicates and the per-target stop reason. Increasing the limit cannot make private, removed or restricted content accessible.

#### Why are fields null?

TikTok does not supply every field for every post. Missing information stays null rather than being reported as zero. Slideshow and subtitle metadata may be absent.

#### How do I get help?

Use the [Actor Issues page](https://apify.com/arabiainsights/tiktok-profile-video-scraper/issues). Include the run ID, sanitized input and expected result. Do not post tokens, cookies or signed media URLs.

### Privacy, compliance, and retention

Only request public data you are entitled to process. Consider [TikTok's terms](https://www.tiktok.com/legal/terms-of-service), its [privacy policy](https://www.tiktok.com/legal/privacy-policy), and applicable obligations for your use case. Results and operational records remain in your Apify account under its storage and retention settings.

# Actor input Schema

## `profiles` (type: `array`):

One to 100 TikTok usernames, @usernames, or supported public profile URLs. Provide this or 'Videos' (at least one is required).

## `videos` (type: `array`):

Up to 1,000 TikTok video URLs (canonical https://www.tiktok.com/@username/video/123, mobile share links https://vt.tiktok.com/..., https://vm.tiktok.com/..., or @username/video/123). Mixes freely with 'Profiles'; duplicates are skipped.

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

Maximum accepted Dataset items for each unique profile after filtering and deduplication.

## `excludePinnedPosts` (type: `boolean`):

Skip a profile's pinned posts. Applies to profile listings only; explicitly requested video URLs are always returned.

## `profileSorting` (type: `string`):

Latest returns TikTok's listing order, where pinned posts can appear first. Oldest scans the available listing and returns the oldest found posts first. Oldest can take longer and cost more even with a small result limit; unavailable posts may leave gaps.

## `fromDate` (type: `string`):

Inclusive UTC lower date bound.

## `toDate` (type: `string`):

Inclusive UTC upper date bound.

## `proxyCountry` (type: `string`):

ISO 3166-1 alpha-2 country for the residential proxy exit. TikTok serves some content only in certain countries: if a profile fails with CONTENT\_WITHHELD, re-run with the country where that content is available.

## `locale` (type: `string`):

Preferred language and regional formatting, such as en-US.

## `maxConcurrency` (type: `integer`):

Maximum simultaneous public profile tasks.

## `proxyConfiguration` (type: `object`):

Apify Residential Proxy is required. Custom proxies and other proxy groups are not supported. Any country selected here must match Residential proxy country above.

## Actor input object example

```json
{
  "maxVideosPerProfile": 100,
  "excludePinnedPosts": false,
  "profileSorting": "latest",
  "proxyCountry": "US",
  "locale": "en-US",
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `videos` (type: `string`):

Normalized public video metadata in the default Dataset overview.

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

Sanitized profile outcomes, counters, stop reasons, and fatal status.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("arabiainsights/tiktok-profile-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("arabiainsights/tiktok-profile-video-scraper").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 '{}' |
apify call arabiainsights/tiktok-profile-video-scraper --silent --output-dataset

```

## MCP server setup

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

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/7BRs8wIjhV67BIXcZ/builds/J7JunM81KkRtl30w6/openapi.json
