# Facebook Ads Library Scraper · Meta Page Ads, Creatives & Reach (`corent1robert/facebook-ads-library-scraper`) Actor

Scrape public ads from the Meta (Facebook) Ads Library by Page URL: creatives, copy, CTAs, placements, and reach/spend when Meta discloses them. JSON/CSV export for competitor intel, creative research, and media audits. Contact: corentin@outreacher.fr

- **URL**: https://apify.com/corent1robert/facebook-ads-library-scraper.md
- **Developed by:** [Corentin Robert](https://apify.com/corent1robert) (community)
- **Categories:** Developer tools, Agents, Social media
- **Stats:** 60 total users, 2 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Facebook Ads Library Scraper

**See every public ad a Facebook Page runs — creatives, copy, placements, and transparency metrics — in one export you can plug into analysis, CRM, or reporting.**

Stop manually clicking through the [Meta Ads Library](https://www.facebook.com/ads/library/). This Actor resolves your page, opens a real browser session to obtain valid library tokens, lists ads the same way Meta’s UI does, then enriches rows with reach and spend **when Meta discloses them**. You get structured JSON (and CSV locally) instead of screenshots and copy-paste.

> **Built for:** Competitive intelligence · Creative & messaging research · Media buying audits · Brand compliance & benchmarking

> **Important:** Numeric **reach / spend** appear when Meta exposes them (often for ads under **EU transparency** rules). Outside those cases, you still get creatives and copy; numbers may be `null`. **Apify Residential Proxy** improves reliability against blocks but is **billed per GB** — use it when you need it, not by default on every run.

***

### What does it extract?

| Category | What you get |
|----------|----------------|
| **Identity** | Ad archive ID, permalink to the Ad Library, page ID & name, profile URL, which page you searched vs which page paid for the ad |
| **Creative** | Images (URLs + copy), videos (HD/SD/preview), titles, body text, CTA label & type, landing URL |
| **Delivery** | Active status, start/end dates, publisher platforms (Facebook, Instagram, Messenger, Threads, …) |
| **Performance** | Impressions/reach and spend **as integers when disclosed**; demographic/geo breakdowns when present in Meta’s payload |

**Scope:** Only ads **published under the page you search** are kept — partner or “other brand” ads that appear on that page are skipped so your export reflects **that page’s own spend**, not every card shown in the UI.

**Output:** Rows in the Apify **Dataset** (JSON, CSV, Excel, HTML from the console). **Locally**, a UTF-8 **`output.csv`** (with BOM for Excel) is written next to your input. Use the **Ads — Overview** view for a reporting-focused column set.

***

### Why teams use it

- **One run = full visibility** on what a competitor (or your brand) is running in the public library, sorted for analysis.
- **Ready for spreadsheets & BI** — stable field names, `null` where Meta hides numbers (not silent zeros).
- **Progress in the Run log** — listing and “reach & spend” phases show status and ETA on large pages.
- **Scales from a quick test** (few ads) to **deep dives** (hundreds of ads) within your timeout and memory limits.

***

### Quick start (about 3 minutes)

1. Open the Actor **Input** tab on Apify.
2. Add at least one **Facebook Page URL** (one per row in the list field), e.g. `https://www.facebook.com/yourpage`.
3. Optionally set **Country** and **Max ads** — or leave defaults / omit for broader runs (see below).
4. Click **Run**.
5. Open the **Dataset** tab when the run finishes and download JSON or CSV.

***

### Input — what to put in

#### Primary: Facebook Page URL(s)

Paste normal profile URLs or **Ads Library** URLs that already contain `view_all_page_id`:

```json
{
  "url": ["https://www.facebook.com/staycationparis"]
}
```

Single URL as a string is also accepted when passed via API:

```json
{
  "url": "https://www.facebook.com/staycationparis"
}
```

**Tip:** If a profile URL sometimes returns a login wall to automated fetches, use an Ads Library link with `view_all_page_id=…` or pass a numeric **page ID** via advanced input (see API section below).

#### Filters (form + API)

| Parameter | Default | Description |
|-----------|---------|-------------|
| `url` | — | **Required.** One or more Page URLs or Ads Library URLs (`string` or `string[]` depending on client). |
| `country` | Omit / ALL | Market filter in the library. Use **All countries** (or omit) for worldwide scope. Internal GraphQL may still use a fallback ISO code for stable listing. |
| `maxAds` | `0` = unlimited | Cap how many ads to collect per page. **0** or omit = no cap (within memory/timeout). |
| `proxyConfiguration` | Omit = direct | Enable **Apify Proxy** (e.g. residential) if Meta rate-limits or blocks your runs. Residential = **per-GB** pricing. |

#### Advanced (API / raw JSON only)

The Actor also supports, depending on version: `pageIds`, `urls`, `pageId`, `libraryUrl`, `adType`, `mediaType`, `sortData`, `speed` (`safe` / `normal` / `fast`), `metricsBatchSize`, `verboseLogs`, etc. See the repository `input_schema.json` and `src/main.js` for the full list.

***

### How it works (short)

1. **Resolve** the Facebook Page ID (from URL or Ads Library link).
2. **List** public ads via Meta’s GraphQL (same data the library UI uses), with pacing to reduce rate limits.
3. **Enrich** each ad with detail requests for reach/spend and richer creatives when needed.
4. **Push** validated rows to the dataset (schema-aligned so exports don’t break).

A headless browser is used to obtain session tokens — runs use more memory than a plain HTTP Actor.

***

### Output sample

```json
{
  "adArchiveId": "906876921871660",
  "adLibraryUrl": "https://www.facebook.com/ads/library/?id=906876921871660",
  "pageId": "1135060673240590",
  "searchedPageId": "1135060673240590",
  "isFromSearchedPage": true,
  "pageName": "Example Page",
  "pageProfileUri": "https://www.facebook.com/...",
  "isActive": true,
  "startDate": "2025-01-15T00:00:00.000Z",
  "publisherPlatform": ["FACEBOOK", "INSTAGRAM"],
  "linkUrl": "https://example.com/landing",
  "ctaText": "Book now",
  "adDescription": "Primary text from the creative…",
  "impressions": 1250000,
  "spend": null,
  "impressionsBreakdown": {
    "targetsEu": true,
    "totalReach": 1250000,
    "genderAudience": "All"
  },
  "images": [
    {
      "original": "https://scontent.xx.fbcdn.net/...",
      "resized": null,
      "title": "",
      "body": "",
      "ctaText": "Book now",
      "ctaType": "LEARN_MORE",
      "linkUrl": "https://example.com/landing"
    }
  ],
  "videos": []
}
```

Download from the **Dataset** tab as JSON, CSV, Excel, or HTML.

***

### Transparency fields & `null`

| Topic | Behavior |
|-------|----------|
| `impressions` / `spend` | Always present on each row. **Integer** when Meta discloses; **`null`** when not (not the same as zero). |
| EU vs rest | Reach/spend appear most often for ads covered by **EU-style** transparency; other regions may return creatives without numbers. |
| `genderAudience` | Normalized to **English** labels when Meta returns localized strings. |
| `resized` / video `sd` | **`null`** when the URL matched `original` / `hd` and was deduplicated. |
| CDN URLs | Image/video URLs point to Meta CDNs; **tokens expire** — archive assets soon if you need permanent files. |

***

### Performance & cost

| Factor | Notes |
|--------|--------|
| **Compute** | Browser + many GraphQL calls — use **timeout** and **memory** from `actor.json` or raise them for huge pages. |
| **Proxy** | Default product behavior can be **direct** (no proxy). Residential proxy reduces blocks but adds **per-GB** cost — disable when not needed. |
| **Rate limits** | Meta may return HTTP 429; the Actor backs off and retries. Very large listings take longer. |
| **Apify pricing** | Charged in platform units (e.g. CU) + proxy traffic if enabled — see [Apify pricing](https://apify.com/pricing). |

**Tip:** Start with a **low `maxAds`** to validate output, then remove the cap or raise it for full exports.

***

### Tips & best practices

**Start small.** Use `maxAds: 10`–`50` on the first run, then scale up.

**Proxy when blocked.** If you see repeated failures or empty sessions from Apify IPs, enable **Apify Proxy** (residential is strongest; datacenter is cheaper).

**Country.** Match the market you care about for filtering in the library UI; “all countries” is supported for broad research.

**Schedule.** Use Apify **Schedules** to refresh competitor snapshots weekly or monthly.

**Local runs.** From the project folder, with `input.json` at the root: `npm start` (see your `Dockerfile` / `package.json`). Dataset files land under `storage/`; **`output.csv`** is written for quick Excel checks.

***

### Use cases

| Goal | Suggested input |
|------|------------------|
| Monitor one competitor’s creatives | Single `url`, optional `maxAds` for tests |
| Full ad history for a page | `url`, omit `maxAds` (watch timeout) |
| Focused market | Set `country` to match your GEO |
| Stable runs from the cloud | Enable `proxyConfiguration` if direct egress is flaky |

***

### FAQ

**Is this affiliated with Meta?**\
No. It automates access to **public** Ads Library data. You must comply with Meta’s terms and applicable laws.

**Why are reach/spend sometimes empty?**\
Meta only discloses them in certain jurisdictions and conditions. The Actor returns `null` instead of guessing.

**Does it include political ads only?**\
The Actor targets **standard commercial** library results unless you pass advanced options (e.g. `adType`) via API — see `input_schema.json` / code for your deployed version.

**Can I scrape many pages in one run?**\
Yes — pass multiple URLs in `url` when supported by your input form, or use bulk fields (`urls`, `pageIds`) via API if exposed in your Actor version.

**Why did my run slow down mid-way?**\
Listing and detail phases are paced; rate limits (429) trigger automatic waits. Large inventories take time.

***

### Legal

This tool helps collect **publicly visible** Ads Library information for analysis. You are responsible for complying with Meta’s terms of service, privacy and advertising rules, and your organisation’s policies. Not affiliated with or endorsed by Meta.

***

### Support

Questions, custom fields, or higher-volume setups: **corentin@outreacher.fr**

**Ready?** Add your Page URL(s), set country and caps if needed, and hit **Run**.

# Actor input Schema

## `url` (type: `array`):

**Bulk list** — one URL per row. Works with `facebook.com/…` pages or Ads Library links that include `view_all_page_id`.

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

Market for the Ads Library session (Meta’s country filter). **Leave empty or omit this field** to search **all countries** (ALL).

## `maxAds` (type: `integer`):

Stop after this many ads for this page. **0** or **omit this field** = **no limit** (within Actor memory/timeout).

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

Omit or disable for **direct** connection. Enable **Apify Proxy** if Meta blocks or rate-limits you.

## Actor input object example

```json
{
  "url": [
    "https://www.facebook.com/staycationparis"
  ],
  "country": "FR",
  "maxAds": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

All ads as structured JSON — download or open in the Dataset tab.

## `adsOverview` (type: `string`):

Slim view for reporting: identity, CTAs, copy, reach/spend, platforms.

## `fullAds` (type: `string`):

Complete rows: images, videos, audience breakdowns, plus all overview fields.

## `runLog` (type: `string`):

Progress and ETA during listing and reach/spend phases.

# 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 = {
    "url": [
        "https://www.facebook.com/staycationparis"
    ],
    "country": "FR",
    "maxAds": 5,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("corent1robert/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 = {
    "url": ["https://www.facebook.com/staycationparis"],
    "country": "FR",
    "maxAds": 5,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("corent1robert/facebook-ads-library-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "url": [
    "https://www.facebook.com/staycationparis"
  ],
  "country": "FR",
  "maxAds": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call corent1robert/facebook-ads-library-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=corent1robert/facebook-ads-library-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/qSyxuu9fMXCgD6mno/builds/L2So5ayh520qap5Pg/openapi.json
