# Meta Ads Library Scraper (`solidcode/meta-ads-library-scraper`) Actor

\[💰 $0.4 / 1K] Extract ads from Meta's public Ad Library across Facebook, Instagram, Messenger, Audience Network, Threads, and WhatsApp. Search by keyword, advertiser page, or Ad Library URL. Returns ad copy, CTAs, advertiser details, dates, platforms, and audience estimates. No login required.

- **URL**: https://apify.com/solidcode/meta-ads-library-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** Social media, Lead generation, Automation
- **Features:** Limited permissions
- **Stats:** 1,383 total users, 155 monthly users, 100.0% runs succeeded, 10 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.40 / 1,000 ad results

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 Ads Library Scraper — Facebook Ads Scraper (Facebook, Instagram & Messenger Ads)

The Meta Ads Library Scraper is a Facebook Ads Scraper for the public Meta Ad Library. Scrape Facebook ads, Instagram ads, Messenger ads, and Audience Network ads at scale — search by keyword, advertiser page URL, or any Ad Library URL, and receive structured JSON with ad copy, CTAs, advertiser data, start/end dates, and per-platform breakdowns. Built for marketers, researchers, and competitive-intelligence teams who need fresh Facebook ad data without spending hours clicking through the Ad Library UI.

### Why This Meta Ads Library Scraper?

- **Live data straight from the public Meta Ad Library** — every run reflects what's currently published on Facebook and Instagram, not a stale cache
- **Six Meta ad surfaces in one schema** — Facebook ads, Instagram ads, Messenger ads, Audience Network, Threads, and WhatsApp ads unified under a single `publisherPlatforms` field
- **52 supported countries** plus an "All countries" mode — scrape Facebook ads from every market in one job, no per-country runs
- **Keyword search, advertiser page URL, or pasted Ad Library URL** — mix all three in one run; URL filters (active status, media type, language, date range) are preserved automatically
- **Full political-ad transparency payload** — declared spend range and currency, impression range, estimated audience reached, an age-and-gender breakdown of who saw the ad, and a per-state delivery split across all 50 US states, all attached automatically to political and issue ads
- **Pay only for the depth you need** — base ad data, optional creative details (CTA link, headline, snapshot URL), and optional advertiser-page enrichment (category, like count, verified flag, linked Instagram handle, follower count) are billed as separate events
- **Pre-flight count mode** — return only the total matching-ad count per source, billed as a single low-cost summary row, before committing to a full Facebook ads scrape
- **No Facebook login required** — the Ad Library is a public transparency database; this scraper does not need credentials, cookies, or any account access
- **Structured JSON output** — camelCase fields, ISO 8601 dates, and ready for Zapier, Make, Google Sheets, or your own pipeline

### Supported Platforms

- Facebook
- Instagram
- Messenger
- Audience Network
- Threads
- WhatsApp

### Use Cases

**Competitor Research & Ad Spy**

- Track every Facebook ad a rival brand has ever run — active or stopped — to map their creative strategy and messaging evolution
- Compare Instagram ads side-by-side across competing e-commerce brands to identify winning offers and seasonal campaigns
- Monitor a competitor's Facebook ad volume over time using the pre-flight count mode as a pulse check
- Build a Facebook ad library of competitor creative for swipe files, agency pitches, and creative reviews

**Ad Creative Analysis**

- Aggregate ad copy from hundreds of Facebook advertisers in a category to spot copy patterns and angle trends
- Filter Facebook and Instagram ads by media type (image vs. video) to benchmark creative mix across a vertical
- Export CTAs and headlines in bulk for copywriting research and A/B inspiration

**Political-Ad Transparency & Compliance**

- Pull every political or social-issue ad running in a given country to audit declared spend ranges and audience estimates
- Research election-period Facebook ad activity for journalism, academic study, or regulatory compliance
- Filter by the "Political & social-issue ads" category to access Meta's mandatory disclosures: estimated audience size, regional reach, and demographic breakdowns

**E-commerce & DTC Intelligence**

- Scrape Instagram ads from direct-to-consumer brands to monitor product launches, discount offers, and creative fatigue signals
- Build a dataset of active Facebook ads by category to inform media-buying decisions or benchmark CPM-proxy signals
- Track when a competitor goes dark (no active ads) or ramps up spend intensity

**Influencer & Affiliate Research**

- Find all ads from a specific advertiser page to identify which affiliate offers are actively running
- Filter by platform to see which brands are investing in Instagram versus Facebook versus Messenger
- Pull ad copy for compliance review or brand-safety screening

**Brand Safety & Monitoring**

- Monitor whether your brand name appears in competitor ads using keyword search
- Track impersonator pages by searching your brand terms and checking advertiser page IDs against your verified list
- Alert on new ads from a specific page URL to catch unauthorized use of your brand identity

### Getting Started

#### Search Facebook Ads by Keyword (simplest)

Search Facebook and Instagram ads by topic or brand name across all countries:

```json
{
    "searchTerms": ["nike"],
    "maxResults": 100
}
```

#### Keyword Search with Filters

Search for active Facebook and Instagram video ads in the United States published after a specific date:

```json
{
    "searchTerms": ["electric scooter", "e-scooter"],
    "country": "US",
    "adActiveStatus": "ACTIVE",
    "mediaType": "VIDEO",
    "publisherPlatforms": ["FACEBOOK", "INSTAGRAM"],
    "dateFrom": "2025-01-01",
    "maxResults": 500
}
```

#### Scrape All Facebook Ads from a Specific Advertiser

Pass a Facebook page URL to collect every public Facebook ad run by that advertiser:

```json
{
    "pageUrls": ["https://www.facebook.com/nike"],
    "country": "US",
    "adActiveStatus": "ALL",
    "scrapeAdDetails": true,
    "includeAboutPage": true,
    "maxResults": 1000
}
```

#### Paste a Facebook Ad Library URL

Copy any URL from the Facebook Ad Library UI — all filters encoded in the URL are preserved automatically:

```json
{
    "startUrls": [
        "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=running+shoes&media_type=image"
    ],
    "maxResults": 200
}
```

#### Political Ads with Full Transparency Data

Pull political and issue ads for a country to access spend ranges, audience estimates, and demographic breakdowns:

```json
{
    "searchTerms": ["vote", "election"],
    "country": "US",
    "adType": "POLITICAL_AND_ISSUE_ADS",
    "scrapeAdDetails": true,
    "maxResults": 500
}
```

#### Pre-flight Count Check

Check how many matching Facebook ads exist before running the full scrape:

```json
{
    "searchTerms": ["crypto trading"],
    "country": "ALL",
    "onlyTotalCount": true
}
```

You get one row per search with `totalAdsCount` (the same "~N results" figure the Ad Library shows, with all your filters applied) and a readable `totalAdsCountText`. Meta stops counting at 50,000, so very broad searches show `50,000+` and `isCountCapped: true`.

### Input Reference

#### What to Scrape

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchTerms` | string\[] | `["nike"]` | Keywords to search the Ad Library for (e.g. `"electric scooter"`, `"crypto trading"`). Each term runs as its own Ad Library search. Leave empty if you only want to use Page URLs or Ad Library URLs. |
| `pageUrls` | string\[] | `[]` | Facebook page URLs (e.g. `https://www.facebook.com/nike`) or numeric page IDs. Returns every public ad currently or historically run by that advertiser. |
| `startUrls` | string\[] | `[]` | Paste full Meta Ad Library URLs (`https://www.facebook.com/ads/library/?...`) — every filter encoded in the URL is preserved. Useful when you've already configured a search in the Ad Library UI. |

#### Filters

All filters apply to Search Terms and Advertiser Pages. Filters are ignored on URLs you paste into "Ad Library URLs" — those URLs already carry their own filters.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `country` | string | `"ALL"` | Country whose Ad Library to query. Use `"ALL"` to search every country at once. Applied to Search Terms and Advertiser Pages; URLs in "Ad Library URLs" use whatever country is encoded in the URL. |
| `adActiveStatus` | string | `"ALL"` | Whether to return only currently-running ads (`"ACTIVE"`), only stopped/inactive ads (`"INACTIVE"`), or both (`"ALL"`). The Ad Library marks ads ACTIVE while they're still being delivered and INACTIVE once they've stopped. |
| `adType` | string | `"ALL"` | Meta groups ads into transparency categories. `"ALL"` covers every public ad. The other categories surface political/issue, housing, employment, and credit ads where Meta provides additional disclosures (audience estimates, sometimes spend). Options: `"ALL"`, `"POLITICAL_AND_ISSUE_ADS"`, `"HOUSING_ADS"`, `"EMPLOYMENT_ADS"`, `"CREDIT_ADS"`. |
| `mediaType` | string | `"ALL"` | Restrict results by creative format. Options: `"ALL"`, `"IMAGE"`, `"VIDEO"`, `"MEME"`, `"NONE"` (text only). |
| `publisherPlatforms` | string\[] | `[]` | Only include ads that ran on these Meta surfaces. Leave empty to include every platform. Options: `"FACEBOOK"`, `"INSTAGRAM"`, `"MESSENGER"`, `"AUDIENCE_NETWORK"`, `"THREADS"`, `"WHATSAPP"`. |
| `languages` | string\[] | `[]` | Only include ads whose creative is in one of these languages. Leave empty for any language. Options: English, Spanish, Portuguese, French, German, Italian, Dutch, Polish, Turkish, Russian, Arabic, Hebrew, Japanese, Korean, Chinese, Hindi, Indonesian, Thai, Vietnamese. |
| `dateFrom` | string | `""` | Only include ads that first ran on or after this date (`YYYY-MM-DD`). Leave empty for no lower bound. |
| `dateTo` | string | `""` | Only include ads that first ran on or before this date (`YYYY-MM-DD`). Leave empty for no upper bound. |

#### Enrichment

Each enrichment toggle adds an extra per-row charge on top of the base ad price — see Pricing below for the rates.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `scrapeAdDetails` | boolean | `false` | Attach creative-level details to every ad row (CTA link, headline, card description, snapshot URL, and CTA button label). Each row that gets these fields is billed at the **Creative details** rate. Disabled when "Only return total count" is on. |
| `includeAboutPage` | boolean | `false` | Look up each advertiser's Facebook page and attach extra fields (category, like count, verified flag, linked Instagram handle, follower count). Each enriched row is billed at the **Advertiser details** rate. Disabled when "Only return total count" is on. |
| `onlyTotalCount` | boolean | `false` | Pre-flight mode — return one row per source containing only the total matching-ad count. Useful for sizing a job before committing budget. Each summary row is billed at the **Total count** rate (much cheaper than full ad collection). When enabled, ad rows are not produced and enrichment toggles are ignored. |

#### Limits

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxResults` | integer | `100` | Cap on total ads collected across every source. Set to `0` for unlimited (the run will keep paginating until Meta returns no more results). Each row is billed at the per-result rate. |

### Output

Each ad row contains the fields below. A realistic example with all enrichment enabled:

```json
{
    "adArchiveID": "1234567890123456",
    "adLibraryURL": "https://www.facebook.com/ads/library/?id=1234567890123456",
    "pageID": "15087023",
    "pageName": "Nike",
    "adStatus": "ACTIVE",
    "publisherPlatforms": ["FACEBOOK", "INSTAGRAM"],
    "startDate": "2025-03-15",
    "endDate": null,
    "adCreationTime": "2025-03-14T18:30:00+00:00",
    "adText": "Run your world. New Air Max 2025 — designed for everyday miles.",
    "adCreativeBodies": [
        "Run your world. New Air Max 2025 — designed for everyday miles."
    ],
    "ctaDomain": "nike.com",
    "ctaUrl": "https://www.nike.com/air-max",
    "ctaHeadline": "Air Max 2025",
    "ctaDescription": "Shop the latest Air Max collection.",
    "ctaText": "Shop Now",
    "ctaType": "SHOP_NOW",
    "adSnapshotUrl": "https://www.facebook.com/ads/archive/render_ad/?id=1234567890123456",
    "pageURL": "https://www.facebook.com/nike",
    "pageProfilePictureURL": "https://example.com/nike-profile.jpg",
    "pageCategory": "Sportswear Store",
    "pageLikes": 35100000,
    "pageVerified": true,
    "pageInstagramUser": "nike",
    "pageInstagramFollowers": 302000000,
    "pageCountry": null,
    "pageAboutText": "Just Do It.",
    "spend": null,
    "impressions": null,
    "reachEstimate": null,
    "currency": null,
    "estimatedAudienceSize": null,
    "regionsReached": null,
    "demographics": null,
    "source": "search",
    "sourceQuery": "nike"
}
```

#### All Available Fields

| Field | Type | Description |
|-------|------|-------------|
| `adArchiveID` | string | Meta's permanent ad archive ID |
| `adLibraryURL` | string | Direct link to this ad in the public Meta Ad Library |
| `pageID` | string | Facebook page ID of the advertiser |
| `pageName` | string | Advertiser's Facebook page display name |
| `adStatus` | string | `"ACTIVE"` while the ad is being delivered; `"INACTIVE"` once stopped |
| `publisherPlatforms` | string\[] | Surfaces where this ad ran — `FACEBOOK`, `INSTAGRAM`, `MESSENGER`, `AUDIENCE_NETWORK`, `THREADS`, `WHATSAPP` |
| `startDate` | string | ISO date the ad first started running |
| `endDate` | string | ISO date the ad stopped (null if still active) |
| `adCreationTime` | string | ISO 8601 timestamp of ad creation |
| `adText` | string | Primary body copy of the ad creative |
| `adCreativeBodies` | string\[] | All body copy variants (Meta sometimes returns per-placement variants) |
| `ctaDomain` | string | Landing-page domain shown on the ad card (`scrapeAdDetails` required) |
| `ctaUrl` | string | Full destination URL of the CTA button (`scrapeAdDetails` required) |
| `ctaHeadline` | string | Card headline (`scrapeAdDetails` required) |
| `ctaDescription` | string | Card link description (`scrapeAdDetails` required) |
| `ctaText` | string | CTA button label, e.g. "Shop Now" (`scrapeAdDetails` required) |
| `ctaType` | string | CTA button type enum, e.g. `SHOP_NOW` (`scrapeAdDetails` required) |
| `adSnapshotUrl` | string | Direct iframe render URL for the ad creative — `https://www.facebook.com/ads/archive/render_ad/?id=...` (`scrapeAdDetails` required) |
| `pageURL` | string | Public Facebook page URL (`scrapeAdDetails` or `includeAboutPage` required) |
| `pageProfilePictureURL` | string | Advertiser's profile picture URL (`scrapeAdDetails` required) |
| `pageCategory` | string | Meta-assigned page category, e.g. "Sportswear Store" (`includeAboutPage` required) |
| `pageLikes` | integer | Facebook page like count (`includeAboutPage` required) |
| `pageVerified` | boolean | `true` if the page holds a blue verified badge (`includeAboutPage` required) |
| `pageInstagramUser` | string | Linked Instagram username (`includeAboutPage` required) |
| `pageInstagramFollowers` | integer | Instagram follower count for the linked account (`includeAboutPage` required) |
| `pageCountry` | string | Advertiser's declared country (null — Meta no longer exposes this field) |
| `pageAboutText` | string | Advertiser's "About" bio text (`includeAboutPage` required) |
| `spend` | string | Declared spend range as shown in the Ad Library, e.g. `"$500K - $600K"` — political/issue ads only |
| `impressions` | object | `{ text, index }` impression range, e.g. `">1M"` — political/issue ads only |
| `reachEstimate` | string | Estimated audience reached, e.g. `">1M"` — political/issue ads only |
| `currency` | string | Currency the spend range is quoted in, e.g. `"USD"` — political/issue ads only |
| `estimatedAudienceSize` | integer | Total EU audience reached — only for ads that report EU reach figures |
| `regionsReached` | object\[] | `{ region, reach }` per state or region, where `reach` is that region's share of the ad's total delivery — political/issue ads only |
| `demographics` | object\[] | `{ country, ageRange, male, female, unknown }` age and gender split of the audience reached — political/issue ads only |
| `source` | string | Which input produced this row: `"search"`, `"page"`, or `"url"` |
| `sourceQuery` | string | The originating search term, page URL, or Ad Library URL |

### Tips for Best Results

- **Size the job first with `onlyTotalCount: true`** — each summary row is billed at the cheap Total count rate, so you can confirm a query has the Facebook ad volume you expect before committing budget
- **Use "Ad Library URL" input** when you need complex filter combinations (e.g. specific audiences, custom country sets) — configure your search in the Facebook Ad Library UI first, then copy the URL
- **Only enable enrichment when you need it** — `scrapeAdDetails` and `includeAboutPage` each add a per-row surcharge on top of the base ad price; leave them off for ad-copy-only research
- **Use `adType: "POLITICAL_AND_ISSUE_ADS"`** when researching election or advocacy campaigns — this unlocks Meta's mandatory transparency disclosures (spend range, impressions, estimated audience reached, per-state delivery, age/gender split) with no extra settings to turn on
- **Filter by `publisherPlatforms`** to isolate Instagram-only ads or Facebook-only ads when benchmarking platform-specific creative strategies
- **Set `maxResults: 0`** only for small advertisers or narrow queries — for broad keyword searches Meta can return tens of thousands of Facebook ads
- **Use date filters** (`dateFrom` / `dateTo`) to scope your scrape to a campaign window and avoid processing historical ads you don't need

### Pricing

**From $0.40 per 1,000 results.** This Facebook ads scraper uses Apify's **Pay-per-event** model — among the lowest prices on Apify for Meta Ad Library data. You only pay for the data you collect, and enrichment toggles are billed as separate events so a basic run stays cheap. Your price drops automatically with your Apify discount tier.

#### Ad results by discount tier

| Results | No discount | Bronze | Silver | Gold |
|---------|-------------|--------|--------|------|
| 100 | $0.048 | $0.045 | $0.043 | $0.040 |
| 1,000 | $0.48 | $0.45 | $0.43 | $0.40 |
| 10,000 | $4.80 | $4.50 | $4.30 | $4.00 |
| 100,000 | $48.00 | $45.00 | $43.00 | $40.00 |

Tiered prices take effect on **October 25, 2026**; until then every plan pays the Gold rate.

#### Optional add-ons

| Event | Fires when | No discount | Bronze | Silver | Gold |
|-------|------------|-------------|--------|--------|------|
| **Creative details** | Per ad row when `scrapeAdDetails` is on (adds CTA link, headline, card description, snapshot URL, CTA button label) | $0.12 / 1K | $0.113 / 1K | $0.107 / 1K | $0.10 / 1K |
| **Advertiser page details** | Per ad row when `includeAboutPage` is on (adds page category, like count, verified flag, Instagram username + follower count, About text) | $0.48 / 1K | $0.45 / 1K | $0.43 / 1K | $0.40 / 1K |
| **Pre-flight count** | Per summary row in `onlyTotalCount` mode (one row per source) | $0.024 each | $0.0226 each | $0.0213 each | $0.02 each |

#### Example costs (Gold tier)

| Configuration | 100 ads | 1,000 ads | 10,000 ads | 100,000 ads |
|---------------|---------|-----------|------------|-------------|
| Base only (no enrichment) | $0.04 | $0.40 | $4.00 | $40.00 |
| Base + creative details | $0.05 | $0.50 | $5.00 | $50.00 |
| Base + advertiser details | $0.08 | $0.80 | $8.00 | $80.00 |
| Base + both enrichments (full) | $0.09 | $0.90 | $9.00 | $90.00 |

`onlyTotalCount` runs are billed per source — a 100-keyword pre-flight check costs $2.00 at Gold.

No compute charges and no hidden fees — the per-event price is everything you pay.

### Integrations

Export data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

- **Zapier** / **Make** / **n8n** — Workflow automation — trigger a Slack alert when a competitor runs a new Facebook ad
- **Google Sheets** — Export directly to a spreadsheet for collaborative analysis
- **Webhooks** — POST results to your own endpoint the moment a run completes
- **Apify API** — Full programmatic access; schedule runs, read datasets, and chain actors
- **Apify CLI** — Trigger runs and download results from the command line

### Frequently Asked Questions

**How do I scrape Facebook ads?**
Use the `searchTerms` input to search Facebook ads by keyword, or paste a Facebook page URL into `pageUrls` to pull every ad from a specific advertiser. Both methods query the public Meta Ad Library — no Facebook account, login, or cookies required.

**What is the best Facebook ads scraper on Apify?**
This actor is purpose-built for the Meta Ad Library and consistently among the lowest-priced Facebook ads scrapers on the platform: from $0.40 per 1,000 ads with no compute charges, optional creative-detail and advertiser-page enrichment billed as separate events, and a pre-flight count mode so you can size jobs before paying.

**Can I download Instagram ads from the Meta Ad Library?**
Yes. The Meta Ad Library includes all Instagram ads that advertisers have run across Meta's platforms. Set `publisherPlatforms: ["INSTAGRAM"]` to filter for Instagram-only ads, or leave it empty to include ads from all surfaces (Facebook, Instagram, Messenger, Audience Network, Threads, WhatsApp).

**What data does the Meta Ad Library expose?**
The public Meta Ad Library provides ad copy (body text), advertiser page name and ID, active/inactive status, platforms where the ad ran, start and end dates, and — for political and issue ads — spend ranges, impression ranges, estimated audience reached, per-state delivery splits, and age/gender breakdowns. Housing, employment, and credit ads are searchable as their own categories, but Meta publishes no spend or audience figures for them. Enable `scrapeAdDetails` to also retrieve CTA links, headlines, card descriptions, and snapshot URLs. Enable `includeAboutPage` for page category, like count, and verified status.

**Is scraping Facebook ads legal?**
The Meta Ad Library is a public transparency database that Meta is legally required to maintain under EU and US regulations. Collecting data from it for research, journalism, competitive intelligence, and compliance purposes is widely accepted. Users are responsible for complying with applicable laws, Meta's Terms of Service, and any GDPR obligations when processing data about EU advertisers.

**How do I find all ads from a specific advertiser?**
Put the advertiser's Facebook page URL (e.g. `https://www.facebook.com/nike`) into the `pageUrls` field. The scraper will return every public ad that page has run — active and historical — up to your `maxResults` cap. You can also use a numeric Facebook page ID if you know it.

**Why am I getting zero results?**
The most common causes are: (1) the search term has no matching ads in the selected country — try `country: "ALL"` to search globally; (2) you've set `adActiveStatus: "ACTIVE"` and the advertiser has no currently-running campaigns; (3) the Ad Library uses the advertiser's page language, so try searching in the language the advertiser uses. The actor returns a status message with filter hints when zero results are found.

**Can I scrape the Meta Ad Library without a Facebook account?**
Yes — the Meta Ad Library is a public database with no login wall. This scraper does not require Facebook credentials, cookies, or any account access.

**How do I scrape political ads and see spend data?**
Set `adType: "POLITICAL_AND_ISSUE_ADS"`. Meta mandates additional transparency disclosures for these campaigns, and every one of them lands on the row automatically: declared spend range (`spend`) with its currency, impression range (`impressions`), estimated audience reached (`reachEstimate`), the per-state delivery split (`regionsReached`), and the age and gender breakdown of who saw the ad (`demographics`). Commercial ads do not expose spend or reach data, so those fields stay empty there.

### Legal & Ethical Use

This actor collects data from the Meta Ad Library, a public transparency resource that Meta is required to maintain under EU (Digital Services Act) and US political ad disclosure regulations. The data returned is intentionally public — Meta designed the Ad Library for exactly this kind of research.

Users are responsible for:

- Complying with Meta's Terms of Service and the Ad Library's usage policies
- Observing applicable data protection laws (GDPR, CCPA) when processing EU or California resident data
- Not using extracted data for spam, harassment, impersonation, or any other unlawful purpose

This actor does not access private posts, personal profiles, or any data that Meta has not explicitly made public through the Ad Library.

# Actor input Schema

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

Keywords to search the Ad Library for (e.g. 'electric scooter', 'crypto trading'). Each term runs as its own Ad Library search. Leave empty if you only want to use Page URLs or Start URLs.

## `pageUrls` (type: `array`):

Facebook page URLs (e.g. https://www.facebook.com/nike) or numeric page IDs. Returns every public ad currently or historically run by that advertiser.

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

Paste full Meta Ad Library URLs (https://www.facebook.com/ads/library/?...) — every filter encoded in the URL is preserved. Useful when you've already configured a search in the Ad Library UI.

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

Country whose Ad Library to query. Use 'ALL' to search every country at once. Applied to Search Terms and Advertiser Pages; URLs in 'Ad Library URLs' use whatever country is encoded in the URL.

## `adActiveStatus` (type: `string`):

Whether to return only currently-running ads, only stopped/inactive ads, or both. The Ad Library marks ads ACTIVE while they're still being delivered and INACTIVE once they've stopped.

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

Meta groups ads into transparency categories. 'All ads' covers every public ad. The other categories surface political/issue, housing, employment, and credit ads where Meta provides additional disclosures (audience estimates, sometimes spend).

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

Restrict results by creative format.

## `publisherPlatforms` (type: `array`):

Only include ads that ran on these Meta surfaces. Leave empty to include every platform.

## `languages` (type: `array`):

Only include ads whose creative is in one of these languages. Leave empty for any language.

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

Only include ads that first ran on or after this date (YYYY-MM-DD). Leave empty for no lower bound.

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

Only include ads that first ran on or before this date (YYYY-MM-DD). Leave empty for no upper bound.

## `includeAboutPage` (type: `boolean`):

Look up each advertiser's Facebook page and attach extra fields (category, like count, verified flag, linked Instagram handle, follower count). Each enriched row is billed at the additional 'Advertiser details' rate (see Pricing). Leave off unless you need the page metadata. Disabled when 'Only return total count' is on.

## `scrapeAdDetails` (type: `boolean`):

Attach creative-level details to every ad row (CTA link, headline, card description, snapshot URL, and CTA button label). Each row that gets these fields is billed at the additional 'Creative details' rate (see Pricing). Disabled when 'Only return total count' is on.

## `onlyTotalCount` (type: `boolean`):

Pre-flight mode — return one row per source containing only the total matching-ad count. Useful for sizing a job before committing budget. Each summary row is billed at the 'Total count' rate (much cheaper than full ad collection). Ad rows are not produced and enrichment toggles are ignored.

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

Cap on total ads collected across every source, shared evenly between them — with 3 search terms and a cap of 60 you get roughly 20 ads per term. Set to 0 for unlimited (the run will keep paginating until Meta returns no more results). Each row is billed at the base 'Ad' rate (plus any enrichment surcharges).

## Actor input object example

```json
{
  "searchTerms": [
    "nike"
  ],
  "pageUrls": [],
  "startUrls": [],
  "country": "ALL",
  "adActiveStatus": "ALL",
  "adType": "ALL",
  "mediaType": "ALL",
  "publisherPlatforms": [],
  "languages": [],
  "dateFrom": "",
  "dateTo": "",
  "includeAboutPage": false,
  "scrapeAdDetails": false,
  "onlyTotalCount": false,
  "maxResults": 100
}
```

# Actor output Schema

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

Table of ads with key fields like advertiser, ad text, status, and dates.

## `details` (type: `string`):

Full per-ad detail rows including advertiser-page enrichment, CTA details, and snapshot URL.

# 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": [
        "nike"
    ],
    "pageUrls": [],
    "startUrls": [],
    "country": "ALL",
    "adActiveStatus": "ALL",
    "adType": "ALL",
    "mediaType": "ALL",
    "publisherPlatforms": [],
    "languages": [],
    "dateFrom": "",
    "dateTo": "",
    "includeAboutPage": false,
    "scrapeAdDetails": false,
    "onlyTotalCount": false,
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/meta-ads-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": ["nike"],
    "pageUrls": [],
    "startUrls": [],
    "country": "ALL",
    "adActiveStatus": "ALL",
    "adType": "ALL",
    "mediaType": "ALL",
    "publisherPlatforms": [],
    "languages": [],
    "dateFrom": "",
    "dateTo": "",
    "includeAboutPage": False,
    "scrapeAdDetails": False,
    "onlyTotalCount": False,
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/meta-ads-library-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": [
    "nike"
  ],
  "pageUrls": [],
  "startUrls": [],
  "country": "ALL",
  "adActiveStatus": "ALL",
  "adType": "ALL",
  "mediaType": "ALL",
  "publisherPlatforms": [],
  "languages": [],
  "dateFrom": "",
  "dateTo": "",
  "includeAboutPage": false,
  "scrapeAdDetails": false,
  "onlyTotalCount": false,
  "maxResults": 100
}' |
apify call solidcode/meta-ads-library-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,solidcode/meta-ads-library-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/jrcXYlbOAUukohvxa/builds/DwKUdLw2qK48agGoo/openapi.json
