# Facebook Ads Library Scraper - Meta & Instagram + EU Reach (`githubanassk/meta-ad-library-scraper`) Actor

Scrape Facebook and Instagram ads from the Meta Ads Library by keyword or advertiser page. Deduplicated ads with creatives, copy, dates, platforms and EU reach, age, gender and payer data. $0.60 per 1,000 ads.

- **URL**: https://apify.com/githubanassk/meta-ad-library-scraper.md
- **Developed by:** [anass kabil](https://apify.com/githubanassk) (community)
- **Categories:** Social media, Marketing
- **Stats:** 1 total users, 1 monthly users, 66.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.60 / 1,000 ad saveds

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: Meta & Instagram ads with EU reach data

Collect ads from the [Meta Ad Library](https://www.facebook.com/ads/library/) by **keyword** or **advertiser page**. Each ad is **deduplicated by archive ID and verified** before it reaches your dataset, so you pay only for unique ads.

### What you get per ad

- **Identity:** ad archive ID, page name and ID, page likes, page categories
- **Status and timing:** active or inactive, start and end dates, total active time
- **Creative:** headline, body text, CTA text and type, landing URL, image and video URLs (HD and SD), carousel cards, display format
- **Delivery:** publisher platforms (Facebook, Instagram, Messenger, Audience Network), impressions index, reach estimate, and spend/currency where Meta publishes it
- **EU and regional transparency** (on by default): total EU reach plus age, gender, and location breakdowns, and the beneficiary and payer, wherever Meta discloses them

### How to use it

1. Add **search terms** (e.g. `protein powder`) and/or **advertiser page IDs**. The page ID is the `view_all_page_id` in a Meta Ad Library URL.
2. Pick a **country**, an **ad status** (active, inactive, or all), and a **media type**.
3. Set **max ads per search** (0 means everything available) and run.

Every search term or page is collected separately. An ad found by two of your searches is kept, and charged, only once.

### Example input

```json
{
  "searchTerms": ["protein powder"],
  "pageIds": ["687161278012626"],
  "country": "US",
  "activeStatus": "active",
  "maxAdsPerSearch": 500
}
```

### Example output (one ad, trimmed)

```json
{
  "ad_archive_id": "2257951791619613",
  "page_id": "687161278012626",
  "page_name": "Clean Simple Eats",
  "is_active": false,
  "start_date": 1782975600,
  "end_date": 1783753200,
  "publisher_platforms": ["FACEBOOK", "INSTAGRAM", "AUDIENCE_NETWORK", "THREADS"],
  "title": "Clean Simple Eats",
  "text_body": "BRB, running to @Walmart to stock up on our fave clean protein...",
  "cta_text": "Shop now",
  "link_url": "https://cleansimpleeats.com/pages/locations",
  "image_url": "https://scontent.xx.fbcdn.net/v/t39.35426-6/...",
  "display_format": "CAROUSEL",
  "search_term": "protein powder",
  "eu_transparency": null
}
```

Dates are Unix timestamps in seconds. For ads shown in the EU, `eu_transparency` holds total EU reach, the age, gender and country breakdowns, and the beneficiary and payer. Export as JSON, CSV or Excel from the dataset tab, or read it through the Apify API.

### Pricing

You pay **$0.60 per 1,000 unique ads** saved ($0.0006 per ad). Duplicates are never charged. Use Apify's **maximum cost per run** setting to cap spend; the run stops cleanly when it reaches your limit.

### Use cases

#### Spy on competitor ads

See every ad a competitor is running right now. Copy the page ID from their Ad Library URL (`view_all_page_id=...`) and pull only active ads:

```json
{ "pageIds": ["687161278012626"], "country": "US", "activeStatus": "active", "maxAdsPerSearch": 0 }
```

Sort by `start_date` to see their newest tests; ads that keep running for months are usually their winners.

#### Build an ad swipe file

Collect proven creatives for a niche in one run. Search a few keywords, keep only video or image ads, and export the dataset to CSV or Google Sheets. Every row has the copy, headline, CTA, landing URL and the creative URLs:

```json
{ "searchTerms": ["protein powder", "pre workout", "creatine"], "country": "US", "mediaType": "video", "maxAdsPerSearch": 200 }
```

#### Count a brand's active ads for agency outreach

A brand running 40 active ads has a creative budget and a team to talk to. Feed a list of prospect page IDs, set `activeStatus` to `active`, and count rows per `page_name` to rank who to pitch first. Add `startDateFrom` to see who launched new ads this month:

```json
{ "pageIds": ["687161278012626", "20531316728"], "country": "ALL", "activeStatus": "active", "startDateFrom": "2026-10-01", "maxAdsPerSearch": 0 }
```

#### Research EU ad reach

Meta publishes reach, age, gender and country breakdowns, plus the beneficiary and payer, for ads shown in the EU. Keep `includeTransparency` on and pick an EU country:

```json
{ "searchTerms": ["electric bike"], "country": "DE", "activeStatus": "all", "includeTransparency": true, "maxAdsPerSearch": 300 }
```

Each ad's `eu_transparency` field then holds total EU reach and the demographic breakdowns, ready for a chart or a report.

#### Monitor on a schedule

Save any input above as an Apify task and add a daily or weekly schedule. Pair `startDateFrom` with the schedule window to get only new ads, and connect the dataset to Google Sheets, Slack, Make, Zapier or n8n through Apify integrations. Ready-made Python, Node and n8n examples (new ads to CSV, Google Sheets or Slack): [github.com/anassk01/facebook-ads-library-scraper](https://github.com/anassk01/facebook-ads-library-scraper).

### Notes

- This actor collects only what Meta publishes in its public Ad Library. Meta doesn't publish clicks, CTR, conversions, or ROAS for commercial ads, so no tool can give you those.
- Spend and impressions ranges exist mainly for political and issue ads, and for ads in regulated regions.
- Residential proxy (the default) gives the most reliable results.

Questions or a field you need? Open an issue on the actor's Issues tab. We answer every one.

# Actor input Schema

## `searchTerms` (type: `array`):

Keywords to search, one per run item (e.g. "protein powder"). Leave empty when using advertiser page IDs.

## `pageIds` (type: `array`):

Collect all ads of these Facebook page IDs (one run item per page).

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

Two-letter country code, or ALL.

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

Stop after this many unique ads for each term or page. 0 = everything available.

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

Collect only active ads, only inactive ads, or both.

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

Limit results to one creative type, or keep all.

## `startDateFrom` (type: `string`):

Only ads that started running on or after this date (YYYY-MM-DD). Older ads that were still running are dropped and not charged. Use it for weekly new-ad monitoring.

## `startDateTo` (type: `string`):

Only ads that started running on or before this date (YYYY-MM-DD).

## `includeTransparency` (type: `boolean`):

Reach, age/gender/location breakdowns, beneficiary and payer where Meta publishes them (EU and other regulated regions).

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

Residential proxies give the most reliable results.

## `failIfEmpty` (type: `boolean`):

Mark the run as failed when it collects zero ads, so monitoring and alerts catch it.

## Actor input object example

```json
{
  "searchTerms": [
    "protein powder"
  ],
  "country": "US",
  "maxAdsPerSearch": 100,
  "activeStatus": "all",
  "mediaType": "all",
  "includeTransparency": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "failIfEmpty": false
}
```

# Actor output Schema

## `overview` (type: `string`):

Key fields per ad: advertiser, status, dates, platforms, copy, creative and EU transparency.

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

Every collected field for each unique ad, including carousel cards and regional regulation data.

# 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 = {
    "searchTerms": [
        "protein powder"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("githubanassk/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 = { "searchTerms": ["protein powder"] }

# Run the Actor and wait for it to finish
run = client.actor("githubanassk/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 '{
  "searchTerms": [
    "protein powder"
  ]
}' |
apify call githubanassk/meta-ad-library-scraper --silent --output-dataset

```

## MCP server setup

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