# Facebook Ads Library Scraper - Meta Ads, All Countries (`eiv/meta-ads-library-scraper`) Actor

Scrape the Facebook Ads Library by keyword, Page or Ad Library link, in any country: ad copy, images and videos, landing pages, CTAs, run dates, platforms and the advertiser Page with its likes. Political ad spend included. No login, no token. From $0.50 per 1,000 ads.

- **URL**: https://apify.com/eiv/meta-ads-library-scraper.md
- **Developed by:** [Eimantas V](https://apify.com/eiv) (community)
- **Categories:** Social media, Lead generation, E-commerce
- **Features:** Limited permissions
- **Stats:** 459 total users, 11 monthly users, 99.6% runs succeeded, 3 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 ad scrapes

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

**Facebook Ads Library Scraper** pulls ads from Meta's Ad Library, the public archive of every ad running on **Facebook, Instagram, Messenger, WhatsApp and Threads**. Search by **keyword, Facebook Page or any Ad Library link**, in **any country**, and get each ad's copy, images and videos, landing page, call to action, run dates and advertiser Page. No login, no Facebook token, no browser, from **$0.50 per 1,000 ads**.

```
Sephora  ·  "The perfect ballet bun is just a trip to Sephora away."  ·  Shop now -> sephora.com
         ·  video ad, active 65 days, 3 ads share this creative  ·  Facebook, Instagram, Threads  ·  20.3M Page likes
```

**Benchmark: 300 ads from three advertisers' Pages in 37 seconds; 200 ads from a keyword and two Pages in 30 seconds.**

### What does Facebook Ads Library Scraper do?

It searches the Ad Library the way you would in your browser, then returns every matching ad as one clean row, ready for a spreadsheet, a swipe file or a competitor dashboard.

- **Every country and every ad.** Ordinary commercial ads in the US, UK, Canada, Australia and everywhere else, not only political ones or EU ones.
- **The full creative.** Ad text, headline, description, call to action, landing page, every image and video (HD), carousel cards and the ad's format.
- **What is working.** How many days each ad has run and how many ads share a creative: long-running, widely used creatives are the advertiser's winners.
- **The advertiser.** Page name, link, likes, categories and the platforms each ad runs on.
- **Political ads.** Spend and impressions ranges, currency and "paid for by", parsed into numbers.
- **Only pay for ads.** An input that cannot be read returns an error row and costs nothing; an ad two inputs both find is charged once.
- **Built for automation.** Schedules, API, webhooks, Make, Zapier, n8n, Google Sheets, and AI agents through Apify's MCP server.

### Why it is fast and cheap

It asks the Ad Library for its own search results directly, 10 ads per request, and never opens a browser. That is why it is quick and why it can charge a fraction of browser-based scrapers. Facebook only answers these searches from home-type internet addresses, so the Actor uses Apify's residential proxy automatically; that cost is included in the price.

### What data can you extract from the Facebook Ads Library?

| Field | Example | What it is |
|---|---|---|
| `advertiserName` | `Sephora` | The Facebook Page running the ad |
| `adText` | `The perfect ballet bun is just a trip to Sephora away.` | The ad copy (all versions, de-duplicated) |
| `headline`, `description` | `We get beauty.` | The link headline and description |
| `ctaText`, `ctaType` | `Shop now`, `SHOP_NOW` | The call-to-action button |
| `linkUrl` | `https://www.sephora.com/` | The landing page |
| `imageUrls`, `videoUrls` | `["https://video...fbcdn.net/..."]` | Every image and video of the ad (links expire after some days: download what you keep) |
| `cards` | `[{ "title": ..., "linkUrl": ..., "imageUrl": ... }]` | Each card of a carousel or dynamic ad |
| `displayFormat` | `VIDEO`, `IMAGE`, `CAROUSEL`, `DCO`, `DPA` | The ad's format (DCO = dynamic creative, DPA = catalogue ad) |
| `startDate`, `endDate`, `isActive`, `daysActive` | `2026-08-31`, `""`, `true`, `65` | When it ran and for how long |
| `collationCount` | `3` | Ads sharing this creative |
| `publisherPlatforms` | `["facebook", "instagram", "threads"]` | Where it runs |
| `pageLikeCount`, `pageCategories`, `advertiserPageUrl` | `20350560`, `["Health/beauty"]` | The advertiser's Page |
| `spend`, `impressions`, `currency`, `bylines` | `{ "lowerBound": "1500", "upperBound": "2000" }` | Political and issue ads only |
| `euTotalReach`, `targetAges`, `targetGender`, `ageCountryGenderReachBreakdown` | (EU ads) | EU reach and targeting (official API source only; null on website rows) |
| `snapshotUrl` | `https://www.facebook.com/ads/library/?id=1797454185033063` | The ad in the Ad Library |
| `inputQuery`, `source` | `https://www.facebook.com/sephora`, `website` | Which input found it, and where the data came from |

### How to scrape the Facebook Ads Library

1. Click **Try for free**. Under **Search keywords or Ad Library links**, enter keywords (one per line) or paste any Ad Library address from your browser. Under **Facebook Pages**, enter the advertisers you want to watch (`https://www.facebook.com/nike`, `Nike` or a Page id).
2. Pick **Countries** (all by default), and any filters: active or stopped ads, media type, platforms, languages, dates, sort order.
3. Set **Max ads**. You pay per ad, so this is also your cost cap. **Max ads per search or Page** keeps one big advertiser from using the whole run.
4. Click **Start**, then open the **Output** tab (views: Overview, Creatives, Advertisers, Political and EU data) or download CSV, Excel or JSON.

### How much does it cost to scrape the Facebook Ads Library?

You pay per ad returned, and the price drops on higher Apify plans:

| Apify plan | Per 1,000 ads |
|---|---|
| Free | $1.00 |
| Starter | $0.75 |
| Scale | $0.65 |
| Business | $0.50 |

- A competitor's 500 active ads on the Starter plan: **$0.38**.
- A weekly swipe file of 10,000 ads on the Business plan: **$5.00**.
- A run also costs **$0.00005** to start. Failed inputs and duplicate ads cost nothing.
- The Free plan's $5 monthly credit covers about **5,000 ads**.
- Count-only mode (how many ads match, without the ads) costs $0.02 per input.

### Input

```json
{
    "searchQueries": ["running shoes", "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=protein%20bar"],
    "pageUrls": ["https://www.facebook.com/sephora", "Gymshark"],
    "countries": ["US"],
    "activeStatus": "ACTIVE",
    "sortBy": "IMPRESSIONS",
    "maxResults": 500,
    "maxResultsPerQuery": 100
}
```

| Field | Default | Notes |
|---|---|---|
| Search keywords or Ad Library links | | Keywords, Ad Library search links, Page links (`view_all_page_id=`) or single ads (`?id=`). A link's own filters win |
| Facebook Pages | | Page address, name or id: every ad the Page runs or ran |
| Ad Library URLs (other scrapers' format) | | `startUrls` from other Ad Library scrapers, run unchanged |
| Countries | All | One or more countries where the ads were shown |
| Active status | Active and inactive | Running now, stopped, or both |
| Ad category | All ads | Political and issue, housing, employment, credit |
| Keyword match | Unordered | Or exact phrase |
| Media type | All | Images, videos, memes, none |
| Platforms, Languages | All | Facebook, Instagram, Messenger, WhatsApp, Threads, Audience Network |
| Shown from / until | | Only ads shown in this date range |
| Sort by | Ad Library default | Total impressions, or most recent first |
| Max ads | 50 | Your cost cap |
| Max ads per search or Page | 0 (none) | Per-input cap |
| Only count ads | off | Counts instead of ads (official API) |
| Data source | Ad Library website | Or the official API, for EU reach and targeting (ordinary ads only for EU countries) |

### Output

Each ad is one row:

```json
{
    "adArchiveId": "1797454185033063",
    "advertiserName": "Sephora",
    "advertiserPageId": "16453004404",
    "advertiserPageUrl": "https://www.facebook.com/sephora/",
    "adText": "The perfect ballet bun is just a trip to Sephora away.",
    "headline": "We get beauty.",
    "ctaText": "Shop now",
    "ctaType": "SHOP_NOW",
    "linkUrl": "https://www.sephora.com/",
    "displayFormat": "DCO",
    "imageUrls": [],
    "videoUrls": ["https://video-phx1-1.xx.fbcdn.net/o1/v/t2/f2/m366/AQOy3VIXrmfzpJHF8wd9..."],
    "publisherPlatforms": ["facebook", "instagram", "threads"],
    "startDate": "2026-08-31",
    "endDate": "",
    "isActive": true,
    "daysActive": 65,
    "collationCount": 3,
    "pageLikeCount": 20350560,
    "pageCategories": ["Health/beauty"],
    "spend": null,
    "impressions": null,
    "snapshotUrl": "https://www.facebook.com/ads/library/?id=1797454185033063",
    "source": "website",
    "inputQuery": "https://www.facebook.com/sephora"
}
```

A political ad adds its ranges, e.g. `"spend": { "lowerBound": "1500", "upperBound": "2000" }, "impressions": { "lowerBound": "100000", "upperBound": "125000" }, "currency": "USD", "bylines": "Swamp Fox Solutions"`.

An input that cannot be read becomes a row with `query` and `error` (never charged), e.g. a Page name the Ad Library does not know, or an Ad Library link with no search in it.

### Tips and limits

- **Find a competitor's best ads**: their Page, **Active** only, **Sort by: Total impressions**, then sort the dataset by `daysActive`.
- **Monitor new ads**: schedule a daily run with **Sort by: Most recent** and a small **Max ads**.
- **Spend is published only for political and issue ads.** Meta does not publish what ordinary advertisers spend, so `spend` is null for them on every tool.
- **EU reach and targeting** (reach, age and gender breakdowns) come from Meta's official API: choose it as the data source; it returns ordinary ads only for EU countries.
- **Media links expire.** Meta's image and video links stop working after some days; download the files you want to keep.
- **Hit your spending limit?** The run stops cleanly at your maximum cost per run and keeps everything it collected.

### FAQ

#### Is it legal to scrape the Facebook Ads Library?

The Ad Library is a public transparency archive that Meta publishes for anyone to search without logging in, and this Actor reads only what it shows logged out. Meta's terms restrict automated collection and reuse of its data, and ads can contain personal data protected by laws such as the GDPR. Use the results for research and analysis, do not resell them as a dataset, and ask a lawyer if you are unsure. Facebook and Meta are trademarks of Meta Platforms, Inc.; this Actor is not affiliated with or endorsed by Meta.

#### Can I use it through the API or with Make, Zapier and n8n?

Yes. Every run can be started through the [Apify API](https://docs.apify.com/api/v2) and returns the dataset as JSON, CSV or Excel. Schedules, webhooks and integrations for Make, Zapier, n8n and Google Sheets are on the **Integrations** tab.

#### Can AI agents use it?

Yes. Agents connected to [Apify's MCP server](https://mcp.apify.com) can find and run this Actor as a tool ("what ads is Gymshark running in the UK?"), with the same per-ad pricing.

#### Why did I get fewer ads than I asked for?

The search or Page has fewer matching ads, the run reached **Max ads per search or Page**, your maximum cost per run, or its timeout. The log says which, and everything collected before that is kept.

### Related scrapers

- [TikTok Ads Library Scraper](https://apify.com/eiv/tiktok-ad-library-scraper): the same research for TikTok ads.
- [Google Ads Transparency Scraper](https://apify.com/eiv/google-ads-transparency-scraper): an advertiser's Google Search, YouTube and Display ads.
- [LinkedIn Ad Library Scraper](https://apify.com/eiv/linkedin-ad-library-scraper): B2B ads on LinkedIn.
- [Facebook Pages Scraper](https://apify.com/eiv/facebook-pages-scraper): contact details, followers and ratings of the advertisers you find.

### Support

Missing a field, or found an Ad Library link that does not work? Open an issue on the **Issues** tab with the input you used, and it will be looked at quickly.

# Actor input Schema

## `searchQueries` (type: `array`):

One per line: a keyword (e.g. running shoes) or any Ad Library address copied from your browser: a search with filters, a Page's ads (view_all_page_id=) or a single ad (?id=). Filters in a link override the ones below.

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

Advertisers whose ads you want: a Page address (https://www.facebook.com/nike), its name (Nike) or its Page id. Every ad the Page runs or ran is returned, filtered by the options below.

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

The same as the first field, in the URL-list format other Ad Library scrapers use, so their saved inputs run unchanged. Use either field.

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

Where the ads were shown. All countries by default. Pick one or more to narrow it, e.g. US. (The official API source below returns ordinary ads only for EU countries.)

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

Running now, stopped, or both. An Ad Library link's own setting wins.

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

All ads for competitor research. Political and issue ads add the spend and impressions ranges Meta publishes for them (null on ordinary ads: Meta does not publish what other advertisers spend).

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

Unordered finds ads with all the words in any order; exact phrase only that phrase.

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

Only ads with images, videos, memes, or no media.

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

Only ads shown on these Meta platforms. Empty = all.

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

Only ads in these languages. Empty = all.

## `adDeliveryDateMin` (type: `string`):

Only ads shown on or after this date (YYYY-MM-DD).

## `adDeliveryDateMax` (type: `string`):

Only ads shown on or before this date (YYYY-MM-DD).

## `sortBy` (type: `string`):

The Ad Library's order: total impressions (its default, the ads seen most first) or most recent. With a low limit this decides which ads you get.

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

Total ads for the whole run, across all inputs. You pay per ad, so this is also your cost cap.

## `maxResultsPerQuery` (type: `integer`):

Stop each keyword, link or Page after this many ads, so one big advertiser cannot use the whole run. 0 = no limit per input.

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

Return how many ads match each input instead of the ads (official API; counts EU and political ads only). Charged per count, not per ad.

## `dataSource` (type: `string`):

Ad Library website (default): every country, ordinary and political ads, images, videos, landing pages. Official API: Meta's API, ordinary ads only if they ran in the EU, but adds EU reach, age/gender targeting and reach breakdowns.

## `proxyConfig` (type: `object`):

Not needed: the website source uses Apify residential addresses automatically (included in the price). Add your own proxy URLs only if you want them used instead.

## Actor input object example

```json
{
  "searchQueries": [
    "Loop Earplugs"
  ],
  "pageUrls": [
    "https://facebook.com/Nike"
  ],
  "countries": [
    "ALL"
  ],
  "activeStatus": "ALL",
  "adType": "ALL",
  "searchType": "KEYWORD_UNORDERED",
  "mediaType": "ALL",
  "publisherPlatforms": [],
  "languages": [],
  "sortBy": "RELEVANCE",
  "maxResults": 50,
  "maxResultsPerQuery": 0,
  "onlyTotalCount": false,
  "dataSource": "website",
  "proxyConfig": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Every ad, key columns first.

## `creatives` (type: `string`):

Images, videos, headline, CTA and landing page of each ad.

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

Ads collected, failed inputs, requests and why the run stopped.

# 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 = {
    "searchQueries": [
        "Loop Earplugs"
    ],
    "pageUrls": [
        "https://facebook.com/Nike"
    ],
    "countries": [
        "ALL"
    ],
    "proxyConfig": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("eiv/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 = {
    "searchQueries": ["Loop Earplugs"],
    "pageUrls": ["https://facebook.com/Nike"],
    "countries": ["ALL"],
    "proxyConfig": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("eiv/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 '{
  "searchQueries": [
    "Loop Earplugs"
  ],
  "pageUrls": [
    "https://facebook.com/Nike"
  ],
  "countries": [
    "ALL"
  ],
  "proxyConfig": {
    "useApifyProxy": false
  }
}' |
apify call eiv/meta-ads-library-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,eiv/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/7utCWNseUb44VvYu3/builds/8IvR4Vd9XAomB4Ggt/openapi.json
