# Meta Ad Library Scraper (`maged120/meta-ad-library-scraper`) Actor

Scrape Facebook and Instagram ads from the Meta Ad Library by keyword, page or Ad Library link: ad text, images, videos, landing pages, platforms, run dates and page details.

- **URL**: https://apify.com/maged120/meta-ad-library-scraper.md
- **Developed by:** [Maged](https://apify.com/maged120) (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 $6.00 / 1,000 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

**Scrape Facebook and Instagram ads from the Meta Ad Library.** Enter a keyword, a Facebook page or any Ad Library link. You get every ad with its full text, headline, button, landing page, images, videos, carousel cards, platforms, start and end dates, and page details.

### What does Meta Ad Library Scraper do?

Meta Ad Library Scraper collects ads from the [Meta Ad Library](https://www.facebook.com/ads/library/), which covers ads running on Facebook, Instagram, Messenger, Threads and the Audience Network. It returns **clean, structured rows**: one per ad, with direct links to the creative files.

It runs on the Apify platform, so you also get API access, scheduled runs, integrations (Google Sheets, Slack, Zapier, Make, webhooks), proxy rotation and run monitoring.

### Why use Meta Ad Library Scraper?

- **Competitor research**: see every ad a competitor runs, what they say and where they send the traffic.
- **Creative swipe files**: download image and video creatives and carousel cards in bulk.
- **Find winning ads**: ads with an early `startDate` that are still active have been running profitably for a long time.
- **Lead generation**: find brands actively spending on ads in your niche, with page links and follower counts.
- **Political and issue ad monitoring**: track spend and impression ranges plus "paid for by" disclaimers.
- **Market research**: see which offers, hooks and calls to action dominate a keyword or country.

### How to scrape the Meta Ad Library

1. Open the **Input** tab.
2. Add **keywords, pages or Ad Library links**, for example `running shoes`, `https://www.facebook.com/nike`, a page ID, or a search link copied from your browser.
3. Pick a **country**, **ad status**, **category** and **media type**, or keep the defaults.
4. Click **Start**. Ads appear in the **Output** tab as they're collected.
5. Download the results as JSON, CSV, Excel or HTML, or pull them through the API.

### Input

| Field | Description |
|---|---|
| `searches` | Keywords, Facebook page links, page IDs or Ad Library links. Mix them freely. |
| `country` | Only ads delivered in this country. Default: all countries. |
| `activeStatus` | Active, inactive or both. Default: active. |
| `adType` | All ads, or only issue, election and political ads. |
| `mediaType` | All, images, videos, memes, or ads without media. |
| `maxAdsPerSearch` | Maximum ads per search (0 = all). Default 100. |

```json
{
    "searches": ["https://www.facebook.com/nike", "running shoes"],
    "country": "US",
    "activeStatus": "active",
    "maxAdsPerSearch": 200
}
```

**Tip:** filters inside a pasted Ad Library link (country, media type, status, and so on) are respected, so you can build the search in your browser and paste it.

### Output

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

```json
{
    "entityType": "ad",
    "searchTerm": "nike",
    "adArchiveId": "2087470841874320",
    "adLibraryUrl": "https://www.facebook.com/ads/library/?id=2087470841874320",
    "pageId": "67997232685",
    "pageName": "Foot Locker",
    "pageUrl": "https://www.facebook.com/Footlocker/",
    "pageLikes": 6730423,
    "pageCategories": ["Shopping"],
    "isActive": true,
    "startDate": "2026-07-22",
    "endDate": "2026-09-30",
    "platforms": ["Facebook", "Instagram", "Messenger", "Threads"],
    "displayFormat": "Dynamic product",
    "body": "Refresh your wardrobe with new styles from Nike, New Balance, adidas, and more.",
    "title": "Shop New Styles",
    "caption": "footlocker.com",
    "ctaText": "Shop now",
    "linkUrl": "https://www.footlocker.com/category/new-arrivals.html",
    "thumbnailUrl": "https://scontent.xx.fbcdn.net/...jpg",
    "imageUrls": null,
    "videoUrls": null,
    "cards": [{ "title": "Shop New Styles", "body": "Refresh your wardrobe...", "imageUrl": "https://scontent.xx.fbcdn.net/...jpg", "linkUrl": "https://www.footlocker.com/..." }],
    "versions": 3
}
```

#### Data fields

| Field | What it means |
|---|---|
| `pageName`, `pageUrl`, `pageLikes`, `pageCategories` | The advertiser's page |
| `body`, `title`, `linkDescription`, `caption` | Ad copy |
| `ctaText`, `linkUrl` | Button text and landing page |
| `displayFormat` | Image, Video, Carousel, Dynamic product, Dynamic creative, and so on |
| `thumbnailUrl`, `imageUrls`, `videoUrls` | Creative files |
| `cards` | Every card of a carousel or dynamic ad, with its own text, link and media |
| `platforms` | Facebook, Instagram, Messenger, Threads, Audience Network |
| `isActive`, `startDate`, `endDate` | Status and run dates (for active ads, `endDate` is the most recent day seen) |
| `versions` | Number of near-identical versions Meta groups under this ad |
| `disclaimer`, `spend`, `impressions`, `currency` | Filled for issue, election and political ads |

#### Dataset views

- **Ads**: copy, landing page, format, platforms and dates.
- **Creatives & media**: images, videos and carousel cards.
- **Political & issue ads**: disclaimers, spend and impressions.

### How many results will I get?

You get one row per ad. A keyword like "nike" matches tens of thousands of ads, so use `maxAdsPerSearch`, country, status and media filters to collect only what you need. A page search typically returns every ad that page is running.

### Tips

- **Use page links for competitors**: a page search returns only that brand's own ads. A keyword search also matches resellers and anyone else mentioning the word.
- **Save Ad Library links**: set up any complex search in the browser, copy the link and paste it into `searches`.
- **Monitor weekly**: schedule the actor and compare `adArchiveId` values to spot new creatives.
- **Media links expire**: image and video links are signed by Meta and stop working after some days, so download the creatives you want to keep soon after the run.

### FAQ

**Is it legal to scrape the Meta Ad Library?**
The Ad Library is a public transparency tool, and the actor collects only publicly shown ad information. You are responsible for how you use the data. Consult a lawyer if you're unsure about your use case.

**Why does the ad text contain `{{product.name}}`?**
Dynamic product ads fill in text per product. The real product text, images and links are in the `cards` field.

**Why is the ad count lower than the number shown in the Ad Library?**
The Ad Library count includes near-identical versions of the same ad. The actor returns one row per ad and reports how many versions it has in `versions`.

**Something missing or broken?**
Open an issue in the **Issues** tab and we'll look at it quickly. Need a custom version or a bigger data pipeline? Get in touch through the same tab.

***

⭐ **Found this Actor useful?** A quick review on the Store helps other users find it and keeps it maintained.

### Related tools

- [Instagram Profile Scraper – followers, bio, business contacts and posts](https://apify.com/maged120/instagram-profile-scraper)

# Actor input Schema

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

One per line. Enter a keyword (running shoes), a Facebook page link (https://www.facebook.com/nike), a page ID, or paste any Ad Library search link straight from your browser. Filters inside a pasted link override the ones below.

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

Only return ads delivered in this country.

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

Active ads only, inactive (ended) ads only, or both.

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

All ads, or only ads about social issues, elections or politics (these include spend and impression ranges).

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

Only return ads with this kind of media.

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

Stop after this many ads for each keyword, page or link. 0 = every ad.

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

Residential proxies give the most reliable results and are recommended. You can switch to other proxies to lower costs.

## Actor input object example

```json
{
  "searches": [
    "https://www.facebook.com/nike",
    "running shoes"
  ],
  "country": "ALL",
  "activeStatus": "active",
  "adType": "all",
  "mediaType": "all",
  "maxAdsPerSearch": 100,
  "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 = {
    "searches": [
        "https://www.facebook.com/nike",
        "running shoes"
    ],
    "maxAdsPerSearch": 100,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("maged120/meta-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": [
        "https://www.facebook.com/nike",
        "running shoes",
    ],
    "maxAdsPerSearch": 100,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("maged120/meta-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": [
    "https://www.facebook.com/nike",
    "running shoes"
  ],
  "maxAdsPerSearch": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call maged120/meta-ad-library-scraper --silent --output-dataset

```

## MCP server setup

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