# Ad Spender Detector — Facebook & Instagram Ad Library Scraper (`jurassic_jove/facebook-ad-library-scraper`) Actor

Facebook Ad Library scraper that finds businesses running Facebook & Instagram ads. Proof-of-budget B2B leads with a spend-signal score and contact emails.

- **URL**: https://apify.com/jurassic\_jove/facebook-ad-library-scraper.md
- **Developed by:** [Data Runner](https://apify.com/jurassic_jove) (community)
- **Categories:** Social media, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $70.00 / 1,000 active advertiser delivereds

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/platform/actors/running/actors-in-store#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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## Ad Spender Detector — Find Businesses Actively Running Facebook & Instagram Ads

**Find businesses that are spending money on ads right now — and reach them before your competitors do.** Ad Spender Detector is a **Facebook Ad Library scraper** built for lead generation: it searches **Meta's public Ad Library** by niche keyword and country, surfaces every business currently running **Facebook & Instagram ads**, scores how strong a spender each one is, and pulls their **contact emails**. Every result is a company that has already proven the two things agencies pay to find: **a marketing budget and the intent to grow.**

> Also searched as: *Facebook Ad Library scraper*, *Meta Ad Library scraper*, *Facebook ads scraper by keyword*, *find businesses running Facebook ads*, *competitor ad finder*.

If a business is paying to run ads today, they are self-selecting as your customer. This Actor hands you a list of them, with contacts, on demand.

---

### Why this is the strongest B2B buying signal there is

Most lead lists tell you a business *exists*. This one tells you a business is **actively spending money to acquire customers** — the single most reliable predictor that they will buy marketing, creative, CRO, landing-page, or lead-gen services.

- 💰 **Proof of budget, not a guess.** An active ad in the Ad Library is money being spent *now*. No "estimated revenue," no firmographic guessing — a live campaign is the receipt.
- 📈 **Proof of growth intent.** Businesses that advertise want more customers. That's your entire pitch, pre-qualified.
- 🎯 **A 0–100 Spend Signal Score.** Rank a whale running 40 ads across every platform above a hobbyist testing one — so your team calls the biggest budgets first.
- ✉️ **Contacts included.** Emails are pulled straight from each advertiser's own landing pages, filtered for the usual noise.
- 🌐 **Public, transparent data source.** The [Meta Ad Library](https://www.facebook.com/ads/library/) is Meta's own ad-transparency tool — public by design, no login, showing every active ad on Facebook and Instagram.

#### Who it's for

| You are… | You get… |
|---|---|
| A **marketing / growth agency** | Businesses already paying for growth — pitch them a better funnel. |
| A **CRO / landing-page shop** | Advertisers sending paid traffic to pages you can optimize. |
| A **creative / video studio** | Brands running ads that need fresh creative — you've seen their current ad. |
| A **lead-gen / cold-outreach seller** | A list where *every* record has budget and intent, not just a pulse. |

**Pitch businesses that already pay for growth — instead of convincing someone to start.**

---

### How it works

1. **Search** the public Ad Library for each of your niche keywords, in your chosen country, for active ads.
2. **Aggregate by advertiser** — many ads collapse into one business record (deduplicated by Facebook Page), tagged with every keyword it matched.
3. **Score** each advertiser's spend signal 0–100 from how many ads it runs, how long they've been live, and how many platforms it's on.
4. **Extract emails** from each advertiser's landing pages through a battle-tested contact-extraction pipeline (plain text, `mailto:`, and obfuscated emails).
5. **Deliver** one clean record per advertiser, highest spend signal first.

#### Realistic input

```json
{
  "searchTerms": ["roof repair"],
  "country": "US",
  "activeStatus": "active",
  "minActiveAds": 3,
  "maxAdvertisers": 50,
  "extractEmails": true,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
````

> `minActiveAds: 3` is the pro move — it filters out businesses dabbling with a single ad and keeps the ones running multiple creatives at once (i.e. actually scaling spend).

#### Example output — one advertiser record

```json
{
  "advertiserName": "Apex Roofing Co",
  "pageUrl": "https://www.facebook.com/apexroofing",
  "pageId": "100200300",
  "spendSignalScore": 87,
  "activeAdsCount": 14,
  "platforms": ["audience_network", "facebook", "instagram"],
  "earliestStartDate": "2026-03-03",
  "adRunningDays": 124,
  "adCategories": ["Roofing Contractor"],
  "landingDomains": ["apexroofing.com"],
  "website": "https://apexroofing.com",
  "emails": ["info@apexroofing.com", "sales@apexroofing.com"],
  "primaryEmail": "info@apexroofing.com",
  "sampleAdText": "Need a new roof? Get a free inspection this week — financing…",
  "searchTermsMatched": ["roof repair", "roofing contractor"],
  "scrapedAt": "2026-07-14T15:04:00.000Z"
}
```

At a glance: Apex has been running ads for **124 days** across **three platforms**, has **14 live ads**, and you have their inbox. That's a business you call today.

The run also writes a **summary** to the `OUTPUT` key (and as a final dataset row): advertisers found, breakdown by platform, average active ads, % with email, per-search-term counts, anything that was blocked, and the exact number of billable events.

***

### The Spend Signal Score, explained (no black box)

`spendSignalScore` is a transparent, deterministic 0–100 blend of three public signals. The same advertiser always scores the same — there's no hidden model and no randomness.

| Component | Max points | What it measures | How it's scaled |
|---|---|---|---|
| **Ad volume** | 50 | Distinct active ads running concurrently — more creative in market = more spend. | Saturating (log) curve; reaches full marks at ~30 ads, so a 200-ad brand and a 30-ad brand both read as "clearly spending a lot." |
| **Ad longevity** | 35 | How long the longest-running ad has been live — advertisers kill losers fast, so a long run = proven ROI. | Linear to 90 days, then flat. |
| **Platform breadth** | 15 | How many of Meta's placements (Facebook, Instagram, Audience Network, Messenger) it runs on. | 1 platform = 0, each additional adds evenly up to the cap. |

**Score = ad volume + ad longevity + platform breadth**, clamped to 0–100.

A brand-new single ad on one platform lands a modest floor (well under 20); a business running many ads, for months, everywhere, tops out near 100. It is a **relative ranking signal, not a dollar estimate** — see limitations.

***

### Works perfectly with the rest of the suite

Ad Spender Detector is the top of the funnel. Chain it with the rest of the **Data Runner** lead stack:

1. **[Lead Deduplicator & Merger](https://apify.com/jurassic_jove/lead-deduplicator-merger)** — merge these advertisers with leads from your other sources and de-duplicate cleanly.
2. **[Email Verifier & Enricher](https://apify.com/jurassic_jove/email-verifier-enricher)** — validate every email so your outreach actually lands.
3. **[Phone Number Validator](https://apify.com/jurassic_jove/phone-number-validator)** — verify and format phone numbers for calling/SMS.
4. **[Icebreaker Generator](https://apify.com/jurassic_jove/icebreaker-generator)** — turn each record into a personalized opener. With this source it's lethal: the icebreaker can reference *the ads they're literally running right now* ("Saw Apex has been running roofing ads for four months straight…").

***

### Pricing

This Actor uses **pay-per-event** pricing — you pay for results, not for time or servers.

| Event | Price | Charged when |
|---|---|---|
| **Active advertiser delivered** | **$0.07** | Once per unique advertiser pushed to your dataset (passed your filters, aggregated, and scored). |
| **Advertiser enriched with emails** | **$0.02** | Only when the email pipeline actually runs for an advertiser (a landing domain was found and visited). |
| Actor start | $0.00005 | Once per run (the first 5 seconds of compute are free). |

**Blocked, filtered-out, and failed advertisers are never charged.** Turn `extractEmails` off and you pay only the $0.07 per advertiser.

> **One thing to know:** the Actor fetches raw ads through a maintained upstream Ad Library scraper, whose small per-ad fee (typically well under a cent per advertiser) is billed to **your** Apify account in addition to the events above — the same pattern as other Meta-sourcing Actors. Make sure your account has credits.

**Example:** 50 advertisers with email extraction ≈ 50 × ($0.07 + $0.02) = **$4.50** + a few cents of upstream ad fees. A list of 50 businesses proven to be spending on ads, with contacts.

***

### Honest limitations

We'd rather you trust the numbers than be surprised.

- **It shows presence, not dollars.** The public Ad Library reveals *that* a business advertises and *what* the ads are — **not how much they spend**. `spendSignalScore` is a signal derived from public activity, **not** a spend estimate. (Exact spend/impression figures exist only for political & social-issue ads, and for EU-delivered ads under transparency law — not for ordinary commercial ads.)
- **Not every advertiser has a public email.** Some send ad traffic to click-to-message (WhatsApp/Messenger) or app installs, or hide contacts behind forms. Those still count as proven spenders — they just arrive without an email. Expect a healthy but not universal email hit rate.
- **Meta may rate-limit at volume.** The Ad Library is heavily protected. This Actor paces itself, keeps `maxAdvertisers` bounded, and if it hits consistent blocks it **stops cleanly, marks the run `blocked` with an actionable note, and delivers whatever it already collected** — it never loops forever or solves CAPTCHAs.
- **Keyword matching is Meta's.** Results reflect how the Ad Library matches your keywords to ad text and advertiser names; very broad terms return broad results. Use `minActiveAds` to raise the quality bar.
- **Not affiliated with Meta.** "Facebook," "Instagram," and "Meta" are trademarks of Meta Platforms, Inc. This Actor is an independent tool that reads Meta's public Ad Library transparency data and is not endorsed by or affiliated with Meta.

***

### FAQ

**How do I find businesses that are running Facebook or Instagram ads?**
Give Ad Spender Detector your niche keywords and a country. It searches Meta's public Ad Library for advertisers matching those terms, deduplicates them into one record per business, scores each one's spend signal, and returns their Page, landing domains, and contact emails — a ready-to-use list of businesses currently advertising on Facebook and Instagram.

**Can I scrape the Facebook Ad Library by keyword?**
Yes — that's exactly what this Actor does. Add one or more keywords to `searchTerms` (e.g. "roof repair", "med spa", "personal injury lawyer"), pick a country, and it returns the advertisers whose active ads match, aggregated by business with a spend-signal score and emails.

**Does this tell me how much a business spends on ads?**
No — and any tool claiming exact commercial spend from the public Ad Library is guessing. Meta publishes spend/impression ranges only for political and social-issue ads (and reach data for EU-delivered ads). For ordinary businesses, the Ad Library shows *presence and activity*, which is exactly what `spendSignalScore` ranks. Presence alone is the signal you need: they're spending, and they want customers.

**Is scraping the Ad Library allowed?**
The Ad Library is Meta's **public** ad-transparency tool — no login required, published deliberately so anyone can inspect active ads. This Actor reads only that logged-out public data. As always, use the output responsibly and in line with your own outreach and privacy obligations.

**Why don't all advertisers have an email?**
Because not every advertiser exposes one. Many run click-to-message or app-install ads, or gate contact behind a form. You still get the business, its Page, its landing domain, and its spend signal — just not always an inbox. Pipe the results through the **Email Verifier & Enricher** to squeeze out more.

**Which countries are supported?**
Any country the Ad Library serves — set the `country` field to an ISO code (US, GB, CA, AU, DE, BR, and dozens more). Results are ads shown to people in that country.

**What's the difference between "active" and "all" ad status?**
"Active only" (default) returns advertisers with ads running *right now* — the strongest live signal. "All" also includes advertisers whose ads recently stopped, useful for a wider net.

**How do I get more (or fewer, cheaper) results?**
Add more `searchTerms`, raise `maxAdvertisers` (hard cap 300), or lower `minActiveAds`. To tighten quality and cost, raise `minActiveAds` to 3–5 so you only get multi-ad spenders.

**What happens if Meta blocks the run?**
It degrades gracefully: bounded retries, then a clean stop with the run marked `blocked` and an actionable note, delivering everything collected up to that point. You're never charged for blocked results.

**Is this a Meta product?**
No. It's an independent Actor that reads Meta's public Ad Library. It is not affiliated with, endorsed by, or sponsored by Meta Platforms, Inc.

***

Built by [data-runner.dev](https://data-runner.dev) — the Data Runner lead-generation suite on Apify.

# Actor input Schema

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

Niche keywords to search in the Ad Library — the kind of business you want to find spending on ads. Add several to widen the net; advertisers matching more than one term are delivered once and tagged with every term they matched. Examples: "roof repair", "med spa", "personal injury lawyer", "dental implants".

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

Ad Library region (ISO alpha-2 country code). The Ad Library is country-scoped: results are ads shown to people in this country.

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

Which Meta platforms the ad must run on. Leave all selected (default) to include every placement. An advertiser is kept if any of its active ads runs on any selected platform.

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

"Active only" (default) returns advertisers with ads running right now — the strongest live buying signal. "All (active + inactive)" also includes advertisers whose ads recently stopped.

## `minActiveAds` (type: `integer`):

Only include advertisers running at least this many distinct active ads. Higher = bigger spender (an advertiser running 8 ads is testing creative and scaling, not dabbling). 1 = every advertiser with at least one ad.

## `maxAdvertisers` (type: `integer`):

Maximum number of UNIQUE advertisers to fully process and deliver, across all search terms combined. Strictly enforced to bound cost and block exposure. Hard cap 300.

## `extractEmails` (type: `boolean`):

Follow each advertiser's landing/page domains and extract contact emails through the reused email-extraction pipeline (plain text, mailto:, and Cloudflare-obfuscated). Charged only when the pipeline actually runs for an advertiser (a domain was found and visited). Turn off to get advertiser + spend-signal data only.

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

Apify proxy used for landing-page email extraction. RESIDENTIAL is recommended for the best reach and lowest block rate. The Ad Library search itself is delegated to a maintained upstream Actor and does not use this proxy.

## `adLibraryActorId` (type: `string`):

The Apify Actor used to fetch raw ads from the public Ad Library. Defaults to a maintained community Actor. Its per-ad fee is billed to YOUR Apify account, in addition to this Actor's per-advertiser fee. Override only if you prefer a different Ad Library source.

## `maxAdsScannedPerTerm` (type: `integer`):

Upper bound on how many raw ads the upstream Actor fetches per search term before aggregation. Bounds upstream cost. The Actor stops early once maxAdvertisers unique advertisers are collected. Leave at default unless you are tuning cost vs. coverage.

## Actor input object example

```json
{
  "searchTerms": [
    "roof repair"
  ],
  "country": "US",
  "platforms": [
    "facebook",
    "instagram",
    "audience_network",
    "messenger"
  ],
  "activeStatus": "active",
  "minActiveAds": 3,
  "maxAdvertisers": 25,
  "extractEmails": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "adLibraryActorId": "curious_coder/facebook-ads-library-scraper",
  "maxAdsScannedPerTerm": 500
}
```

# 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": [
        "roof repair"
    ],
    "country": "US",
    "platforms": [
        "facebook",
        "instagram",
        "audience_network",
        "messenger"
    ],
    "activeStatus": "active",
    "minActiveAds": 3,
    "maxAdvertisers": 25,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    },
    "adLibraryActorId": "curious_coder/facebook-ads-library-scraper",
    "maxAdsScannedPerTerm": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("jurassic_jove/facebook-ad-library-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": ["roof repair"],
    "country": "US",
    "platforms": [
        "facebook",
        "instagram",
        "audience_network",
        "messenger",
    ],
    "activeStatus": "active",
    "minActiveAds": 3,
    "maxAdvertisers": 25,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
    "adLibraryActorId": "curious_coder/facebook-ads-library-scraper",
    "maxAdsScannedPerTerm": 500,
}

# Run the Actor and wait for it to finish
run = client.actor("jurassic_jove/facebook-ad-library-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": [
    "roof repair"
  ],
  "country": "US",
  "platforms": [
    "facebook",
    "instagram",
    "audience_network",
    "messenger"
  ],
  "activeStatus": "active",
  "minActiveAds": 3,
  "maxAdvertisers": 25,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "adLibraryActorId": "curious_coder/facebook-ads-library-scraper",
  "maxAdsScannedPerTerm": 500
}' |
apify call jurassic_jove/facebook-ad-library-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=jurassic_jove/facebook-ad-library-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Ad Spender Detector — Facebook & Instagram Ad Library Scraper",
        "description": "Facebook Ad Library scraper that finds businesses running Facebook & Instagram ads. Proof-of-budget B2B leads with a spend-signal score and contact emails.",
        "version": "0.1",
        "x-build-id": "aUY0cdTyUjia6w9KH"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/jurassic_jove~facebook-ad-library-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-jurassic_jove-facebook-ad-library-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/jurassic_jove~facebook-ad-library-scraper/runs": {
            "post": {
                "operationId": "runs-sync-jurassic_jove-facebook-ad-library-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/jurassic_jove~facebook-ad-library-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-jurassic_jove-facebook-ad-library-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "searchTerms"
                ],
                "properties": {
                    "searchTerms": {
                        "title": "Search terms (niche keywords)",
                        "type": "array",
                        "description": "Niche keywords to search in the Ad Library — the kind of business you want to find spending on ads. Add several to widen the net; advertisers matching more than one term are delivered once and tagged with every term they matched. Examples: \"roof repair\", \"med spa\", \"personal injury lawyer\", \"dental implants\".",
                        "items": {
                            "type": "string"
                        }
                    },
                    "country": {
                        "title": "Country",
                        "enum": [
                            "US",
                            "CA",
                            "GB",
                            "IE",
                            "AU",
                            "NZ",
                            "DE",
                            "FR",
                            "ES",
                            "IT",
                            "NL",
                            "BE",
                            "AT",
                            "CH",
                            "PT",
                            "SE",
                            "NO",
                            "DK",
                            "FI",
                            "PL",
                            "BR",
                            "MX",
                            "AR",
                            "CO",
                            "CL",
                            "PE",
                            "IN",
                            "SG",
                            "AE",
                            "SA",
                            "ZA",
                            "PH",
                            "ID",
                            "MY",
                            "TH",
                            "JP",
                            "KR"
                        ],
                        "type": "string",
                        "description": "Ad Library region (ISO alpha-2 country code). The Ad Library is country-scoped: results are ads shown to people in this country.",
                        "default": "US"
                    },
                    "platforms": {
                        "title": "Platforms",
                        "type": "array",
                        "description": "Which Meta platforms the ad must run on. Leave all selected (default) to include every placement. An advertiser is kept if any of its active ads runs on any selected platform.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "facebook",
                                "instagram",
                                "audience_network",
                                "messenger"
                            ],
                            "enumTitles": [
                                "Facebook",
                                "Instagram",
                                "Audience Network",
                                "Messenger"
                            ]
                        },
                        "default": [
                            "facebook",
                            "instagram",
                            "audience_network",
                            "messenger"
                        ]
                    },
                    "activeStatus": {
                        "title": "Ad status",
                        "enum": [
                            "active",
                            "all"
                        ],
                        "type": "string",
                        "description": "\"Active only\" (default) returns advertisers with ads running right now — the strongest live buying signal. \"All (active + inactive)\" also includes advertisers whose ads recently stopped.",
                        "default": "active"
                    },
                    "minActiveAds": {
                        "title": "Minimum active ads",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Only include advertisers running at least this many distinct active ads. Higher = bigger spender (an advertiser running 8 ads is testing creative and scaling, not dabbling). 1 = every advertiser with at least one ad.",
                        "default": 1
                    },
                    "maxAdvertisers": {
                        "title": "Max advertisers",
                        "minimum": 1,
                        "maximum": 300,
                        "type": "integer",
                        "description": "Maximum number of UNIQUE advertisers to fully process and deliver, across all search terms combined. Strictly enforced to bound cost and block exposure. Hard cap 300.",
                        "default": 50
                    },
                    "extractEmails": {
                        "title": "Extract contact emails from landing pages",
                        "type": "boolean",
                        "description": "Follow each advertiser's landing/page domains and extract contact emails through the reused email-extraction pipeline (plain text, mailto:, and Cloudflare-obfuscated). Charged only when the pipeline actually runs for an advertiser (a domain was found and visited). Turn off to get advertiser + spend-signal data only.",
                        "default": true
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Apify proxy used for landing-page email extraction. RESIDENTIAL is recommended for the best reach and lowest block rate. The Ad Library search itself is delegated to a maintained upstream Actor and does not use this proxy.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    },
                    "adLibraryActorId": {
                        "title": "Upstream Ad Library Actor (advanced)",
                        "type": "string",
                        "description": "The Apify Actor used to fetch raw ads from the public Ad Library. Defaults to a maintained community Actor. Its per-ad fee is billed to YOUR Apify account, in addition to this Actor's per-advertiser fee. Override only if you prefer a different Ad Library source."
                    },
                    "maxAdsScannedPerTerm": {
                        "title": "Max ads scanned per term (advanced)",
                        "minimum": 20,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Upper bound on how many raw ads the upstream Actor fetches per search term before aggregation. Bounds upstream cost. The Actor stops early once maxAdvertisers unique advertisers are collected. Leave at default unless you are tuning cost vs. coverage."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
