# Facebook Ad Library Scraper (`thescrappa/facebook-ad-library-scraper`) Actor

Scrape Facebook and Instagram ads from the Meta Ad Library with advertiser, ad copy, call to action, landing page, dates, platforms and video links. Search by keyword, advertiser name or page ID, run many searches at once and page through results. No login needed.

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

## Pricing

from $0.30 / 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.
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 Ad Library Scraper

Search the public Meta Ad Library for Facebook and Instagram ads by keyword, advertiser name or Facebook page ID. Each ad comes back as one row with the advertiser, ad copy, call to action, landing page, start and stop dates, platforms, video links and a direct Ad Library link. Run many searches at once to watch competitors, collect creative ideas or check who advertises on a topic.

### What data can you extract?

| Field | Type | Description |
| --- | --- | --- |
| `ad_archive_id` | String | Meta Ad Library ID of the ad. Ads are unique by this ID in one run. |
| `ad_library_url` | String | Link that opens the ad in the public Meta Ad Library, for example `https://www.facebook.com/ads/library/?id=866569929827744`. Use it to see the image creative. |
| `page_id`, `page_name` | String | Facebook page ID and name of the advertiser. |
| `page_profile_uri`, `page_profile_picture_url` | String | Link to the advertiser's Facebook page and its profile picture. |
| `page_like_count` | Integer | Number of likes of the advertiser's page. |
| `page_categories` | Array | Page categories, for example "Shoe shop" or "Retail company". |
| `page_is_deleted` | Boolean | True when the advertiser's page no longer exists. |
| `is_active` | Boolean | True when Meta lists the ad as running. |
| `ad_delivery_start_time`, `ad_delivery_stop_time` | String | ISO 8601 date and time the ad started and stopped (or is planned to stop). Kept exactly as Meta reports them. |
| `total_active_time` | Number | Seconds the ad has been active, when Meta reports it. |
| `text` | String | Main ad copy. Dynamic product ads can contain Meta templates such as `{{product.name}}`. |
| `title`, `caption`, `link_description` | String | Headline, display domain and link description under the creative. |
| `cta_text`, `cta_type` | String | Call to action button text and type, for example "Shop now" and `SHOP_NOW`. |
| `link_url` | String | Landing page the ad links to. |
| `display_format` | String | Creative format: IMAGE, VIDEO, CAROUSEL, DPA (dynamic product ad) or DCO (dynamic creative). |
| `videos` | Array | Video creatives, each with `video_hd_url`, `video_sd_url` and `video_length`. The URLs are signed by Meta and expire after some days. |
| `images` | Array | Image creative URLs. Currently empty for most image ads; open `ad_library_url` to see them. |
| `cards` | Array | Carousel and dynamic ad cards, each with `title`, `body`, `link_url` and `image_url`. `image_url` is currently empty. |
| `extra_links` | Array | Additional link URLs of the ad. |
| `publisher_platform`, `publisher_platforms` | String, Array | Meta platforms where the ad runs, such as facebook and instagram, when Meta lists them. |
| `platform_delivery` | Array | Delivery details per platform, when Meta lists them. |
| `categories` | Array | Meta ad categories, for example `POLITICAL` or `UNKNOWN`. |
| `targeted_or_reached_countries` | Array | Countries the ad targeted or reached, when Meta lists them. |
| `country_iso_code`, `currency` | String | Country and spend currency of the ad, when Meta lists them. |
| `spend`, `impressions_with_index` | Object | Spend and impression ranges. Meta publishes them only for political and social issue ads. |
| `reach_estimate`, `reach_estimate_bucket`, `reach_estimate_is_coarse_bucket` | Mixed | Estimated audience reach, when Meta publishes it. |
| `disclaimer_label` | String | "Paid for by" disclaimer of political ads. |
| `gated_type`, `is_reshared` | String, Boolean | Meta's visibility type of the ad and whether it is a reshared post. |
| `search_query` | String | The search from your input that found this ad, for example "running shoes" or "advertiser Fleet Feet". |
| `search_type` | String | How the ad was found: keyword, advertiser_name, page_id or combined. |
| `search_page_id` | String | Facebook page ID used for the search, also when it was looked up from an advertiser name. |
| `scraped_at` | String | ISO 8601 date and time the ad was collected. |

### Use cases

- Marketers can watch every running ad of their competitors and see new creatives, offers and landing pages each week.
- Media buyers can collect winning video ads in a niche and download the video files for creative research.
- Agencies can build swipe files of ad copy and calls to action by keyword before they pitch a client.
- Ecommerce brands can find stores that advertise a product type in a country and see how long their ads run.
- Researchers and journalists can export political and social issue ads with spend and impression ranges.

### How to use

1. Add one object per search to **Searches**. Use `query` for a keyword, `advertiser_name` for a brand, or `page_id` for a known Facebook page.
2. Set **Country** to the two-letter code of the market, for example US, GB or DE.
3. Choose **Ad status**, and optionally **Media type**, **Ad category** and **Platforms**.
4. Set **Maximum ads per search** and start the run.

```json
{
  "searches": [
    { "query": "running shoes" },
    { "advertiser_name": "Fleet Feet" },
    { "page_id": "15087023444" },
    { "query": "black friday", "advertiser_name": "Fleet Feet" }
  ],
  "country": "US",
  "active_status": "ACTIVE",
  "media_type": "VIDEO",
  "publisher_platforms": ["instagram"],
  "maxResults": 100
}
```

### Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `searches` | Array | Yes | One object per search with `query` (keyword), `advertiser_name` (brand name, looked up once per run) or `page_id` (numeric Facebook page ID or an Ad Library URL with `view_all_page_id`). Combine `query` with `advertiser_name` or `page_id` to search one advertiser's ads for a keyword. Up to 100 searches. |
| `country` | String | No | Two-letter country code where the ads were shown. Default US. |
| `active_status` | String | No | ACTIVE (default), INACTIVE or ALL. |
| `media_type` | String | No | ALL, IMAGE, VIDEO, MEME, IMAGE_AND_MEME or NONE. Leave empty for all formats. |
| `ad_type` | String | No | ALL, POLITICAL_AND_ISSUE_ADS, CREDIT_ADS, FINANCIAL_PRODUCTS_AND_SERVICES_ADS, EMPLOYMENT_ADS, HOUSING_ADS or UNCATEGORIZED_ADS. |
| `publisher_platforms` | Array | No | Only ads on these platforms: facebook, instagram, messenger, audience_network, threads. |
| `maxResults` | Integer | No | Most new ads to save for each search, from 1 to 5,000. Default 100. |

### Output example

```json
{
  "ad_archive_id": "1187340298815526",
  "ad_library_url": "https://www.facebook.com/ads/library/?id=1187340298815526",
  "page_id": "8625969852",
  "page_name": "Fleet Feet",
  "page_profile_uri": "https://www.facebook.com/fleetfeet/",
  "page_profile_picture_url": "https://scontent.xx.fbcdn.net/v/t39.35426-6/339833255_886849079038456_n.jpg?stp=dst-jpg_s60x60&_nc_cat=108&oh=00_AYB4c2d&oe=6ADD0893",
  "page_like_count": 124084,
  "page_categories": ["Retail company"],
  "page_is_deleted": false,
  "publisher_platform": null,
  "publisher_platforms": ["facebook", "instagram"],
  "is_active": true,
  "ad_delivery_start_time": "2026-10-02T07:00:00+00:00",
  "ad_delivery_stop_time": null,
  "total_active_time": null,
  "text": "Your next PR starts with the right fit. Get a free 3D foot scan and gait analysis at your local Fleet Feet.",
  "title": "Find your perfect running shoe",
  "caption": "fleetfeet.com",
  "cta_text": "Learn more",
  "cta_type": "LEARN_MORE",
  "link_url": "https://www.fleetfeet.com/fit-id",
  "link_description": "Free fit id® scan in every store",
  "display_format": "VIDEO",
  "images": [],
  "videos": [
    {
      "video_hd_url": "https://video.xx.fbcdn.net/o1/v/t2/f2/m69/AQOk3fit_id_hd.mp4?efg=eyJ2ZW5jb2RlX3RhZyI6Imhk&oh=00_AYC1e2f&oe=6ADE11A0",
      "video_sd_url": "https://video.xx.fbcdn.net/o1/v/t2/f2/m69/AQOk3fit_id_sd.mp4?efg=eyJ2ZW5jb2RlX3RhZyI6InNk&oh=00_AYD3a4b&oe=6ADE11A0",
      "video_length": 21.3
    }
  ],
  "cards": [],
  "extra_links": [],
  "disclaimer_label": null,
  "country_iso_code": null,
  "is_reshared": false,
  "targeted_or_reached_countries": [],
  "categories": ["UNKNOWN"],
  "currency": null,
  "gated_type": "ELIGIBLE",
  "spend": null,
  "impressions_with_index": null,
  "reach_estimate": null,
  "reach_estimate_bucket": null,
  "reach_estimate_is_coarse_bucket": true,
  "platform_delivery": [],
  "search_query": "advertiser Fleet Feet",
  "search_type": "advertiser_name",
  "search_page_id": "8625969852",
  "scraped_at": "2026-10-20T09:00:00Z"
}
```

### Pricing

From $0.25 to $0.375 per 1,000 ads, depending on your Apify plan ($0.375 on the Free plan), plus a one-time start fee of $0.00005 per run. You pay only for ads saved to the dataset. Advertiser name lookups and duplicate ads are free.

### FAQ

#### How do I search one advertiser?

Add `{"advertiser_name": "Fleet Feet"}`. The Actor looks up the name in the Ad Library once per run and uses the page with exactly this name and the most likes. The page ID it used is in `search_page_id` and in the run log. If you know the page ID, use `{"page_id": "8625969852"}` instead. You find it in the Ad Library URL of the advertiser after `view_all_page_id=`.

#### How many ads can one search return?

Meta serves the Ad Library 10 ads per page, and the Actor follows the pages until it reaches **Maximum ads per search** (up to 5,000) or the last page. A search for 200 ads takes about 50 seconds. Ads that an earlier search in the same run already saved are skipped and not charged. For very broad keywords, add a country, media type or platform filter to get the most relevant ads first.

#### Why are the images of image ads empty?

The Ad Library data the Actor reads currently has no image URLs for image, carousel and dynamic product ads, so `images` is empty and `cards[].image_url` is null. Video ads include their video files. Every row has `ad_library_url`, which opens the ad with its image on facebook.com.

#### Why does an active ad have a stop date in the past, or text like {{product.name}}?

The Actor keeps both values exactly as Meta stores them and does not guess a status. Advertisers set planned stop dates that Meta does not always update. Dynamic product ads store a template such as `{{product.name}}` that Meta fills with a product from the advertiser's catalog when it shows the ad.

#### Is scraping the Facebook Ad Library legal?

The Actor reads the public Meta Ad Library that anyone can open without a Facebook account. It does not log in and does not use cookies. Rules depend on your location and use case. Check the applicable laws and Meta's terms, and handle personal data with care.

#### Can I start runs through the Apify API?

Yes. Send a POST request to `https://api.apify.com/v2/acts/thescrappa~facebook-ad-library-scraper/runs` with your input as JSON, or use an Apify client library. Read the results from the run's default dataset.

#### Can I connect the results to other tools?

Yes. Use Apify integrations to send the results to Make, Zapier, n8n, Google Sheets, Slack or a webhook, or download them as JSON, CSV or Excel.

#### What happens when a search fails?

The Actor retries short outages, then logs the error and continues with the next search. Ads saved before the error stay in the dataset. The run fails only when no search could be run.

### Related Scrappa Actors

- [Instagram User Posts Scraper](https://apify.com/thescrappa/instagram-user-posts-cheapest-0-20-1000-results)
- [Instagram User Info Scraper](https://apify.com/thescrappa/instagram-user-info-cheapest-0-20-1000-results)
- [Threads Profile Scraper](https://apify.com/thescrappa/threads-profile-scraper)
- [Similarweb Traffic Analytics Scraper](https://apify.com/thescrappa/similarweb-traffic-analytics-scraper)
- [LinkedIn Company Scraper](https://apify.com/thescrappa/linkedin-company-scraper)

# Actor input Schema

## `searches` (type: `array`):

One object per search. Use query for a keyword, advertiser_name to look up a brand's page, or page_id for a known Facebook page. Combine query with advertiser_name or page_id to search one advertiser's ads for a keyword. Ads found by several searches are saved once.

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

Two-letter country code where the ads were shown, for example US, GB, DE or FR.

## `active_status` (type: `string`):

Only ads that are running now, only stopped ads, or both.

## `media_type` (type: `string`):

Only ads with this creative format. Leave empty for all formats.

## `ad_type` (type: `string`):

Only ads in this category. Political ads also include spend and impression ranges.

## `publisher_platforms` (type: `array`):

Only ads shown on these Meta platforms. Leave empty for all platforms.

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

Stop each search after this many new ads. The Actor pages through Meta's results 10 ads at a time.

## Actor input object example

```json
{
  "searches": [
    {
      "query": "running shoes"
    }
  ],
  "country": "US",
  "active_status": "ACTIVE",
  "maxResults": 20
}
```

# Actor output Schema

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

All results from this run in the default dataset.

# 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 = {
    "searches": [
        {
            "query": "running shoes"
        }
    ],
    "country": "US",
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("thescrappa/facebook-ad-library-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searches": [{ "query": "running shoes" }],
    "country": "US",
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("thescrappa/facebook-ad-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 '{
  "searches": [
    {
      "query": "running shoes"
    }
  ],
  "country": "US",
  "maxResults": 20
}' |
apify call thescrappa/facebook-ad-library-scraper --silent --output-dataset

```

## MCP server setup

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