# Meta Ad Transcript Scraper - Video Ads to Text (`automation_craft/meta-ad-transcript-scraper`) Actor

Meta ad transcript scraper, no login: Facebook and Instagram video ads from the Meta Ad Library turned into text in bulk, inside the Actor. Rows carry the transcript, timed segments, language, hook and confidence beside the ad copy and call to action. CSV, API, schedules; pay per transcript.

- **URL**: https://apify.com/automation_craft/meta-ad-transcript-scraper.md
- **Developed by:** [Automation Craft](https://apify.com/automation_craft) (community)
- **Categories:** Social media, Marketing, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $19.00 / 1,000 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?

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

### Meta Ad Transcript Scraper - Video Ads to Text

**Turn Facebook and Instagram video ads from the Meta Ad Library into text in bulk**: search by keyword or advertiser, paste Ad Library links, video links or the dataset of any Ad Library run, and get every ad's spoken script as a transcript with timed segments, word timestamps, the language, the opening line and the second speech begins, next to the ad's copy, call to action, dates and platforms. The speech model (Whisper) runs inside the Actor: no outside AI service, no API key, no login. Videos without speech, repeats and failed reads are free rows that say why.

#### Why marketers use it

- **Competitor scripts as data.** Hooks, offers and calls to action of the video ads a brand runs right now, ready for a spreadsheet or your own AI model.
- **Every input you already have.** Search terms, advertiser names or page ids, single Ad Library links or ad ids, Ad Library search links with their filters, direct video URLs, the dataset of another Ad Library run, or pasted rows.
- **Honest billing.** A transcript is charged once per video: the same creative running under several ad ids is transcribed and charged once, a video with no speech is a free `no_speech` row, an expired link is read again from the Ad Library when the ad id is known.
- **Deeper rows.** Language with its probability, a confidence figure, speech seconds, words per minute, subtitles (SRT and WebVTT), optional English translation, on-screen text, scene cuts and the Ad Library's EU reach details.

### How to transcribe Meta video ads

1. Type one or more **Search terms** (for example `meal kit`) and pick the **Countries** (US by default), or paste **Advertisers**, **Ad Library links or ad ids**, **Meta video URLs**, or pick a **Dataset** of an Ad Library run.
2. Set **Transcripts per search** and **Transcripts per run** (3 and 3 in the form) to the size you want.
3. Click **Start**. Each video ad comes back as one row with its transcript; open the **Transcripts** view or export JSON, CSV or Excel.
4. To follow a competitor, save the input as a task with a **Memory name** and **New ads only**, and schedule it: each run transcribes and charges only the videos it has not delivered before.

Clicking Start with nothing set runs a sample: 3 video ads running in the US for "fitness app".

### What you get

One `transcript` row per video ad, plus free `status` rows (one per ad or video not transcribed, with the reason), one free `coverage` row per search, and a run `summary`. Fill rates measured on 54 transcript rows of 40 platform runs on 2026-10-13 (searches in the US and Spain, advertisers, ad links, video links, pasted rows, a chained dataset):

| Field | What it holds | Filled |
|---|---|---|
| `transcript` | the speech of the video as text | 54 of 54 |
| `segments` | the transcript in timed segments (`start`, `end`, `text`) | 54 of 54 |
| `words` | every word with its start, end and probability (with `wordTimestamps`) | when asked |
| `language`, `languageName`, `languageProbability` | the spoken language the model detected | 54 of 54 |
| `hook`, `hookSeconds`, `hookStartSeconds` | the words spoken in the first seconds after speech begins, and the second it begins | 54 of 54 |
| `confidence` | the model's own mean token probability, 0 to 1 | 54 of 54 |
| `speechSeconds`, `wordCount`, `wordsPerMinute` | seconds of voice found, words, pace | 54 of 54 |
| `videoDurationSeconds`, `transcriptSeconds`, `transcriptComplete` | the video's length, the audio transcribed, and whether all of it was | 54 of 54 |
| `adArchiveId`, `adLibraryUrl`, `pageName`, `adText` | the ad and its advertiser (empty only for a bare video link given without its ad) | 50 of 54 |
| `pageId`, `ctaText`, `ctaType` | the advertiser's page id and the call to action | 40 to 46 of 54 |
| `startDate`, `isActive`, `daysRunning` | the ad's dates | 40 to 46 of 54 |
| `publisherPlatforms`, `landingUrl`, `landingDomain` | where it runs and where it sends people | 38 to 40 of 54 |
| `targetedOrReachedCountries` | as the Ad Library's search answer gives it: an empty list on every row read (the reach per country of an ad shown in the EU comes with `adDetails`) | 0 of 54 |
| `videoId`, `videoUrl`, `videoUrlExpiresAt` | the creative's asset id and the file read (links expire after 1 to 4 days) | 52 to 54 of 54 |
| `subtitlesSrt`, `subtitlesVtt`, `translationEnglish`, `onScreenText`, `sceneCuts`, `cutsPerMinute`, `adDetails`, `mediaFileUrl`, `pageActiveAdCount`, `rawAd` | the options and add-ons below | when asked |
| `imageUrl`, `imageText`, `mediaFileUrl` | on `image_text` and `image_file` rows: the image ad's file, its text, the saved file | when asked |
| `status`, `paidEvents`, `message` | why a row is what it is, and the events it is charged for | every row |

Real row (shortened), from a search for "meal kit" in the US:

```json
{
  "type": "transcript",
  "status": "transcribed",
  "adArchiveId": "4309638865973296",
  "pageName": "Hungryroot",
  "ctaText": "See details",
  "language": "en",
  "languageProbability": 1,
  "hook": "It is 5.30 and I just got my very first",
  "hookStartSeconds": 9.81,
  "transcript": "It is 5.30 and I just got my very first delivery from Hungary route. It is perfect because guess what? ...",
  "transcriptSeconds": 102.22,
  "videoDurationSeconds": 102.33,
  "speechSeconds": 81.66,
  "wordCount": 315,
  "confidence": 0.81,
  "paidEvents": { "transcript": 1, "transcript-minute": 1 }
}
```

The example shows what a speech model does with a brand name it does not know ("Hungary route" for Hungryroot): names, prices and codes are worth a glance before you quote them. The video runs 102 seconds, so the row is one transcript and one transcript minute.

#### Row statuses

Paid rows (type `transcript`): `transcribed`, `transcribed_partial` (the compute cap stopped the read; the row says where), `screen_text` (a silent video's on-screen text), `image_text` (an image ad's text), `image_file` (an image ad's saved file).

Free status rows: `no_speech` (music, silence or text on screen), `no_audio_track`, `no_video` (an image or text ad), `same_video` (the same creative as another ad of the run, with its transcript in full), `already_delivered` (your memory holds it), `language_filtered`, `duration_filtered`, `ad_text_filtered`, `launch_filtered`, `advertiser_filtered`, `category_filtered`, `video_expired`, `video_gone`, `video_too_large`, `video_failed`, `ad_not_found`, `lookup_failed`, `advertiser_not_found`, `advertiser_ambiguous` (the candidates are listed), `image_text_empty`, `failed`, `skipped` (the run stopped first), `not_charged` (a correction: the row it names was delivered without part of its charge), `duplicate_input` (a value given twice), `memory_free` (the named memory could not be used, so every row the run delivers from then on is free), `memory_full` (the memory holds its maximum of keys, no new row is delivered under it), `invalid`.

### How much does it cost to transcribe Meta video ads?

Pay per event. A transcript includes the first 60 seconds of audio; a longer video adds one transcript minute per started minute after that. The add-ons are charged only when you switch them on, and only for what they deliver.

| Event | Free plan | Bronze | Silver | Gold |
|---|---|---|---|---|
| Transcript (one video, first 60 seconds included) | $0.024 | $0.024 | $0.022 | $0.019 |
| Transcript minute (each started minute after 60 seconds) | $0.015 | $0.015 | $0.014 | $0.012 |
| Translation minute (optional, each started minute translated) | $0.015 | $0.015 | $0.014 | $0.012 |
| Text frame (optional, one frame or image with new on-screen text) | $0.0064 | $0.0064 | $0.0058 | $0.005 |
| Ad details (optional, per ad) | $0.00128 | $0.00128 | $0.00116 | $0.001 |
| Media file (optional, per file saved) | $0.00256 | $0.00256 | $0.00232 | $0.002 |
| Actor start (per run, per GB of memory; 1 GB by default) | $0.024 | $0.024 | $0.024 | $0.024 |

Platinum and Diamond plans pay the Gold price. The Actor start has no plan discount.

The Store pricing card shows these prices per 1,000 events: "$19.00 / 1,000" on the Transcript row means one transcript costs 1.9 cents on the Gold plan, and "$12.00 / 1,000" on the Transcript minute row means one extra minute costs 1.2 cents.

Example on the Gold plan: 20 video ads of 35 seconds each cost 20 x $0.019 + $0.024 = $0.404; the same run with two 90 second ads among them adds 2 x $0.012. Videos without speech, the same creative under another ad id, videos your memory holds and failed reads cost nothing.

### Input

| Field | What it does |
|---|---|
| `searchTerms` | words to search the Ad Library for |
| `advertisers` | exact page names, page ids, Facebook page URLs or an advertiser's Ad Library page link |
| `adUrls` | Ad Library links with `?id=`, bare ad ids, or Ad Library search links (their filters apply) |
| `videoUrls` | direct video files on Meta's video CDN |
| `dataset`, `rows` | the dataset of an Ad Library run (picked in the form), or rows pasted as JSON |
| `countries`, `activeStatus`, `mediaType`, `adType`, `platforms`, `adLanguages`, `searchType`, `sort`, `dateFrom`, `dateTo`, `targetedCountryOnly` | the Ad Library's own filters (countries as two or three letter codes or names) |
| `launchedAfter`, `adTextContains`, `onePerAdvertiser`, `pageCategories`, `minDurationSeconds`, `maxDurationSeconds`, `spokenLanguages` | filters applied before any download (spoken languages: after detection), free |
| `maxAdsPerSearch`, `maxAds`, `videosPerAd`, `transcribeSeconds` | sizes and caps |
| `spokenLanguage`, `hookSeconds`, `wordTimestamps`, `subtitles`, `sceneCuts` | transcription options, free |
| `translateToEnglish`, `onScreenText`, `maxTextFrames`, `imageAdText`, `adDetails`, `saveMediaFiles`, `saveImageFiles` | add-ons, priced above |
| `advertiserActiveAds`, `includeRawData` | the advertiser's number of active ads, the Ad Library's own record of the ad, on each paid row and its free `same_video` copies (not on the other free status rows); free |
| `memoryName`, `newAdsOnly`, `resetMemory`, `runTag`, `advertiserSummary` | monitoring and labels |

A key sent as null or an empty text counts as left out, on every field except the seven pick lists (`activeStatus`, `mediaType`, `adType`, `searchType`, `sort`, `onScreenText`, `saveMediaFiles`): the platform checks those against their values before the run starts, so send one of the values or leave the key out. A value that cannot be used is listed by its position in a free row; a field whose values are all unusable stops the run before anything is read.

Each dataset or pasted row is read on its own: the filters check that row's own ad copy and start date. A row whose video link has expired is read again from the Ad Library by its ad id, and a row with only an ad id takes the ad's facts from there. Failed rows of an earlier run of this Actor (`video_expired`, `video_failed`, `lookup_failed`, `failed`, `skipped`) can be pasted back to try them again.

### What this Actor does not do

- It does not log in, and it reads only what the Meta Ad Library shows logged out.
- It does not call any outside AI service: no summaries, creative critiques or ad scores written by a language model. The transcript, the hook, the calls to action and the advertiser summary rows are yours to feed to the model you choose.
- It does not read other ad libraries (Google, TikTok, LinkedIn) or the advertiser's landing page; it delivers the landing link and domain.
- It does not transcribe videos without speech: they are free `no_speech` rows (their on-screen text can be read with `onScreenText`).
- Its speech model is Whisper base: on a test set of real ads the median word error was 8.6 percent in English and about 25 percent in other languages, and unknown brand names can be misheard. A video with only a few spoken words (under one second of voice) counts as no speech; a sung line can count as speech.
- It reads the SD file of each video (same audio as HD). Video links signed by Meta expire after 1 to 4 days; an expired link of an ad with a known id is read again, others are free `video_expired` rows.
- It does not keep transcripts in its memory: a video an earlier run delivered comes back as a free `already_delivered` row that names that run's dataset, not as a second transcript.

### FAQ

#### How do I bulk pull transcripts from Meta video ads?

Give the Actor search terms, advertisers or Ad Library links and set the number of transcripts per search; every video ad it finds comes back as one row with its transcript, segments and hook. A dataset of another Ad Library run can be picked as the input too.

#### Can I download the videos from the Facebook Ad Library?

Every row carries the video file link it read (`videoUrl`, valid for 1 to 4 days). With `saveMediaFiles` set to `video` or `audio` (and `saveImageFiles` for image ads), the Actor also stores the file in the run's key-value store and puts its link on the row (a Media file event per file).

#### Does it work for Instagram ads?

Yes. The Meta Ad Library holds the ads that run on Facebook, Instagram, Messenger, Audience Network, WhatsApp and Threads; filter them with `platforms`.

#### Which languages does it transcribe?

Every language the Whisper model reads (100 language codes); each row gives the detected language and its probability. Set `spokenLanguage` when you know it, `spokenLanguages` to keep only some, and `translateToEnglish` for an English version of the rest.

#### How do I get the transcript of one Facebook ad video?

Paste the ad's Ad Library link (with `?id=`) or its ad id into **Ad Library links or ad ids**, or the video file link into **Meta video URLs**, and click Start. The row carries the transcript, timed segments, the language and the opening line; a video without speech, a video your memory holds and a failed read are free rows with the reason.

#### Why does this Actor run with limited permissions?

It needs nothing else: it reads public pages and files, writes to its own run storage, and keeps an optional memory in a named key-value store it creates itself. It can read a dataset you pick in the dataset field, and no other storage of your account.

### Use it from code

```bash
curl -X POST "https://api.apify.com/v2/acts/automation_craft~meta-ad-transcript-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms": ["meal kit"], "countries": ["US"], "maxAdsPerSearch": 5, "maxAds": 5}'
```

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('automation_craft/meta-ad-transcript-scraper').call({ adUrls: ['https://www.facebook.com/ads/library/?id=4309638865973296'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((x) => x.type === 'transcript').map((x) => x.transcript));
```

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("automation_craft/meta-ad-transcript-scraper").call(run_input={"advertisers": ["HelloFresh"], "maxAds": 10})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item["type"] == "transcript":
        print(item["pageName"], item["hook"])
```

### Changelog

- 0.1 (2026-10-13): first release. Search, advertisers, ad links, video URLs, datasets and pasted rows; Whisper base inside the Actor; segments, words, hook, confidence, subtitles; translation, on-screen text, image text, scene cuts, ad details and media files as options; memory with new ads only and the "no longer shown" report.

### More data tools by Automation Craft

- [Meta Ads Library Scraper - Ad Library, All Filters](https://apify.com/automation_craft/meta-ads-library-scraper)
- [Facebook Ads Library Scraper - Ad Library & Spy](https://apify.com/automation_craft/facebook-ads-library-scraper)
- [Instagram Ads Library Scraper - Creatives, Video](https://apify.com/automation_craft/instagram-ads-library-scraper)
- [Meta Ad Spend Scraper: Advertiser Spend by Country](https://apify.com/automation_craft/meta-ad-spend-scraper)
- [TikTok Creative Center Scraper: Top Ads, No Login](https://apify.com/automation_craft/tiktok-creative-center-scraper)
- [Google Ads Transparency Scraper - Decoded Creatives](https://apify.com/automation_craft/google-ads-transparency-scraper)
- [TikTok Video Scraper: Post Stats, Transcripts](https://apify.com/automation_craft/tiktok-video-scraper)
- [Facebook Posts Scraper - Page Posts, No Login](https://apify.com/automation_craft/facebook-posts-scraper)

# Changelog

This Actor's version history is a separate document: https://apify.com/automation_craft/meta-ad-transcript-scraper/changelog.md

# Actor input Schema

## `searchTerms` (type: `array`):

Words to search the Meta Ad Library for, as its search box takes them (for example fitness app). Each search transcribes the video ads it finds, up to "Transcripts per search". Leave every target field empty to run a 3 ad sample.

## `advertisers` (type: `array`):

Advertisers whose video ads to transcribe: the exact page name as the Ad Library shows it (HelloFresh), the page id, the Facebook page URL or the advertiser's Ad Library page link (with view_all_page_id). A name is used only when exactly one page carries it; otherwise a free row lists the candidates.

## `adUrls` (type: `array`):

Single ads: an Ad Library link with ?id= (the ad's "Copy link") or the bare ad id. An Ad Library search link (with q= or view_all_page_id=) is read as a search with its own filters. An id the Ad Library does not have is a free row.

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

Direct video files on Meta's video CDN (video...fbcdn.net, the video_sd_url or video_hd_url of any Ad Library row). These links expire after 1 to 4 days; an expired one is a free row.

## `dataset` (type: `string`):

Pick the dataset of a finished run of any Ad Library scraper: up to 10,000 rows are read, each row's ad id and video links are used, and an ad whose links have expired is read again from the Ad Library by its id.

## `rows` (type: `array`):

Rows of an Ad Library run pasted as JSON (any scraper's shape): each row's ad id and every Meta video link in it are used. Up to 2,000 rows.

## `countries` (type: `array`):

Countries of the Ad Library to search: two letter codes (US, GB, DE ...), three letter codes (USA, GBR, DEU ...) or names in English, German, French, Spanish, Italian or Portuguese, or ALL. Each search and advertiser is read in every country listed. US when left empty.

## `activeStatus` (type: `string`):

Ads running now (active, the default when left out), ads that stopped, or both.

## `mediaType` (type: `string`):

Video ads (the default when left out). The other formats of the Ad Library give image and text ads, which are free rows unless "Read image ad text" is on.

## `adType` (type: `string`):

The Ad Library's ad category filter. All when left out.

## `platforms` (type: `array`):

Only ads shown on these platforms. Every platform when left empty.

## `adLanguages` (type: `array`):

Two letter codes of the languages of the ad copy the Ad Library filters by (en, es, de ...). Every language when left empty. To filter by the spoken language use "Spoken languages".

## `searchType` (type: `string`):

How the Ad Library matches the search terms. Any of the words when left out.

## `sort` (type: `string`):

The order the Ad Library returns ads in. Relevance when left out.

## `dateFrom` (type: `string`):

Only ads shown on or after this day: YYYY-MM-DD, today, yesterday or "7 days", "3 months".

## `dateTo` (type: `string`):

Only ads shown on or before this day, in the same forms as "Shown from".

## `launchedAfter` (type: `string`):

Only ads whose start date is on or after this day (YYYY-MM-DD or "30 days"); older ads are skipped free before any download.

## `targetedCountryOnly` (type: `boolean`):

Only ads targeted at the chosen country, not ads that merely reached it.

## `adTextContains` (type: `array`):

Only ads whose copy (text, headline, caption) contains one of these words or phrases, as whole words. Others are skipped free before any download.

## `onePerAdvertiser` (type: `boolean`):

Transcribe at most one ad of each advertiser in the run.

## `pageCategories` (type: `array`):

Transcribe only ads whose advertiser's page carries one of these categories, as the Ad Library names them (for example Health/beauty, Restaurant, Public figure); compared without letter case. An ad whose page category is not known is left out. Free.

## `maxAdsPerSearch` (type: `integer`):

How many ads each search, advertiser and country may deliver as transcripts (10 when left out). Ads without speech, already delivered or filtered out do not count.

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

The most transcripts this run delivers (20 when left out); a safety cap on the bill.

## `videosPerAd` (type: `integer`):

Ads with several creatives (dynamic and carousel ads) carry several videos: how many of them to transcribe, each its own row and transcript (1 when left out).

## `minDurationSeconds` (type: `integer`):

Skip videos shorter than this, free and before download.

## `maxDurationSeconds` (type: `integer`):

Skip videos longer than this, free and before download.

## `transcribeSeconds` (type: `integer`):

The most audio transcribed per video (600 when left out); a longer video is transcribed to this point and its row says where it was cut.

## `spokenLanguage` (type: `string`):

The language spoken in the videos as a two letter code (en, es, de ...) when you know it; it skips language detection and helps short ads. auto when left out.

## `spokenLanguages` (type: `array`):

Only transcribe videos whose detected spoken language is one of these codes (en, es ...); others are free rows, stopped after detection.

## `hookSeconds` (type: `integer`):

The opening line: the words spoken in the first N seconds after speech begins (3 when left out).

## `wordTimestamps` (type: `boolean`):

Add every word with its start and end time and its probability. Free.

## `subtitles` (type: `boolean`):

Add the transcript as SRT and WebVTT subtitle text. Free.

## `sceneCuts` (type: `boolean`):

Add the estimated times of the video's hard cuts and the cuts per minute. Free.

## `translateToEnglish` (type: `boolean`):

Add an English translation of the speech of non English videos (the speech model's own translation). Charged per started minute translated.

## `onScreenText` (type: `string`):

Read the text shown on screen from frames of the video (OCR inside the Actor): off (the default when left out), only for videos without speech, or for every video. Charged per frame with new text.

## `maxTextFrames` (type: `integer`):

The most frames read for on-screen text per video (6 when left out): the first frame after each scene cut, spread over the video.

## `imageAdText` (type: `boolean`):

For image ads (Ad format: all or image), read the text in the picture. Charged as one text frame per image with text.

## `adDetails` (type: `boolean`):

Add the Ad Library's detail record of each transcribed ad: advertiser facts and, for ads shown in the EU, the reach figures. Charged per ad.

## `saveMediaFiles` (type: `string`):

Save the audio track or the video of each transcribed ad to this run's key-value store, with its link on the row. Charged per file.

## `saveImageFiles` (type: `boolean`):

Save the image file of each image ad to this run's key-value store, with its link on the row (one Media file event per image). Image ads are read when the media type includes images.

## `advertiserActiveAds` (type: `boolean`):

Add the number of ads each transcribed ad's advertiser has active in the Ad Library (one extra page read per advertiser and country, kept for the run). Free; when the run's allowance of unpaid work is spent, the count is left empty with the reason.

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

Add the Ad Library's own record of the ad, as it answered, to each row (rawAd). Rows of video links or pasted rows without a fresh read carry none.

## `memoryName` (type: `string`):

A short name for a memory kept across runs (a watchlist): a video delivered under it is never transcribed or charged again; later runs return a free row for it, or skip it with "New ads only".

## `newAdsOnly` (type: `boolean`):

With a memory name: skip the videos the memory holds, without a row and without a download.

## `resetMemory` (type: `boolean`):

Forget everything the memory holds before this run.

## `runTag` (type: `string`):

A label copied onto every row of this run, for your own sorting.

## `advertiserSummary` (type: `boolean`):

Add one free row per advertiser at the end: transcripts, seconds, languages, calls to action and the hooks heard.

## Actor input object example

```json
{
  "searchTerms": [
    "fitness app"
  ],
  "countries": [
    "US"
  ],
  "maxAdsPerSearch": 3,
  "maxAds": 3
}
```

# Actor output Schema

## `items` (type: `string`):

No description

# 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 = {
    "searchTerms": [
        "fitness app"
    ],
    "countries": [
        "US"
    ],
    "maxAdsPerSearch": 3,
    "maxAds": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/meta-ad-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 = {
    "searchTerms": ["fitness app"],
    "countries": ["US"],
    "maxAdsPerSearch": 3,
    "maxAds": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("automation_craft/meta-ad-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 '{
  "searchTerms": [
    "fitness app"
  ],
  "countries": [
    "US"
  ],
  "maxAdsPerSearch": 3,
  "maxAds": 3
}' |
apify call automation_craft/meta-ad-transcript-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation_craft/meta-ad-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/588PDR5Z98ypgCQ4E/builds/fs7mrM4Snc8kjr3oe/openapi.json
