# TikTok Ad Transcripts & Hooks (Creative Center Top Ads) (`steadyfetch/tiktok-ads-transcript-scraper`) Actor

Charged only when a transcript is delivered — expired links and music-only ads are free rows. TikTok Creative Center Top Ads → transcript, first-3s hook, CTR and brand metadata. Paste ad links or material IDs (a fresh link is fetched for you) or chain any scraper. No start fee.

- **URL**: https://apify.com/steadyfetch/tiktok-ads-transcript-scraper.md
- **Developed by:** [Steadyfetch Team](https://apify.com/steadyfetch) (community)
- **Categories:** AI, Social media, Videos
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 ad video transcripts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

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 Ads Transcript Scraper — Creative Center Top Ads hooks & transcripts

Turn [TikTok Creative Center](https://ads.tiktok.com/business/creativecenter/inspiration/topads/pc/en) **Top Ads** into **structured transcripts** — full text, the **first-3-seconds hook**, and CTR/brand metadata in one JSON row per ad. Chain this TikTok ads transcript scraper straight after any Creative Center / Top Ads scraper run (dataset ID, pasted rows, or video URLs), or pass Top Ads material IDs and it fetches a fresh video link itself. **You are charged only when a transcript is delivered** — expired links, music-only creatives, and ads that dropped out of Top Ads carry no result fee.

| You give it | You get back |
|---|---|
| Ad video URLs (`videoUrl` / `videoUrl720p` / `video_url` from any Creative Center scraper) | `transcript` — full speech-to-text, any length |
| …or your scraper run's **dataset ID** (one-click chaining) | `hook3s` — what's said in the first 3 seconds |
| …or Top Ads **material IDs** / **ad page links** you copied browsing Creative Center (fresh links fetched for you) | `brandName`, `adTitle`, `ctr`, `cost`, `likes`, `industryKey`, `objectiveKey`, `materialId` |
| …or pasted dataset rows (any scraper's shape) | `language`, `durationSeconds`, timestamped `segments`, `urlExpiresAt` |

### Output

One JSON row per ad. Delivered rows carry the transcript and `charged: true`; anything that could not be delivered carries a `status` saying why, and `charged: false`. Real rows from the live example run below (long text trimmed with … for the page):

| status | charged | materialId | ctr | likes | hook3s | transcript | language | durationSeconds |
|---|---|---|---|---|---|---|---|---|
| `transcribed` | `true` | 7662608412568305665 | 0.97 | 1510 | Mystic Skill Enlightenment. Unlock new Mystic Skill Motive in the hands. | Mystic Skill Enlightenment. Unlock new Mystic Skill Motive in the hands. Ever seen someone kick a giant battle, and you're just standing there wondering… | English | 110.83 |
| `no_audio` | `false` | 7668529233501913089 | 0.9 | 0 | *null* | *null* | *null* | 14.72 |
| `transcribed` | `true` | 7662036896940326919 | 0.27 | 7520 | Hi, how are you? Good, how are you? Good, thank you. Just table for one? Yeah, absolutely. | Hi, how are you? Good, how are you? Good, thank you. Just table for one? Yeah, absolutely. Perfect. Just got off work. I'm so exhausted… | English | 175.74 |

The middle row is a music-only creative: it is delivered with its Top Ads metadata and **not charged**.

![TikTok ad transcripts output table — material ID, CTR, likes, first-3s hook, transcript and the charged flag](https://raw.githubusercontent.com/steadyfetch/n8n-templates/master/assets/tiktok-ads-transcript-scraper-output-table.png)

Full row, as JSON:

```json
{
  "status": "transcribed",
  "charged": true,
  "materialId": "7662340784365568017",
  "brandName": "",
  "adTitle": "Why Promote Stands Out Here is why Promote stands out! Target the audience based on your goals...",
  "ctr": 0.39,
  "cost": 0,
  "likes": 19,
  "industryKey": "label_20112000000",
  "objectiveKey": "campaign_objective_reach",
  "hook3s": "Looking for more ways to support your growth on TikTok?",
  "transcript": "Looking for more ways to support your growth on TikTok? Here's why Promote stands out. Promote is TikTok's in-app advertising tool to grow account performance...",
  "language": "English",
  "durationSeconds": 44.2,
  "urlExpiresAt": "2026-08-21T20:14:56.000Z",
  "segments": [{ "start": 0, "end": 2.96, "text": "Looking for more ways to support your growth on TikTok?" }],
  "chargeEvents": { "transcript": 1, "surchargeMinutes": 0 }
}
```

**[Browse the full live example dataset →](https://api.apify.com/v2/datasets/7qBRP5ezeRo5gbeDZ/items?clean=true\&format=json)** — real output from a verified run, including the free uncharged rows.

Every field is always present (explicit `null` over silent omission). Non-delivered rows carry `status` + `statusReason` instead — `unavailable_expired` (dead link, expiry time stated), `no_audio` (music-only or voice-less creative), `no_audio_stream` (the file has no audio track), `no_onscreen_text` (a silent ad with no readable on-screen copy either — see below), `no_creative_found` (no video link or material ID in the row, or the ad left Top Ads), `input_error` (guidance on what to pass instead), `asr_unavailable` (our speech service refused us mid-run — please re-run), or `failed_*` (also listed in the run's `ERRORS` record). None of them are charged.

### Silent ads: read the on-screen text instead (optional)

A good share of Top Ads carry no speech at all — music-only creatives and kinetic-typography ads whose whole message is **on the screen**. By default those ship as free `no_audio` / `no_audio_stream` rows and every run tells you how many it saw.

Turn on **Read on-screen text on silent video ads** (`includeOnScreenText`, off by default) and each silent ad's own keyframes are read instead:

```json
{
  "status": "onscreen_text_extracted",
  "charged": true,
  "materialId": "7668529233501913089",
  "onScreenText": {
    "headline": "Let AI build your Shopify loyalty program in minutes",
    "body": "No coding, no headaches. Just plug in and start rewarding.",
    "cta": "START FOR FREE",
    "rawText": "Let AI build your Shopify loyalty program in minutes\nNo coding, no headaches…"
  },
  "chargeEvents": { "transcript": 1, "surchargeMinutes": 0 }
}
```

- A delivered `onScreenText` row is charged **like a transcript** — same event, same price, never the long-video surcharge.
- Ads with no readable on-screen copy stay **uncharged** either way: b-roll whose only visible text is a logo or a placard comes back as `no_onscreen_text`, not as a charged row of noise.
- The frames come from the video this actor already downloaded, so nothing is fetched twice.
- `brandName` always comes from TikTok's own Top Ads metadata, never from reading a video frame.

### For AI agents & LLMs — copy this block

```
Actor:   steadyfetch/tiktok-ads-transcript-scraper  (Apify Store)
Does:    TikTok Creative Center Top Ads -> full transcript + first-3-seconds hook +
         CTR/brand metadata. One JSON row per ad. No TikTok login, cookies or API key.
Run:     POST https://api.apify.com/v2/acts/steadyfetch~tiktok-ads-transcript-scraper/run-sync-get-dataset-items?token=APIFY_TOKEN
Input    (any ONE of the first four fields is enough):
  {
    "materialIds": ["7662340784365568017"],   // Top Ads material ids; a fresh video link is fetched
    "videoUrls": ["https://ads.tiktok.com/business/creativecenter/topads/7662340784365568017"],
                                              // ad page links or *.tiktokcdn.com video links
    "datasetId": "<dataset id of any Creative Center / Top Ads scraper run>",
    "datasetItems": [ { /* pasted scraper rows, any shape */ } ],
    "includeOnScreenText": false,             // optional: read silent ads' on-screen text
    "maxAds": 1000                            // optional cap
  }
Output   one row per ad: status, charged, materialId, brandName, adTitle, ctr, cost,
         likes, industryKey, objectiveKey, hook3s, transcript, language,
         durationSeconds, urlExpiresAt, segments[]
         with includeOnScreenText: silent ads add onScreenText{headline,body,cta,rawText}
Pricing  pay per event, platform usage INCLUDED, no start fee:
  tiktok-ad-transcript   $0.020 -> $0.008 per delivered transcript (falls with your Apify plan tier)
                         also charges a delivered onScreenText row (includeOnScreenText)
  long-video-surcharge   $0.005 per started minute past the first 3 minutes
  Charged only on delivery — expired links, failures, and silent ads with no
  readable text cost $0.
  Cap any run with maxTotalChargeUsd (minimum $0.05).
MCP:     reachable through Apify's MCP server; ask for "TikTok ad transcripts".
```

### Why this TikTok ads transcript scraper?

- **Charged only on delivery.** A transcript either lands in your dataset or the row carries no result fee. Expired link → uncharged row that says so, with the exact expiry time. Music-only ad → uncharged row that says so. No start fee, no per-run fee.
- **Built for TikTok's 6-hour links.** Creative Center video links are signed and expire about **6 hours** after your scraper minted them (not the 24–48 hours some listings claim). This actor decodes the expiry *before* downloading, skips dead links at zero cost, and — if your rows carry the ad's material ID — fetches a **fresh link** from the Top Ads detail page and transcribes anyway. Old datasets become usable again.
- **Any video length.** Top Ads run 5 seconds to 5 minutes; all of it transcribes. Videos past 3 minutes add a small per-started-minute surcharge instead of failing or being cut.
- **Hook as data.** The first-3s hook is the line media buyers study; you get it as its own field, plus full segment timestamps for anything deeper.
- **Works with any scraper's output.** The input deep-scans your rows for the TikTok CDN video link and the ad metadata — no field mapping, no glue code.
- **Priced for bulk.** The first 3 minutes of every ad are included, and the per-transcript price falls with volume — see the pricing tab.

This actor may fail when the platform changes things — failed items are never charged.

### How to transcribe TikTok Top Ads (no code)

1. Run any TikTok Creative Center / Top Ads scraper (see *Works with* below) — pick your region, industry, and period as usual.
2. Open this actor and paste the scraper run's **dataset ID** into *Dataset ID* (or use Apify's *Connect Actor* integration so it chains automatically the moment the scraper finishes — the best way to beat the 6-hour link expiry).
3. Click **Start**. Each ad comes back as one JSON row: transcript + hook + CTR/brand metadata.
4. Export as JSON/CSV, or read it via API.

Prefer URLs? Paste the `videoUrl` / `videoUrl720p` / `video_url` values into **Ad video URLs**. Browsing [Creative Center](https://ads.tiktok.com/business/creativecenter/inspiration/topads/pc/en) and found an ad you want transcribed? Copy its page link (`ads.tiktok.com/business/creativecenter/topads/<id>`, with or without the trailing `/pc/en` and tracking parameters) and paste it into either field — same for material IDs. The actor fetches a fresh video link for each.

### Why do TikTok Creative Center video links expire?

TikTok's video CDN signs every link with an expiry timestamp — about **6 hours** from when the page (or your scraper) minted it. After that the link is dead. This actor handles it honestly:

- A link that is already expired is refused *before* any download — the row comes back as uncharged `unavailable_expired` with `urlExpiresAt` showing exactly when it died.
- If the same row carries the ad's **material ID** (most scrapers include it), the actor fetches a fresh link from the ad's public Top Ads detail page and transcribes anyway (best effort — if the ad has since dropped out of Top Ads, you get an uncharged `no_creative_found` row).
- If most of a run's links are expired, the run summary says so plainly and suggests the fix: re-run your scraper, or pass material IDs.

**Transcribe soon after scraping, or chain automatically** — *Connect Actor* on the scraper run hands this actor the dataset while every link is still fresh.

### How much does it cost to transcribe TikTok ads?

**One result = one ad's full transcript payload** (transcript + hook + metadata + segments). The first 3 minutes of each video are included; longer videos add a small per-started-minute surcharge. No start fee, no subscription, no third-party API key to buy.

| Job | Approx. cost |
|---|---|
| 50 Top Ads from one industry | ≈ $1.00 |
| 500 ads (a serious creative teardown) | ≈ $10 |
| Apify free plan ($5 credit) | ≈ **250 ad transcripts** |

Platform usage (compute + transfer) is **included in the event price** — the per-transcript price you see is the whole price. Expired, music-only, or dropped ads carry no result fee.

### Use it via API, MCP, and integrations

- **API**: standard Apify run API — `POST .../acts/steadyfetch~tiktok-ads-transcript-scraper/runs` with `{ "datasetId": "..." }` or `{ "materialIds": ["..."] }`. Python/Node clients work as with any actor.
- **MCP**: works from Claude, Cursor, and any MCP client through Apify's MCP server — ask for "TikTok ad transcripts" with a dataset ID, material IDs, or URLs.
- **n8n**: a free ready-made template, no community nodes needed — **[TikTok Top Ads transcripts →](https://github.com/steadyfetch/n8n-templates#tiktok-top-ads-transcripts--creative-center-industryregion--hooks--transcripts)** (Creative Center industry/region → hooks & transcripts → spreadsheet-shaped rows, 3-minute setup).
- **Make / Zapier**: call it as a regular Apify actor step right after your Creative Center scraper node — pass the scraper's default dataset ID.

### Works with — Creative Center scrapers you can chain from

This actor reads the **video link value** in each row (any `https://…tiktokcdn…/…` video link), not a fixed field name, so it works with any Creative Center scraper that exports direct video links — and it picks up the material ID for the fresh-link fallback. Verified output shapes on this store:

| Scraper | Where the video link lives | Material ID field |
|---|---|---|
| [azzouzana/tiktok-creative-center-top-ads-scraper](https://apify.com/azzouzana/tiktok-creative-center-top-ads-scraper) | `videoUrl720p` / `videoUrl540p` / `videoUrl360p` | `adId` (also `detailUrl`) |
| [doliz/tiktok-creative-center-scraper](https://apify.com/doliz/tiktok-creative-center-scraper) | `video_info.video_url.720p` | `id` |
| [datapeak/tiktok-creative-center](https://apify.com/datapeak/tiktok-creative-center) | `videoUrl` | `adId` (also `detailsUrl`) |
| [beyondops/tiktok-ad-library-scraper](https://apify.com/beyondops/tiktok-ad-library-scraper) | `videoUrlHd` / `videoUrl` | `adId` |
| [lexis-solutions/tiktok-top-ads-scraper](https://apify.com/lexis-solutions/tiktok-top-ads-scraper) | `videoUrls.720p` | `id` |
| [dltik/tiktok-creative-center](https://apify.com/dltik/tiktok-creative-center) | `video_url_720p` | `ad_id` (also `detail_url`) |

**How to chain:** run the scraper → copy the run's **dataset ID** into this actor's *Dataset ID* field, or use Apify's *Connect Actor* integration to pass it automatically → Start. Using a scraper that isn't listed? If its rows contain the TikTok CDN video link or the material ID, it works the same way — and if a row has neither, it comes back as an uncharged `no_creative_found`.

### FAQ

**What happens to expired links?** They are detected before any download and returned as uncharged `unavailable_expired` rows with the expiry time. If the row also has a material ID, the actor fetches a fresh link first and only reports expiry when that fails too.

**Music-only ads, or ads without a voice-over?** Speech-recognition models hallucinate filler on music. The actor detects that (in any language) and returns an honest, uncharged `no_audio` row instead of selling you a fake transcript. Expect a fair share of these on TikTok — many top ads are music plus on-screen text.

**Do I need TikTok cookies or an API key?** No. The actor only downloads public ad videos from TikTok's CDN and reads public Top Ads detail pages. No login, no cookies, no third-party ASR key.

**Can I paste the Creative Center *listing* page?** No — that page is a list of many ads, not a single ad. Run a Creative Center scraper over it first and chain the result here (or open one ad and paste its page link / material ID). A listing URL comes back as an uncharged `input_error` row with this guidance.

**Material IDs — what if I mistype one?** Material IDs are long numbers, so a typo can look like a valid ID. Those come back as uncharged `no_creative_found` rows ("no longer listed in Top Ads"), not as input errors — check the ID against your scraper's row if you see one unexpectedly.

**What happens on a failed download?** Up to 3 attempts, then an uncharged `failed_download` row plus an entry in the run's `ERRORS` record. You pay no result fee for anything that didn't deliver.

**Languages?** Whisper-class multilingual ASR — English, Spanish, Japanese, Arabic, Indonesian, and ~90 more transcribe out of the box; the detected `language` ships on every row.

**Why not scrape Top Ads here too?** Single-purpose by design: your scraper (whichever you like — region, industry, keyword filters included) finds the ads; this actor turns them into transcript data, reliably. One job, done honestly.

**Is this an official TikTok product?** No. This is an independent actor from steadyfetch — unofficial, and not affiliated with, endorsed by, or sponsored by ByteDance Ltd. or TikTok. "TikTok" and "TikTok Creative Center" are trademarks of their respective owners, used here only to name the public Top Ads surface this actor reads.

### Steadyfetch ad-intelligence suite

One actor per ad surface, one job each, the same contract everywhere: **all-inclusive pay-per-event,
no start fee, charged only on delivery** — and the same row shape, so a workflow built for one platform
ports to the next.

**Ad creatives → transcripts & on-creative text**

| Ad surface | Actor | Free n8n template |
|---|---|---|
| Facebook & Instagram Ad Library | [Facebook Ad Library Transcript Scraper — Video & Image Ad Text](https://apify.com/steadyfetch/facebook-ads-transcript-scraper) | [Facebook ad transcripts →](https://github.com/steadyfetch/n8n-templates#facebook-ad-transcripts--scrape-competitor-ads--hooks-ctas--transcripts) · [Competitor ad teardown →](https://github.com/steadyfetch/n8n-templates#competitor-ad-teardown--one-competitor-pagekeyword--hooks-ctas--transcripts-one-row-per-ad) |
| Google Ads Transparency Center | [Google Ads Video Transcripts & Hooks (Ads Transparency Center)](https://apify.com/steadyfetch/google-ads-video-transcript-scraper) | [Google Ads video transcripts →](https://github.com/steadyfetch/n8n-templates#google-ads-video-transcripts--one-advertiserdomain--hooks--transcripts) |
| **TikTok Creative Center Top Ads** | **this actor** | [TikTok Top Ads transcripts →](https://github.com/steadyfetch/n8n-templates#tiktok-top-ads-transcripts--creative-center-industryregion--hooks--transcripts) |
| LinkedIn Ad Library | [LinkedIn Ads Transcript Scraper — Video Hooks & CTAs](https://apify.com/steadyfetch/linkedin-ads-transcript-scraper) | [LinkedIn Ad Library transcripts →](https://github.com/steadyfetch/n8n-templates#linkedin-ad-library-transcripts--one-advertiser--hooks--transcripts) |
| Instagram Reels (organic posts) | [Instagram Reels to Text · @handle](https://apify.com/steadyfetch/instagram-reel-transcript-scraper) | [Instagram Reel transcripts →](https://github.com/steadyfetch/n8n-templates#instagram-reel-transcripts--scrape-a-profiles-reels--hooks--transcripts) |

**Ad creatives → text (image & text ads, read by OCR)**

| Ad surface | Actor |
|---|---|
| Google Ads Transparency Center | [Google Ads Creative Text & OCR (Transparency Center)](https://apify.com/steadyfetch/google-ads-creative-text-scraper) |

All templates in one place: **[github.com/steadyfetch/n8n-templates](https://github.com/steadyfetch/n8n-templates)** — free, no community nodes needed.

**The rest of the steadyfetch shelf** — same contract everywhere: all-inclusive pay per event,
no start fee, charged only on delivery.

| Family | Actors |
|---|---|
| **Ad creative intelligence** | [Facebook](https://apify.com/steadyfetch/facebook-ads-transcript-scraper) · [Google Ads video](https://apify.com/steadyfetch/google-ads-video-transcript-scraper) · [TikTok](https://apify.com/steadyfetch/tiktok-ads-transcript-scraper) · [LinkedIn](https://apify.com/steadyfetch/linkedin-ads-transcript-scraper) · [Google Ads text & OCR](https://apify.com/steadyfetch/google-ads-creative-text-scraper) |
| Trends & keywords | [Google Trends](https://apify.com/steadyfetch/google-trends-scraper) · [Trends Now](https://apify.com/steadyfetch/google-trends-now-scraper) · [Breakout keywords](https://apify.com/steadyfetch/breakout-keywords-scraper) · [Autocomplete keywords](https://apify.com/steadyfetch/google-keyword-suggest-scraper) · [Keyword volume & CPC](https://apify.com/steadyfetch/keyword-search-volume-scraper) · [Social trends](https://apify.com/steadyfetch/social-trends-scraper) |
| YouTube transcripts | [YouTube videos](https://apify.com/steadyfetch/youtube-transcript-scraper) · [YouTube channels](https://apify.com/steadyfetch/youtube-channel-transcripts) |
| Instagram | [Reel transcripts](https://apify.com/steadyfetch/instagram-reel-transcript-scraper) · [Profile posts](https://apify.com/steadyfetch/instagram-profile-posts) |
| Jobs | [Indeed](https://apify.com/steadyfetch/indeed-jobs-scraper) · [Career sites by domain](https://apify.com/steadyfetch/company-jobs-by-domain) · [Glassdoor](https://apify.com/steadyfetch/glassdoor-jobs-scraper) · [Multi-board](https://apify.com/steadyfetch/multi-job-board-scraper) · Google Jobs |
| Amazon | [Products](https://apify.com/steadyfetch/amazon-product-scraper) · [Search](https://apify.com/steadyfetch/amazon-search-scraper) · Bestsellers · Sellers |
| Any media file | [Speech to Text · any link or file](https://apify.com/steadyfetch/media-transcriber) |

Unlinked names are publishing shortly on the same account — search **steadyfetch** on Apify Store.

### Feedback & support

Found an issue? Open it on the **Issues tab** — we respond within one business day. Feature requests welcome.

# Actor input Schema

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

TikTok CDN video links (\*.tiktokcdn.com) — the videoUrl / videoUrl720p / video\_url field from any Creative Center scraper result. Ad page links copied while browsing Creative Center (ads.tiktok.com/business/creativecenter/topads/…) work here too — a fresh video link is fetched for each.

## `materialIds` (type: `array`):

Creative Center Top Ads material IDs (the long id in scraper results) or ad page links (ads.tiktok.com/business/creativecenter/topads/…). The actor fetches a fresh video link for each — useful when your scraped video URLs have already expired.

## `datasetId` (type: `string`):

The default dataset ID of a finished Creative Center scraper run. With Apify's 'Connect actor' integration this is filled automatically — the cleanest way to chain.

## `datasetItems` (type: `array`):

Paste rows from your Creative Center scraper run. The actor deep-scans each row for the ad video URL + metadata (brand, title, CTR, material ID) — works with any scraper's output shape. The prefilled demo row shows the honesty contract: it returns one uncharged row — replace it with your own rows, video URLs, or material IDs.

## `includeOnScreenText` (type: `boolean`):

OFF (default): an ad with no speech is never charged. ON: silent and music-only ads have their on-screen text read from the video's own frames and delivered as `onScreenText`, charged like a transcript (same event, same price — never the long-video surcharge). Ads with no readable on-screen text stay uncharged either way.

## `maxAds` (type: `integer`):

Safety cap on how many ads to transcribe in one run.

## Actor input object example

```json
{
  "datasetItems": [
    {
      "_demo": "Replace me with rows from your Creative Center scraper run (or use videoUrls / materialIds / datasetId). This demo row returns one uncharged row showing the per-row status contract.",
      "brand_name": "Demo Brand",
      "ad_title": "Demo Top Ad — replace me with rows from your Creative Center scraper run",
      "ctr": 0.05,
      "cost": 2,
      "industry_key": "label_demo",
      "objective_key": "3"
    }
  ],
  "includeOnScreenText": false,
  "maxAds": 1000
}
```

# Actor output Schema

## `transcripts` (type: `string`):

One row per ad: transcript, first-3s hook, brand, CTR, duration, and a status (transcribed / no\_audio / unavailable\_expired / no\_creative\_found / …). Only 'transcribed' rows are charged.

## `summary` (type: `string`):

Delivered count, uncharged misses, failures, and the honest status message.

## `errors` (type: `string`):

Present only when downloads/ASR failed after all retries: video URL, material ID, and 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 = {
    "datasetItems": [
        {
            "_demo": "Replace me with rows from your Creative Center scraper run (or use videoUrls / materialIds / datasetId). This demo row returns one uncharged row showing the per-row status contract.",
            "brand_name": "Demo Brand",
            "ad_title": "Demo Top Ad — replace me with rows from your Creative Center scraper run",
            "ctr": 0.05,
            "cost": 2,
            "industry_key": "label_demo",
            "objective_key": "3"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyfetch/tiktok-ads-transcript-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 = { "datasetItems": [{
            "_demo": "Replace me with rows from your Creative Center scraper run (or use videoUrls / materialIds / datasetId). This demo row returns one uncharged row showing the per-row status contract.",
            "brand_name": "Demo Brand",
            "ad_title": "Demo Top Ad — replace me with rows from your Creative Center scraper run",
            "ctr": 0.05,
            "cost": 2,
            "industry_key": "label_demo",
            "objective_key": "3",
        }] }

# Run the Actor and wait for it to finish
run = client.actor("steadyfetch/tiktok-ads-transcript-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 '{
  "datasetItems": [
    {
      "_demo": "Replace me with rows from your Creative Center scraper run (or use videoUrls / materialIds / datasetId). This demo row returns one uncharged row showing the per-row status contract.",
      "brand_name": "Demo Brand",
      "ad_title": "Demo Top Ad — replace me with rows from your Creative Center scraper run",
      "ctr": 0.05,
      "cost": 2,
      "industry_key": "label_demo",
      "objective_key": "3"
    }
  ]
}' |
apify call steadyfetch/tiktok-ads-transcript-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyfetch/tiktok-ads-transcript-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/ghETiEZzba3fTxPXr/builds/cE2f4ZHnf7nS0BC88/openapi.json
