# Meta Ad Creative Analyzer (`iturrilabs/ad-breakdown`) Actor

Turn Facebook and Instagram ads into structured creative research: transcript, on-screen text, hook, angle, offer, CTA and timeline. Search by advertiser or keyword, and track only new ads. Failed ads are never charged.

- **URL**: https://apify.com/iturrilabs/ad-breakdown.md
- **Developed by:** [IturriLabs](https://apify.com/iturrilabs) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 video ad analyzeds

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

Learn more: https://docs.apify.com/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 Creative Analyzer

Turn Facebook and Instagram ads into structured creative research. Give it an advertiser, keyword, or Ad Library URL and get the transcript, on-screen text, hook, angle, offer, CTA, and a timeline of each ad.

### What you get

- **Exact words:** spoken transcript and on-screen text in the ad's original language.
- **Creative breakdown:** hook, angle, audience, offer, pain points, proof, CTA, format, and tone.
- **Timeline:** what happens in each part of a video ad.
- **Ideas:** why the ad may work and variations to test.
- **New-ad tracking:** use a monitor name on a schedule to analyze only ads you have not seen.

### Who it is for

Creative strategists, media buyers, agencies, and AI agents that need to understand competitors' ads without watching them one by one.

### How to use it

1. Add advertisers, keywords, or Ad Library URLs.
2. Choose a country, language, and the maximum number of ads.
3. Run it and export the results to JSON, CSV, or Excel, or use them through the API.

You can also analyze a dataset from `jmlp/meta-ad-library-scraper` or `apify/facebook-ads-scraper`, or public media URLs.

### Input example

```json
{
  "keywords": ["protein powder"],
  "country": "US",
  "activeStatus": "active",
  "maxAds": 10,
  "analysisLanguage": "en",
  "monitorName": "protein-powder-us"
}
```

Only video ads are analyzed by default. Turn on **Include image ads** if an advertiser mainly runs static images.

### Output example

Shortened result from a real public ad:

```json
{
  "status": "analyzed",
  "advertiser": "Shop FlavCity",
  "adType": "video",
  "hookText": "What do you think the big difference is between these protein shakes at the store and this FlavCity protein powder smoothie?",
  "hookType": "question",
  "angle": "Comparing the ingredient quality of a popular store-bought protein shake with the advertised product.",
  "offer": "Protein starter kit with 10 single serves and a free shaker cup.",
  "cta": "Shop now",
  "format": "talking_head",
  "adLibraryUrl": "https://www.facebook.com/ads/library/?id=904160855878574",
  "analysis": {
    "transcript": "What do you think the big difference is between these protein shakes at the store and this FlavCity protein powder smoothie?...",
    "on_screen_text": ["What's the BIG difference?"],
    "structure": [
      {"start_seconds": 0, "end_seconds": 3, "label": "hook", "description": "The host poses a question comparing two protein products."},
      {"start_seconds": 52, "end_seconds": 60, "label": "CTA", "description": "The host introduces the starter kit offer and encourages the viewer to try it."}
    ]
  }
}
```

A `SUMMARY` record in the run's key-value store counts hooks, formats, and advertisers.

### Pricing

You pay per analyzed ad. Ads that fail, have expired media, or are too large are not charged. When you search by advertiser, keyword, or URL, the Ad Library scraper run is billed separately at its own price. Set a maximum cost per run to control spending.

### Limits

- Media files are limited to 18 MB.
- Only publicly available ads are processed.
- Analysis is AI-generated and may contain mistakes, so review it before making decisions.

# Actor input Schema

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

Facebook page IDs, names, @usernames or page links.

## `keywords` (type: `array`):

Search the Ad Library by keyword across all advertisers.

## `adLibraryUrls` (type: `array`):

Full Meta Ad Library search or page URLs.

## `inputDatasetId` (type: `string`):

Analyze ads you already scraped. Works with datasets from jmlp/meta-ad-library-scraper and apify/facebook-ads-scraper.

## `mediaUrls` (type: `array`):

Analyze ad creatives directly from public HTTPS URLs.

## `country` (type: `string`):

Ad Library country.

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

Which ads to search for.

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

Maximum number of ads to analyze and charge for in this run.

## `includeImageAds` (type: `boolean`):

Also analyze image ads. Video ads are always analyzed.

## `analysisLanguage` (type: `string`):

Language for the analysis. Transcripts always stay in the ad's original language.

## `monitorName` (type: `string`):

Use the same name on scheduled runs to analyze only ads not seen before. Letters, numbers and hyphens only.

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

How many ads to analyze at the same time.

## Actor input object example

```json
{
  "keywords": [
    "protein powder"
  ],
  "country": "US",
  "activeStatus": "active",
  "maxAds": 2,
  "includeImageAds": false,
  "analysisLanguage": "en",
  "concurrency": 3
}
```

# Actor output Schema

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

One record per ad with its transcript, hook, angle, offer, CTA and timeline.

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

Totals by result, hook type, format and advertiser.

# 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 = {
    "keywords": [
        "protein powder"
    ],
    "country": "US",
    "maxAds": 2
};

// Run the Actor and wait for it to finish
const run = await client.actor("iturrilabs/ad-breakdown").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 = {
    "keywords": ["protein powder"],
    "country": "US",
    "maxAds": 2,
}

# Run the Actor and wait for it to finish
run = client.actor("iturrilabs/ad-breakdown").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 '{
  "keywords": [
    "protein powder"
  ],
  "country": "US",
  "maxAds": 2
}' |
apify call iturrilabs/ad-breakdown --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,iturrilabs/ad-breakdown"
        }
    }
}
```

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/WkB0EQRzpNmXaW6TN/builds/ehsBPeVGvik2ZP0Wi/openapi.json
