# Facebook Ads Library Scraper (`alkausari_mujahid/facebook-ads-library-scraper`) Actor

Scrape the Meta (Facebook & Instagram) Ad Library by keyword, Facebook Page or Ad Library URL. Get every ad's text, images, videos, dates, platforms and advertiser.

- **URL**: https://apify.com/alkausari_mujahid/facebook-ads-library-scraper.md
- **Developed by:** [Alkausari M](https://apify.com/alkausari_mujahid) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 ads

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

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

**Facebook Ads Library Scraper** extracts ads from the [Meta Ad Library](https://www.facebook.com/ads/library/) — Facebook, Instagram, Messenger, Threads and Audience Network — with no account, API key or browser needed. One Actor covers five jobs:

- 🔎 **Search by keyword** — every ad that mentions a brand, product or topic, in any country, with all the website's filters: status, category, media type, platforms, languages, dates and sort order.
- 🏢 **All ads of an advertiser** — paste a Facebook Page link, username or page ID and get every ad that Page is running.
- 🖼️ **Images and videos that keep working** — Facebook's media links expire after about 4 days. Turn on **Save images and videos** and every file is copied to your storage with a permanent link.
- 🇪🇺 **Who paid, who was targeted, how many people saw it** — EU and UK reach broken down by country, age and gender, the payer and beneficiary, targeted locations, ages and gender, plus the advertiser's Instagram username, followers and verification.
- 🔔 **Only new ads, every day** — schedule the Actor and it saves only the ads it hasn't seen before, so each run brings you just what's new.

Paste keywords, Pages and Ad Library links — or mix them in one run. The first ads arrive within seconds, a search runs at about 250 ads a minute, and results export to CSV, Excel or JSON, or flow into Google Sheets, Zapier and Make.

### Use cases

- 🕵️ **Competitor research** — see every ad a competitor runs: the copy, creatives, landing pages, offers, and how long each ad has been live
- 💡 **Creative inspiration** — collect winning ads in your niche; the longest-running ads are usually the ones that work
- 📇 **Lead generation** — find businesses that are actively spending on ads, with their Page, website, Instagram account and follower count
- 🗳️ **Political and issue ad research** — spending ranges, impressions and "paid for by" disclaimers for political ads
- 🛡️ **Brand protection** — catch ads that misuse your brand name or copy your products

### What you get

|                                        | For each ad                                                                                                       |
| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| 📝 **The ad**                          | Text, headline, link caption, button, landing page, and every card of carousel and catalog ads                    |
| 🖼️ **Creatives**                       | Image links, video links (HD and SD) and preview images — or permanent copies of the files                        |
| 📅 **Timing**                          | Start date, end date for finished ads, days running, active or not                                                |
| 📣 **Where it ran**                    | Facebook, Instagram, Messenger, Threads, Audience Network                                                         |
| 🏢 **Advertiser**                      | Page name, link, ID, likes, categories and profile picture                                                        |
| 🧬 **Versions**                        | How many versions of the ad Facebook grouped together                                                             |
| 🗳️ **Political ads**                   | Spend range, impressions, currency and "paid for by" disclaimer                                                   |
| 🇪🇺 **Transparency** *(optional)*       | EU and UK reach by country, age and gender; payer and beneficiary; targeted locations, ages and gender            |
| 📸 **Advertiser profile** *(optional)* | Instagram username, followers and verification; Facebook likes, category and verification badge; Page description |

### How to run the Actor

1. Click **Try for free**.
2. Type **Keywords**, paste **Facebook Pages**, or paste **Ad Library URLs** — or all three.
3. Pick the **Country** and other filters, and set **Max ads per search**.
4. Press **Start**, then open the **Output** tab and export.

Here is what each kind of input gives you:

| Paste                                                            | You get                                                             |
| ---------------------------------------------------------------- | ------------------------------------------------------------------- |
| **Keyword** (`running shoes`)                                    | Ads that contain the words, filtered by the settings you pick       |
| **Facebook Page** (`facebook.com/nike`, `nike` or `15087023444`) | Every ad that Page runs                                             |
| **Ad Library search URL**                                        | Exactly what that search shows on the website, with its own filters |
| **Single-ad link** (`…/ads/library/?id=123…`)                    | That one ad                                                         |

The easiest way to get a complex search right: set it up on [facebook.com/ads/library](https://www.facebook.com/ads/library/), then copy the URL from your browser into **Ad Library URLs**.

### Input

| Setting                                          | What it does                                                       | Default       |
| ------------------------------------------------ | ------------------------------------------------------------------ | ------------- |
| **Keywords**                                     | Words or phrases to search for, one search each                    | —             |
| **Facebook Pages**                               | Page links, usernames or page IDs — all their ads                  | —             |
| **Ad Library URLs**                              | Searches or single ads copied from the Ad Library website          | —             |
| **Max ads per search**                           | Ads to save for each keyword, Page or URL (`0` = all)              | `100`         |
| **Country**                                      | Only ads shown in this country                                     | All countries |
| **Ad status**                                    | Active ads, inactive ads, or both                                  | Active        |
| **Ad category**                                  | All ads, or political/issue, housing, employment or financial ads  | All           |
| **Keyword match**                                | Any of the words, or the exact phrase                              | Any words     |
| **Media type**                                   | Images, memes, videos, or ads without either                       | All           |
| **Platforms**                                    | Only ads that ran on these platforms                               | All           |
| **Ad languages**                                 | Only ads in these languages (`en`, `es`, `de`…)                    | All           |
| **Shown from / until**                           | Only ads shown between these dates                                 | —             |
| **Sort by**                                      | Relevance, newest first, or most impressions                       | Relevance     |
| **Only new ads**                                 | Skip ads this search returned in earlier runs                      | Off           |
| **Save images and videos**                       | Copy the creatives to storage with permanent links                 | Off           |
| **Include EU ad details and advertiser profile** | Reach, targeting, payer and the advertiser's Instagram for each ad | Off           |
| **Proxy**                                        | Keep Apify residential proxy                                       | Residential   |

The filters apply to keywords and Pages. Ad Library URLs keep the filters already in the URL.

#### Example input

```json
{
    "searchQueries": ["running shoes", "protein powder"],
    "pages": ["https://www.facebook.com/nike"],
    "country": "US",
    "activeStatus": "active",
    "sortBy": "newest",
    "maxAdsPerSearch": 200
}
```

### Output

One row per ad, with three ready-made views on the Output tab: **Ads** (with a preview of each creative), **EU details & advertiser**, and **Saved media**. Here is a real record from a keyword search in Germany with EU details on, shortened:

```json
{
    "adArchiveId": "2255540481904788",
    "adLibraryUrl": "https://www.facebook.com/ads/library/?id=2255540481904788",
    "isActive": true,
    "startDate": "2026-07-31",
    "daysRunning": 95,
    "pageName": "Senior Health Insider",
    "pageLikeCount": 11463,
    "publisherPlatforms": ["FACEBOOK", "INSTAGRAM"],
    "displayFormat": "IMAGE",
    "title": "Buy 1, Get 2 FREE",
    "body": "I came to America for one reason, says Chen Wei, founder of…",
    "caption": "trybronoir.com",
    "linkUrl": "https://trybronoir.com/pages/chen-10-reasons-people-over-50-feet-b1g2",
    "ctaText": "Shop now",
    "imageUrls": ["https://scontent-iad3-1.xx.fbcdn.net/v/t39.35426-6/759975836…"],
    "versionsCount": 3,
    "sourceInput": "sneakers",
    "adDetails": {
        "euTotalReach": 13969,
        "targetLocations": [
            { "name": "Ireland", "type": "countries" },
            { "name": "Italy", "type": "countries" }
        ],
        "targetGender": "All",
        "targetAgeMin": 18,
        "targetAgeMax": 65,
        "reachByCountryAgeGender": [{ "country": "BE", "ageRange": "55-64", "male": 39, "female": 86, "unknown": 2 }],
        "payers": [{ "payer": "Bronoir LLC", "beneficiary": "Bronoir LLC" }],
        "uk": { "totalReach": 8022, "targetGender": "All", "targetAgeMin": 18, "targetAgeMax": 65 },
        "advertiser": { "category": "Clothing store", "facebookLikes": 11463, "facebookVerification": "NOT_VERIFIED" }
    }
}
```

With **Save images and videos** on, each ad also lists its stored files:

```json
"mediaFiles": [
    {
        "type": "image",
        "sourceUrl": "https://scontent-iad3-2.xx.fbcdn.net/v/t39.35426-6/700927950…",
        "url": "https://api.apify.com/v2/key-value-stores/weuGi9waaHoWNL64z/records/ad-1550534860016399-1.jpg"
    }
]
```

Every record in a run carries the same columns, left empty where an ad doesn't have something — so Zapier, Make and Sheets can map them from a single sample.

### Pricing

You pay per ad saved, so the bill is simply how many ads you asked for:

| Ads    | Ads only | With saved media *or* EU details | With both |
| ------ | -------- | -------------------------------- | --------- |
| 100    | $0.15    | $0.35                            | $0.55     |
| 1,000  | $1.50    | $3.50                            | $5.50     |
| 10,000 | $15.00   | $35.00                           | $55.00    |

**Save images and videos** adds $2.00 per 1,000 ads, however many files each ad has, and **EU ad details and advertiser profile** adds $2.00 per 1,000 ads. **Ads whose files couldn't be saved, or whose details Facebook doesn't return, aren't charged the extra.** An ad found by two of your searches in the same run is charged once, and with **Only new ads** on, ads seen in earlier runs are never charged again.

Set a **Maximum cost per run** in the run options and the Actor works out how many ads that pays for, then stops there — it never fetches ads you won't be billed for.

### Getting past Facebook's 2,500-ad limit

**The Ad Library shows at most about 2,500 ads for any one search**, even when it says 20,000 match. The Actor notices when Facebook stops giving new ads and ends that search, so you never pay for repeats. To get more, split a big search into smaller ones — each gets its own 2,500:

| Split by       | Example                                                      |
| -------------- | ------------------------------------------------------------ |
| **Country**    | The same keyword once for `US`, once for `GB`, once for `DE` |
| **Date range** | One search per month with **Shown from / until**             |
| **Media type** | One search for images, one for videos                        |
| **Language**   | One search per ad language                                   |

An ad that turns up in two of your searches is saved once per run.

### Integrations & scheduling

Results don't have to stay on Apify. Without writing any code you can:

- **Send ads to Google Sheets, Airtable or Slack** — pick the integration on the Actor's Integrations tab and every run appends its results automatically.
- **Connect anything else via Zapier or Make** — thousands of apps, triggered when a run finishes.
- **Fire a webhook** to your own server the moment a run completes, with a link to the fresh dataset.
- **Pull the data over the API** in JSON, CSV, Excel or XML — one URL, ideal for a script or notebook.

**Track competitors on autopilot.** Put their Pages into **Facebook Pages**, turn on **Only new ads**, set **Sort by** to **Newest first**, and schedule the Actor daily. Each run saves just the ads that appeared since the last one — send them to Slack or a sheet and you have a competitor ad alert with no code at all.

### Tips

- For **EU reach and targeting**, pick an EU country. With "All countries", most ads come from outside the EU, where Facebook doesn't publish them.
- For **inactive ads**, also pick an EU country: Facebook keeps inactive ads only for political/issue ads everywhere, and for any ad shown in the EU (for one year).
- **Newest first** sorting finds fresh ads fastest and works best with **Only new ads**.
- **Most impressions** sorting surfaces the ads seen by the most people.

### Good to know

- **Residential proxy** — Facebook refuses ad results to datacenter IPs. Without residential proxy, each search stops after the first ~30 ads, which come with the page itself.
- **Ad counts** — the number Facebook shows for a search counts every version of every ad. Results group the versions together, so a search can return fewer rows than its count; **versionsCount** says how many versions each row stands for.
- **Catalog ads** — dynamic product ads (format `DPA`) use templates such as `{{product.name}}` in their text; the products themselves are in the cards.
- **Dates** — start and end dates are Ad Library dates in US Pacific time, as on the website. Active ads have no end date.
- **Only new ads** — the first run saves everything up to **Max ads per search** and remembers it; later runs save only ads it hasn't seen. Each keyword, Page and filter combination is remembered separately.
- **Political ads** — spend, impressions and disclaimers are filled for political and issue ads only; Facebook doesn't publish them for other ads.

### 📮 Support

Bugs, feature requests, or custom scraping work — open an issue on Apify, email alkausarimujahid@gmail.com, or visit my website [ayzalsoft.com](https://ayzalsoft.com).

# Actor input Schema

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

Words or phrases to search the Ad Library for, one per line — brand names, products, topics. Each keyword is a separate search.

## `pages` (type: `array`):

Get all ads of these advertisers. Paste a Facebook Page URL (facebook.com/nike), a username (nike) or a page ID (15087023444), one per line.

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

Paste searches straight from facebook.com/ads/library — set the filters on the website, then copy the URL. The URL's own filters are used. A single-ad link (…/ads/library/?id=123) returns that ad.

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

How many ads to save for each keyword, Page or URL. Set 0 to get every ad Facebook shows.

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

Only ads shown in this country. "All countries" searches everywhere. Used for keywords and Pages; Ad Library URLs keep their own country.

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

Active ads are running now. Inactive ads are kept by Facebook only for political/issue ads, and for ads shown in the EU (for one year).

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

Limit to one of Facebook's special ad categories.

## `keywordMatch` (type: `string`):

"Any words" finds ads containing all the words in any order. "Exact phrase" finds the exact phrase only.

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

Only ads with this kind of creative.

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

Only ads that ran on these platforms. Leave empty for all.

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

Only ads in these languages, as two-letter codes (en, es, de…). Leave empty for all.

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

Only ads that were shown on or after this date.

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

Only ads that were shown on or before this date.

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

"Relevance" is the Ad Library's default order. "Newest first" shows the most recently started ads first — best with "Only new ads". "Most impressions" puts the ads seen by the most people first.

## `onlyNewAds` (type: `boolean`):

Save only ads this search hasn't returned in earlier runs. Schedule the Actor (e.g. daily) to get just the new ads each time. Works best with "Sort by: Newest first". The first run saves everything up to the limit.

## `saveMedia` (type: `string`):

Facebook's image and video links expire after about 4 days. Turn this on to copy the files to the run's storage, with permanent links in the mediaFiles field.

## `includeAdDetails` (type: `boolean`):

For each ad, also get the Ad Library's transparency panel: who paid for it, who it targeted (locations, gender, ages), EU reach by country, age and gender, plus the advertiser's Instagram username, followers and verification. One extra request per ad, so runs take longer. EU reach and targeting exist only for ads shown in the EU.

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

Add the complete, unprocessed ad object from Facebook under the raw field.

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

Keep Apify residential proxy. Facebook refuses ad results to datacenter IPs, so without residential each search stops after its first ~30 ads. Pages still load directly to keep proxy traffic low.

## Actor input object example

```json
{
  "searchQueries": [
    "running shoes"
  ],
  "pages": [],
  "startUrls": [],
  "maxAdsPerSearch": 100,
  "country": "ALL",
  "activeStatus": "active",
  "adType": "all",
  "keywordMatch": "any",
  "mediaType": "all",
  "platforms": [],
  "languages": [],
  "sortBy": "relevance",
  "onlyNewAds": false,
  "saveMedia": "none",
  "includeAdDetails": false,
  "includeRawData": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

No description

## `files` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQueries": [
        "running shoes"
    ],
    "pages": [],
    "startUrls": [],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("alkausari_mujahid/facebook-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": ["running shoes"],
    "pages": [],
    "startUrls": [],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("alkausari_mujahid/facebook-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": [
    "running shoes"
  ],
  "pages": [],
  "startUrls": [],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call alkausari_mujahid/facebook-ads-library-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,alkausari_mujahid/facebook-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/iIwgtfj1yJYRQx18E/builds/2E7JHiuK6KZ6TMvAr/openapi.json
