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

Scrapes ads from the Facebook Ad Library for any keyword or advertiser: ad text, images, videos, run dates, platforms and page details. Paste any Ad Library link and every filter in it is kept.

- **URL**: https://apify.com/mina_safwat/facebook-ads-library-scraper.md
- **Developed by:** [Mina](https://apify.com/mina_safwat) (community)
- **Categories:** Social media, Marketing, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 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

**Scrape the Facebook Ad Library by keyword or advertiser.** Paste any link from the [Meta Ad Library](https://www.facebook.com/ads/library/) and get every ad behind it as clean, structured data: **ad text, headline, call to action, landing page, image and video URLs, carousel cards, run dates, days active, platforms and advertiser details**. Every filter you set in the Ad Library (country, active status, ad category, media type, platform, language, dates) is kept automatically.

### What does Facebook Ads Library Scraper do?

Facebook Ads Library Scraper collects ads from Meta's public Ad Library, the transparency archive of ads running on Facebook, Instagram, Messenger, WhatsApp, Threads and the Audience Network. It works from the links you already use:

- **Keyword searches**: every ad that mentions a word or phrase, for example all active "coffee" ads in the US.
- **Advertiser pages**: the complete ad library of one brand or competitor, for example every ad Nike has run.

It runs on the Apify platform, so you get API access, scheduling, integrations (Make, Zapier, Google Sheets, webhooks), run monitoring and exports to JSON, CSV, Excel or HTML, all without any login, cookies or Facebook account.

### Why use Facebook Ads Library Scraper?

- **Competitor research**: see every creative a competitor is running, how long each ad has been live and which platforms it is on. Ads that run for months are usually the ones that work.
- **Creative inspiration**: collect hooks, headlines, calls to action and video creatives across a whole niche in minutes.
- **Market monitoring**: schedule a weekly run on a keyword or a list of advertisers and track new launches.
- **Agency reporting**: export a brand's full ad history to a spreadsheet for audits and pitches.
- **Research and journalism**: political and issue ads come with the spend and impression ranges Meta publishes.

### How to scrape the Facebook Ad Library

1. Open the [Facebook Ad Library](https://www.facebook.com/ads/library/) in your browser.
2. Pick a country and ad category, then search for a keyword or choose an advertiser from the suggestions.
3. Set any filters you want (active or inactive ads, media type, platform, language, date range).
4. Copy the address from your browser's address bar.
5. Paste it into **Ad Library links**, add more links if you like, and click **Start**.
6. Download your ads from the **Output** tab when the run finishes.

### Input

| Field | What it does |
|---|---|
| **Ad Library links** (`startUrls`) | One or more Ad Library links, either keyword searches or advertiser pages. Filters in the link are kept. |
| **Max ads per link** (`maxAdsPerUrl`) | Stops after this many ads for each link. Defaults to 200. |
| **Proxy** (`proxyConfiguration`) | Keep the default Apify residential proxy. Without it Facebook stops after the first 30 ads of each link. |

Example input:

```json
{
    "startUrls": [
        { "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&media_type=all&q=coffee&search_type=keyword_unordered" },
        { "url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=ALL&media_type=all&search_type=page&view_all_page_id=15087023444" }
    ],
    "maxAdsPerUrl": 200
}
```

Links that are not Ad Library searches (a Facebook page, a single-ad link, a link without a keyword or advertiser) are skipped and listed with the reason in the `FAILED_INPUTS` record of the run's key-value store. You are never charged for them.

### Output

Each ad is one row. You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

```json
{
    "adArchiveId": "1520310666349109",
    "adLibraryUrl": "https://www.facebook.com/ads/library/?id=1520310666349109",
    "pageId": "15087023444",
    "pageName": "Nike",
    "pageProfileUrl": "https://www.facebook.com/nike/",
    "pageProfilePictureUrl": "https://scontent.xx.fbcdn.net/v/t39.35426-6/683200075_n.jpg?...",
    "pageLikeCount": 39511262,
    "pageCategories": ["Sportswear"],
    "isActive": false,
    "startDate": "2026-04-29",
    "endDate": "2026-05-25",
    "activeDays": 27,
    "platforms": ["FACEBOOK", "INSTAGRAM"],
    "spend": null,
    "impressions": null,
    "displayFormat": "IMAGE",
    "bodyText": "Add a retro touch to any fit.",
    "title": "Find Nike Near You",
    "caption": "nike.com",
    "linkDescription": "Shop Nike",
    "ctaText": "Shop now",
    "ctaType": "SHOP_NOW",
    "linkUrl": "https://www.nike.com/w/womens-summer-essentials-lifestyle-13jrmz5e1x6z6pei9",
    "images": ["https://scontent.xx.fbcdn.net/v/t39.35426-6/680632406_n.jpg?..."],
    "videos": [],
    "cards": [],
    "collationCount": 3,
    "position": 23,
    "searchTotal": 14752,
    "inputUrl": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=ALL&media_type=all&search_type=page&view_all_page_id=15087023444"
}
```

The Output tab has three views: **Ads** (text, dates, platforms, landing page), **Creatives** (images, videos, carousel cards) and **Advertisers** (page name, likes, categories).

### Data fields

| Field | Description |
|---|---|
| `adArchiveId` | The ad's ID in the Ad Library |
| `adLibraryUrl` | Link to the ad in the Ad Library |
| `pageId`, `pageName` | The advertiser's Facebook page |
| `pageProfileUrl`, `pageProfilePictureUrl` | Advertiser page link and profile picture |
| `pageLikeCount`, `pageCategories` | Advertiser page likes and categories |
| `isActive` | Whether the ad is running now |
| `startDate`, `endDate` | First and last day the ad ran, as Meta reports them (for most active ads the last day is today) |
| `activeDays` | Calendar days the ad has run, counting the first and last day |
| `platforms` | Where the ad runs: FACEBOOK, INSTAGRAM, MESSENGER, WHATSAPP, THREADS, AUDIENCE_NETWORK |
| `spend`, `impressions` | Spend and impression ranges, published by Meta for political and issue ads only |
| `displayFormat` | IMAGE, VIDEO, CAROUSEL, DPA (catalog), DCO (dynamic creative) and so on |
| `bodyText`, `title`, `caption`, `linkDescription` | The ad's copy |
| `ctaText`, `ctaType` | The call-to-action button |
| `linkUrl` | The landing page |
| `images` | Image URLs |
| `videos` | Video URLs: `hdUrl`, `sdUrl` and `previewUrl` |
| `cards` | Carousel and catalog cards, each with its own title, text, link, button and media |
| `collationCount` | How many versions of this ad share the same creative |
| `position` | The ad's position in the search results |
| `searchTotal` | How many ads match the search, as the Ad Library counts them (50,001 means more than 50,000) |
| `inputUrl` | The link the ad was found through |

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

The Actor uses pay-per-event pricing: you pay a small fee for each ad saved to the dataset (see the **Pricing** tab), and nothing for links that return no ads. It needs no browser and runs on 512 MB of memory, so platform usage stays very low. A run with the prefilled input (two links, 20 ads each) finishes in well under a minute.

You can cap the cost of any run with **Maximum cost per run** in the run options: the Actor stops cleanly as soon as the limit is reached and keeps everything collected so far.

### Tips for scraping the Ad Library

- **Filter in the Ad Library, not afterwards.** Country, active status, media type, platform and date filters cut the result set before you pay for it.
- **Use advertiser links for competitor tracking.** A keyword search returns ads that mention the word; an advertiser link returns everything that page has run.
- **Exact phrases**: put the keyword in quotes in the Ad Library search box to get `search_type=keyword_exact_phrase` links.
- **Catalog ads**: catalog (DPA) and dynamic (DCO) ads often show template text such as `{{product.name}}` in their headline; the real product names, prices and links are in `cards`.
- **Media links expire.** Image and video URLs are signed by Facebook and stop working after a few days, so download any creatives you want to keep soon after the run.
- **Schedule it.** Run the same links weekly and compare `adArchiveId`s to spot new ads.

### FAQ, disclaimers and support

**Do I need a Facebook account or cookies?** No. The Ad Library is public, and the Actor reads it without logging in.

**How many ads can I get?** Up to the number the Ad Library shows for your search. Facebook serves the first 30 ads and then 10 at a time, so large libraries take longer.

**Why did I get only 30 ads per link?** The proxy was turned off or set to data-center addresses. Facebook serves those the first 30 ads of a search and refuses the rest, so keep the default residential proxy.

**Which ads does a link without an ad category return?** All ads: the Ad Library now defaults to "All ads". For political and issue ads only, with their spend and impression ranges, pick that category in the Ad Library before copying the link.

**Why is `searchTotal` 50,001?** The Ad Library stops counting at 50,000 and shows "50,000+" for bigger result sets.

**Does it include the reach and demographic breakdown of EU ads?** Not yet. It returns everything shown on the ad cards in the search results.

**Is it legal to scrape the Facebook Ad Library?** The Ad Library is a public transparency archive that Meta publishes so anyone can inspect ads. This Actor only reads publicly available information and does not collect private user data. You are responsible for how you use the data: check Meta's terms and the laws that apply to you (such as GDPR) before using it, especially for personal data or political ads. If in doubt, ask a lawyer.

**Something is not working or you need a custom field?** Open an issue on the **Issues** tab and we will look into it. Custom scraping solutions are available on request.

# Actor input Schema

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

Links copied from the Facebook Ad Library, one per line. Search for a keyword, or pick an advertiser to see all of its ads, set whatever filters you want (country, active or inactive, ad category, media type, platform, language, dates), then copy the address bar. Every filter in the link is honoured. Links that are not Ad Library searches are skipped and listed in the FAILED_INPUTS record.

## `maxAdsPerUrl` (type: `integer`):

Stops after this many ads for each link. Facebook serves the first 30 ads, then 10 at a time; raise this to collect an advertiser's whole library.

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

Keep Apify's residential proxy on. Facebook stops data-center addresses after the first 30 ads of each search, and a page it turns away is retried from a fresh residential address.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&media_type=all&q=coffee&search_type=keyword_unordered"
    },
    {
      "url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=ALL&media_type=all&search_type=page&view_all_page_id=15087023444"
    }
  ],
  "maxAdsPerUrl": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "startUrls": [
        {
            "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&media_type=all&q=coffee&search_type=keyword_unordered"
        },
        {
            "url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=ALL&media_type=all&search_type=page&view_all_page_id=15087023444"
        }
    ],
    "maxAdsPerUrl": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("mina_safwat/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 = {
    "startUrls": [
        { "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&media_type=all&q=coffee&search_type=keyword_unordered" },
        { "url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=ALL&media_type=all&search_type=page&view_all_page_id=15087023444" },
    ],
    "maxAdsPerUrl": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("mina_safwat/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 '{
  "startUrls": [
    {
      "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&media_type=all&q=coffee&search_type=keyword_unordered"
    },
    {
      "url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=ALL&media_type=all&search_type=page&view_all_page_id=15087023444"
    }
  ],
  "maxAdsPerUrl": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call mina_safwat/facebook-ads-library-scraper --silent --output-dataset

```

## MCP server setup

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