# TikTok Posts Scraper (`scraper-engine/tiktok-posts-scraper`) Actor

TikTok Posts Scraper extracts public post data including captions, creators, hashtags, views, likes, comments, shares, upload dates, and video URLs. Build structured datasets for content research, trend analysis, influencer discovery, and competitor monitoring.

- **URL**: https://apify.com/scraper-engine/tiktok-posts-scraper.md
- **Developed by:** [Scraper Engine](https://apify.com/scraper-engine) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.99 / 1,000 results

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?

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 Posts Scraper — Video Stats, Captions and Engagement Data

TikTok Posts Scraper extracts video posts, captions, engagement stats and creator profile data from TikTok profiles, hashtags, keyword searches, or pasted TikTok URLs (profile, video, hashtag, search, or music links). Every post comes back as structured JSON — likes, plays, comments, shares, saves, author details, video metadata, hashtags and music info — with no HTML parsing or manual API signing required. Start a run and watch posts land in your dataset in real time, one at a time.

### What is TikTok Posts Scraper?

TikTok Posts Scraper is an Apify Actor that drives a real Chromium browser to load TikTok's own public pages, capture the JSON TikTok's front-end already fetches, and normalize it into a consistent output schema. It supports four input modes — profile usernames, a hashtag, a keyword search, or a list of pasted TikTok URLs — and can mix URL types freely in one run. No TikTok account or login is required: every page is loaded the same way a logged-out visitor would see it. It's built for growth marketers, social media analysts, and developers or AI engineers who need TikTok post data as clean JSON rather than scraped HTML.

### What TikTok post data is publicly available to scrape?

Captions, engagement counts, video files, hashtags, attached music, and a post's public author profile are all visible on tiktok.com without logging in.

| Data Category | Publicly Available | Restricted behind |
| --- | --- | --- |
| Post caption, ID and timestamp | Yes | — |
| Engagement counts (likes, plays, comments, shares, saves) | Yes | — |
| Video file and cover images | Yes | — |
| Hashtags attached to the post | Yes | — |
| Attached music/sound details | Yes | — |
| Public author profile (username, nickname, bio, verified badge, follower/following/heart counts) | Yes | — |
| Posts from a private account | — | Login as an approved follower |
| Full follower/following lists, DMs, saved collections | — | Login |
| Creator Studio analytics (audience demographics, watch time, revenue) | — | Account owner's own login |

TikTok Posts Scraper only returns publicly visible data — what any visitor sees. Nothing behind a login wall.

### What data can I extract with TikTok Posts Scraper?

TikTok Posts Scraper returns every post as one JSON object covering the post's content, its engagement metrics, and its author and media details — 20 top-level fields in total.

| Field Name | Description |
| --- | --- |
| `id` | Unique TikTok post/video ID |
| `text` | The post's caption text |
| `createTime` | Unix timestamp the post was published |
| `createTimeISO` | Same timestamp in ISO-8601 format |
| `webVideoUrl` | Canonical `https://www.tiktok.com/@handle/video/id` link |
| `hashtags` | Array of `{id, name, title}` objects for every hashtag on the post |
| `musicMeta` | Object with the sound's id, title, authorName, original flag, album, duration, playUrl, coverThumb |
| `isAd` | `true` when TikTok flags the post as sponsored/ad content |
| `scrapeSection` | Which run mode produced this record — profile, hashtag, search, music, or video |
| `sourceLabel` | The handle, hashtag, keyword, or URL this record was collected under |
| `scrapedAt` | ISO-8601 timestamp of when the Actor saved this record |
| `diggCount` | Number of likes |
| `shareCount` | Number of shares |
| `playCount` | Number of plays/views |
| `commentCount` | Number of comments |
| `collectCount` | Number of saves |
| `authorMeta` | Object with the creator's id, uniqueId, nickname, avatar, signature, verified, secUid, privateAccount, followerCount, followingCount, heartCount, videoCount, friendCount |
| `videoMeta` | Object with height, width, duration, ratio, format, definition, playAddr, downloadAddr |
| `covers` | Object with cover, originCover, dynamicCover thumbnail URLs |
| `mediaUrls` | Array of the post's downloadable/playable video URLs |

#### Post and content fields

`id`, `text`, `createTime`, `createTimeISO`, `webVideoUrl`, `hashtags`, `musicMeta`, `isAd`, `scrapeSection`, `sourceLabel`, `scrapedAt` — everything that identifies and describes the post itself.

#### Engagement metrics

`diggCount`, `shareCount`, `playCount`, `commentCount`, `collectCount` — the numeric performance counters TikTok shows on every post.

#### Author and media fields

`authorMeta`, `videoMeta`, `covers`, `mediaUrls` — the creator's public profile, the video file's technical details, cover thumbnails, and direct media links.

#### 🤖 Add-on: Need additional TikTok data?

Need results narrowed to just a keyword search, without touching profile or hashtag mode? [TikTok Keyword Search Scraper](https://apify.com) is a dedicated keyword-search variant of this same engine. Need spoken content, not just captions? [Best TikTok AI Transcript Extractor](https://apify.com) transcribes a TikTok video's audio into text. Both are built by Scraper Engine and slot into the same JSON-in, JSON-out workflow.

### Why not build this yourself?

TikTok's web API (`/api/post/item_list`, `/api/challenge/item_list`, `/api/search/item/full`, `/api/music/item_list`, `/api/item/detail`) requires request-signing headers that TikTok's own obfuscated front-end JavaScript computes per request from a live browser fingerprint, plus a session cookie minted the same way — there is no static formula to replay from a plain HTTP client. A DIY scraper has to drive a real browser instead, spoof a believable fingerprint, handle TikTok's soft bot-checks on first load, trigger and follow the site's own infinite-scroll cursor to paginate, and maintain a proxy escalation path (direct, then datacenter, then residential) as blocking pressure increases — all of which breaks again the next time TikTok changes its front-end. TikTok Posts Scraper already does all of this and hands you typed JSON instead.

### How to use TikTok Posts Scraper

TikTok Posts Scraper runs on the Apify platform — no separate signup or API key beyond your Apify account is needed to start a run from the Console.

1. Open TikTok Posts Scraper in Apify Console (or the Apify Store) and click **Start**.
2. Provide input: paste one or more TikTok URLs into **Start URLs**, or leave it empty and pick a **Scrape Mode** — `profiles`, `hashtag`, or `keyword` — then fill in the matching field (`profiles`, `hashtag`, or `keyword`).
3. Set optional filters worth tuning: `sortBy`, `datePosted` (keyword mode only), `maxResultsPerProfile` / `maxResults`, and `region`.
4. Click **Start** to launch the run.
5. Watch posts land in the dataset in real time as they're scraped, then download the results as JSON or CSV, or open one of the section-specific dataset views (overview / profiles / hashtag / search / music / video).

#### How to scale to bulk post extraction

`profiles` accepts an array of usernames scraped as separate targets — up to `concurrency` of them run in parallel browser tabs at once (default 2, max 5). `startUrls` accepts a mixed list of profile, video, hashtag, search, and music URLs in one run, pasted directly, uploaded as a file, or linked to a hosted `.txt` file (one URL per line) for bulk input.

### What can you do with TikTok post data?

- 📈 A growth marketer tracking a brand hashtag uses `diggCount` and `playCount` to identify which videos are outperforming the rest before a weekly report.
- 🎯 An influencer-marketing agent vetting creators uses `authorMeta.followerCount` and `authorMeta.verified` to shortlist accounts before outreach.
- 🎵 A trend researcher monitoring a niche keyword uses `hashtags` and `musicMeta` to spot which sounds and tags are driving reach right now.
- 🧩 An analyst benchmarking competitors uses `sourceLabel` and `scrapeSection` to compare engagement across multiple profiles collected in a single run.
- 🤖 An AI engineer building a RAG pipeline over TikTok trend data feeds `text` (captions) and the engagement fields into a vector store, letting an agent answer "what's trending in this niche right now" from live post data.

### How does TikTok Posts Scraper handle rate limits and blocking?

Every run starts on a direct (no-proxy) connection with a real, generated browser fingerprint (screen, navigator, WebGL, canvas, fonts) injected via browserforge — the same fingerprinting library Crawlee's own PlaywrightCrawler uses by default. If TikTok keeps rejecting a target after its normal page-load retry budget (`maxMountRetries`), the Actor escalates itself one step at a time — direct → datacenter proxy → residential proxy — retrying up to 3 times on a fresh residential session before giving up on that one target, and every escalation is logged. If a user configures their own proxy, that choice is honored as-is with no automatic override. When a target still can't be scraped after escalation, it's skipped and logged with the reason while the rest of the run continues; after 4 consecutive fully-unreachable targets, the run logs one clear diagnosis and stops queuing further targets, keeping everything already collected.

### ⬇️ Input

TikTok Posts Scraper takes no required fields — provide at least one of Start URLs, Profiles, Hashtag, or Keyword for a productive run.

| Parameter | Required | Type | Description | Example Value |
| --- | --- | --- | --- | --- |
| `startUrls` | No | array | TikTok URLs (profile / video / hashtag / search / music), mixed freely. Overrides `scrapeMode` when filled in. | `["https://www.tiktok.com/@mrbeast"]` |
| `scrapeMode` | No | string | Used only when `startUrls` is empty. One of `profiles`, `hashtag`, `keyword`. Default `profiles`. | `"profiles"` |
| `profiles` | No | array | Usernames to scrape, without the `@`. Required when `scrapeMode` is `profiles`. | `["mrbeast"]` |
| `hashtag` | No | string | One hashtag to scrape, without the `#`. Required when `scrapeMode` is `hashtag`. | `"fyp"` |
| `keyword` | No | string | Keyword or phrase to search. Required when `scrapeMode` is `keyword`. | `"cooking recipes"` |
| `maxResultsPerProfile` | No | integer | Max posts to collect per profile (profiles mode only). Default `30`, min `1`, max `500000`. | `50` |
| `maxResults` | No | integer | Max total posts to collect (hashtag and keyword modes only). Default `50`, min `1`, max `100000`. | `50` |
| `sortBy` | No | string | Client-side sort. Profiles: `latest`, `popular`. Keyword search: `relevance`, `most-liked`, `date-posted`. Leave empty for TikTok's own order. | `"latest"` |
| `datePosted` | No | string | Keep only posts within this window (keyword mode only). One of `yesterday`, `this-week`, `this-month`, `last-3-months`, `last-6-months`, `all-time`. | `"this-month"` |
| `region` | No | string | 2-letter country code sent as a locale/Accept-Language hint. `minLength`/`maxLength` 2. | `"US"` |
| `proxyConfiguration` | No | object | Apify Proxy configuration. Default is no proxy — the Actor auto-escalates if TikTok blocks requests. | `{"useApifyProxy": false}` |
| `maxMountRetries` | No | integer | Page-load reload attempts before escalating the proxy. Default `5`, min `1`, max `20`. | `5` |
| `maxScrollRetries` | No | integer | Consecutive empty scrolls allowed before assuming no more results. Default `8`, min `1`, max `20`. | `8` |
| `maxScanned` | No | integer | Safety cap on raw posts scanned per target while paginating. Default `20000`, min `100`, max `200000`. | `20000` |
| `concurrency` | No | integer | Targets scraped in parallel browser tabs. Default `2`, min `1`, max `5`. | `2` |

#### Example input

```json
{
  "startUrls": [],
  "scrapeMode": "profiles",
  "profiles": ["mrbeast", "chefmarco"],
  "hashtag": "",
  "keyword": "",
  "maxResultsPerProfile": 50,
  "maxResults": 50,
  "sortBy": "latest",
  "datePosted": "",
  "region": "US",
  "proxyConfiguration": { "useApifyProxy": false },
  "maxMountRetries": 5,
  "maxScrollRetries": 8,
  "maxScanned": 20000,
  "concurrency": 2
}
```

### ⬆️ Output

Every post is pushed to the dataset the moment it's collected, as typed, normalized JSON with a consistent schema across runs. Results can be downloaded as JSON or exported as CSV, and browsed through per-section dataset views (overview, profiles, hashtag, search, music, video) that surface the columns most relevant to each mode. Every record includes `id` and `webVideoUrl`; every other field can be `null` when TikTok didn't return that piece of data for a given post.

#### Example output

```json
{
  "id": "7280231103294197022",
  "text": "we really cooked this up 🔥 #cooking #recipe",
  "createTime": 1725193182,
  "createTimeISO": "2024-09-01T12:19:42+00:00",
  "authorMeta": {
    "id": "6829267836608987141",
    "uniqueId": "chefmarco",
    "nickname": "Chef Marco",
    "avatar": "https://p16-sign-va.tiktokcdn.com/chefmarco-avatar.jpeg",
    "signature": "Home cook sharing 30-minute recipes",
    "verified": false,
    "secUid": "MS4wLjABAAAAxq3example",
    "privateAccount": false,
    "followerCount": 184300,
    "followingCount": 512,
    "heartCount": 2340000,
    "videoCount": 412,
    "friendCount": 12
  },
  "videoMeta": {
    "height": 1024,
    "width": 576,
    "duration": 38,
    "ratio": "720p",
    "format": "mp4",
    "definition": "540p",
    "playAddr": "https://v16-webapp.tiktok.com/chefmarco-play.mp4",
    "downloadAddr": "https://v16-webapp.tiktok.com/chefmarco-download.mp4"
  },
  "diggCount": 91700,
  "shareCount": 4210,
  "playCount": 680000,
  "commentCount": 2730,
  "collectCount": 4920,
  "webVideoUrl": "https://www.tiktok.com/@chefmarco/video/7280231103294197022",
  "mediaUrls": [
    "https://v16-webapp.tiktok.com/chefmarco-download.mp4",
    "https://v16-webapp.tiktok.com/chefmarco-play.mp4"
  ],
  "covers": {
    "cover": "https://p16-sign.tiktokcdn.com/chefmarco-cover.jpeg",
    "originCover": "https://p16-sign.tiktokcdn.com/chefmarco-origincover.jpeg",
    "dynamicCover": "https://p16-sign.tiktokcdn.com/chefmarco-dynamiccover.jpeg"
  },
  "hashtags": [
    { "id": "123456", "name": "cooking", "title": "cooking" },
    { "id": "654321", "name": "recipe", "title": "recipe" }
  ],
  "musicMeta": {
    "id": "7280100000000000000",
    "title": "original sound",
    "authorName": "chefmarco",
    "original": true,
    "album": null,
    "duration": 38,
    "playUrl": "https://sf16-ies-music.tiktokcdn.com/chefmarco-sound.mp3",
    "coverThumb": "https://p16-sign.tiktokcdn.com/chefmarco-musiccover.jpeg"
  },
  "isAd": false,
  "scrapeSection": "profile",
  "sourceLabel": "chefmarco",
  "scrapedAt": "2026-09-03T10:15:22.123456+00:00"
}
```

### How does it work?

TikTok Posts Scraper loads TikTok's own public pages in a real Chromium browser (Playwright) with a generated, believable browser fingerprint, rather than hand-crafting or replaying request-signing headers TikTok's front-end computes at runtime. It reads posts directly out of the JSON responses TikTok's own page code fires as it loads and as the page is scrolled — no header is ever forged. Every run starts on a direct connection and only escalates through a datacenter, then a residential, proxy tier if TikTok actually starts blocking requests. Pagination is driven by scrolling, the same trigger TikTok's own infinite-load code responds to, following the server-issued cursor page after page. Only what a logged-out visitor could already see is ever collected, and the output schema stays the same regardless of how TikTok's front-end layout changes underneath it.

### Integrations

TikTok Posts Scraper works like any other Apify Actor — with the Apify API, the Apify client libraries, and any workflow tool that can call an HTTP endpoint or an Apify SDK.

#### Calling TikTok Posts Scraper programmatically

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("your-username/tiktok-posts-scraper").call(
    run_input={
        "scrapeMode": "profiles",
        "profiles": ["mrbeast"],
        "maxResultsPerProfile": 50,
    }
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["text"], item["diggCount"])
```

Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request.

#### No-code tools (n8n, Make, LangChain)

In n8n, use the official Apify node (or an HTTP Request node pointed at the run-sync endpoint) to trigger a scrape and feed the dataset straight into your workflow. In Make.com, the Apify app's "Run Actor and Get Dataset Items" module does the same without writing code. In LangChain, the community `ApifyWrapper` can call this Actor by ID and map each dataset item into a `Document` for a RAG pipeline.

### Is it legal to scrape TikTok posts?

Scraping publicly accessible data is generally lawful in most jurisdictions — TikTok Posts Scraper only accesses pages any logged-out visitor can already see, the same captions, engagement counts, and creator profile info TikTok itself displays without a login. Because the output includes creator-identifying fields (`authorMeta`: username, nickname, avatar, bio) tied to identifiable public individuals, GDPR (in the EU) and CCPA (in California) govern how you store and use that personal data once collected — not the act of viewing it — so you're responsible for having a lawful basis, honoring deletion or opt-out requests, and not repurposing the data to profile private individuals. Consult legal counsel if your use case involves bulk storage of personal data.

### Frequently asked questions

#### What TikTok post fields does TikTok Posts Scraper return?

The top fields are `id`, `text`, `diggCount`, `playCount`, and `authorMeta`, alongside 15 more covering timestamps, video metadata, hashtags, music, and shares/comments/saves. See [What data can I extract](#what-data-can-i-extract-with-tiktok-posts-scraper) above for the full table.

#### Does TikTok Posts Scraper require a TikTok account or login?

No. Every target is loaded as a public, logged-out page — no TikTok account, cookie, or session is configured or required to run a scrape.

#### How many posts can I extract in one run?

Up to `maxResultsPerProfile` (max `500000`) per profile in profiles mode, or up to `maxResults` (max `100000`) total in hashtag or keyword-search mode — both are configurable input limits, not fixed caps.

#### What happens if a profile is private, deleted, or has no posts?

The target's page never mounts a post grid, so after `maxMountRetries` reload attempts the target is logged as failed and skipped — it returns zero records, while every other target in the run keeps going unaffected. If an account is public but has `privateAccount: true` set on a post's `authorMeta` from an earlier public post, that flag is still captured as returned by TikTok.

#### Can I scrape multiple TikTok profiles or hashtags at once?

Yes. `profiles` accepts an array of usernames scraped as separate targets, and `startUrls` accepts a mixed list of profile, hashtag, search, video, and music URLs in a single run — up to `concurrency` targets run in parallel browser tabs at once.

#### Does TikTok Posts Scraper work with Claude, ChatGPT, and other AI agent tools?

Yes, as an HTTP endpoint — any agent framework that can call the Apify API (start a run, read the resulting dataset) can use TikTok Posts Scraper as a tool, the same way it's called programmatically above.

#### What's the difference between using Start URLs and Scrape Mode?

`startUrls` takes priority: paste any mix of TikTok profile, video, hashtag, search, or music links and each is scraped as its own target, ignoring `scrapeMode` entirely. Leave `startUrls` empty to use `scrapeMode` instead, which scrapes by username(s), a single hashtag, or a single keyword search.

#### Does TikTok Posts Scraper return data in a format LLMs can use directly?

Yes. Every post is typed, normalized JSON with consistent field names across runs — no HTML parsing or CSS selectors involved. Pass it directly to an LLM, index it into a vector store, or feed it to an agent tool.

#### What happens when TikTok changes its layout or anti-bot system?

TikTok Posts Scraper is actively maintained, and the output schema is designed to stay stable across TikTok front-end changes — pagination and mount logic already include reload-based recovery for the soft bot-checks TikTok serves on a fresh page load. No specific turnaround time for future TikTok changes is published or promised.

#### Can I use TikTok Posts Scraper without managing proxies or browser infrastructure?

Yes. The Actor runs its own headless Chromium browser with a generated fingerprint and handles the direct-to-datacenter-to-residential proxy escalation automatically — you only need to configure a proxy yourself if you want to force a specific one from the start.

#### Which TikTok post fields work best for AI training data and RAG indexing?

For RAG, index `text` (the caption) alongside `hashtags` and `musicMeta` for topical and sound-trend context. For training data, `diggCount`, `playCount`, `commentCount`, `shareCount`, `collectCount`, and `createTime` are the most consistently structured numeric fields across every record, and all fields return as typed primitives or nested objects — never raw HTML.

### Related scrapers

| Scraper Name | What it extracts |
| --- | --- |
| TikTok Keyword Search Scraper | TikTok posts matching a search keyword, from the same engine |
| Best TikTok AI Transcript Extractor | Spoken-word transcripts from TikTok videos |
| Instagram Transcript API & Profile Scraper (AI Video to Text) | Instagram profile data and video transcripts |
| Twitter/X Profile Viewer | Public X (Twitter) profile data |

### Your feedback

Found a bug, or need a TikTok field this Actor doesn't return yet? Let us know at dev.scraperengine@gmail.com — we read every message and use it to prioritize fixes and new fields.

# Actor input Schema

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

Paste any TikTok URLs and get results immediately — profile, video, hashtag (#tag), search, or music links, mixed freely in one list. Paste directly, upload a file, or link to a hosted .txt file (one URL per line) for bulk input. When this is filled in, 'Scrape Mode' below is ignored.

## `scrapeMode` (type: `string`):

Used only when 'Start URLs' above is empty. Choose what kind of TikTok data to scrape.

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

Usernames to scrape (without the @). Required when Scrape Mode is 'profiles'.

## `hashtag` (type: `string`):

One hashtag to scrape posts from (without the #). Required when Scrape Mode is 'hashtag'.

## `keyword` (type: `string`):

Keyword or phrase to search TikTok for. Required when Scrape Mode is 'keyword'.

## `maxResultsPerProfile` (type: `integer`):

Maximum number of posts to collect per profile (profiles mode only).

## `maxResults` (type: `integer`):

Maximum total number of posts to collect (hashtag and keyword-search modes only).

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

Applied client-side after collection. Profiles mode: 'latest' or 'popular'. Keyword-search mode: 'relevance', 'most-liked', or 'date-posted'. Leave empty to keep TikTok's own order.

## `datePosted` (type: `string`):

Only keep posts published within this window (keyword-search mode only).

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

2-letter country code (e.g. US, GB, FR) — sent as a locale/Accept-Language hint. For a real change of exit IP geography, also pick a country inside 'Proxy configuration' below.

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

🟢 Default = no proxy (direct connection), which works for most runs. If TikTok starts rejecting requests, the Actor automatically escalates itself: Direct ➜ 🖥️ Datacenter proxy ➜ 🏠 Residential proxy (retried up to 3×), then stays on residential for the rest of the run. Every switch is logged. Override this only to force a specific proxy from the start.

## `maxMountRetries` (type: `integer`):

How many times to reload a page before treating it as blocked and escalating the proxy. Raise this if runs on a slow connection give up too early.

## `maxScrollRetries` (type: `integer`):

How many consecutive scrolls with no new posts to allow before assuming a target has no more results. Raise this if a run stops short of 'Max Results' on a profile/hashtag/search that clearly has more content.

## `maxScanned` (type: `integer`):

Safety cap on how many raw posts a single target may scan through while paginating, even if 'Max Results' hasn't been reached yet (protects against a runaway crawl).

## `concurrency` (type: `integer`):

How many targets (profiles/hashtags/searches/URLs) to scrape in parallel browser tabs. Keep this low — TikTok's anti-bot risk system is more likely to challenge a run that looks like a burst of parallel traffic.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.tiktok.com/@mrbeast"
  ],
  "scrapeMode": "profiles",
  "profiles": [
    "mrbeast"
  ],
  "hashtag": "fyp",
  "keyword": "cooking recipes",
  "maxResultsPerProfile": 30,
  "maxResults": 50,
  "region": "US",
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "maxMountRetries": 5,
  "maxScrollRetries": 8,
  "maxScanned": 20000,
  "concurrency": 2
}
```

# Actor output Schema

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

Every scraped post, from every section, in the order it was collected.

## `overview` (type: `string`):

Quick-glance columns across every section, with the section clearly labelled per row.

## `profiles` (type: `string`):

Results collected in 'profiles' mode.

## `hashtag` (type: `string`):

Results collected in 'hashtag' mode.

## `search` (type: `string`):

Results collected in 'keyword' (search) mode.

## `music` (type: `string`):

Results collected from a music/sound URL.

## `video` (type: `string`):

Results collected from a single pasted video URL.

## `csv` (type: `string`):

All results exported as CSV.

# 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": [
        "https://www.tiktok.com/@mrbeast"
    ],
    "profiles": [
        "mrbeast"
    ],
    "hashtag": "fyp",
    "keyword": "cooking recipes",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scraper-engine/tiktok-posts-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 = {
    "startUrls": ["https://www.tiktok.com/@mrbeast"],
    "profiles": ["mrbeast"],
    "hashtag": "fyp",
    "keyword": "cooking recipes",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("scraper-engine/tiktok-posts-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 '{
  "startUrls": [
    "https://www.tiktok.com/@mrbeast"
  ],
  "profiles": [
    "mrbeast"
  ],
  "hashtag": "fyp",
  "keyword": "cooking recipes",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call scraper-engine/tiktok-posts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scraper-engine/tiktok-posts-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/DIvekjyeDa9xG9VnO/builds/y8EZyOIBC9HZF2Qfz/openapi.json
