# Meta Facebook Ad Library Scraper (`code-node-tools/facebook-ad-library-scraper`) Actor

Meta Facebook Ads Library scraper for keyword, Page, or URL search. Extract ad creatives, advertiser info, spend, and reach as JSON/CSV, no login needed. Also works as a Meta Ads Library scraper and Facebook Ad Library scraping API via Apify.

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

## Pricing

from $0.70 / 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/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** pulls ad data straight out of Meta's public [Ad Library](https://www.facebook.com/ads/library/) — no login, no cookies, no browser required. Give it a search term, a Facebook Page, or an Ad Library URL you already built by hand, and it streams back every matching ad as structured JSON: advertiser info, creative text and images, delivery dates, platforms, and more. Whether you're calling it "Facebook Ad Library scraper," "Meta Ads Library scraper," or "Facebook meta ad library scraper" — this Actor is built to do exactly that, at scale, on the Apify platform.

### What is this Facebook Ads Library scraper?

It's an Apify Actor that automates Meta's Ad Library the way a person would use the website's search and filters — by keyword, by advertiser Page, or by pasting in an Ad Library search URL — except it runs unattended, in parallel across as many searches as you give it, and hands you clean JSON or CSV instead of a web page. It's a fully async Python actor, so multiple searches collect at the same time instead of one after another.

If you've searched for a "Facebook ads library scraper API," this **is** that API: every input option below is also available through the [Apify API](https://docs.apify.com/api/v2), so you can trigger runs, poll status, and pull results from your own code or product without touching the Console. As a Facebook ads library scraper Apify Actor, it also comes with everything the platform adds on top: scheduling, monitoring, integrations, and residential proxy rotation handled for you.

### What data can this Meta Ads Library scraper extract?

For every matching ad, you get:

- Advertiser (Page) name, ID, logo, like count, verification status, and Page URL
- Ad creative content — headline, body text, description, call-to-action, image and video URLs, per creative variant
- Delivery status, start/stop dates, and which platforms it ran on (Facebook, Instagram, Messenger, Threads)
- Reach, spend, and impression ranges, targeting, and audience distribution — where Meta makes that data public (mainly political/issue ads under EU and US transparency rules)
- Categories, disclaimers, funding entity, and byline information
- Collation grouping, so you can tell which ads are variants of the same underlying creative

### How to scrape the Facebook Ad Library with this Actor

You don't need to build an Ad Library URL by hand, though you can if you already have one.

#### Search by keyword

Set `queries` to a list of search terms — one Facebook Ad Library scraping session runs per term, in parallel:

```json
{ "queries": ["solar panels", "yoga retreat"] }
```

#### Search by Page

Set `pageIds` to numeric Facebook Page IDs to pull a Page's full ad history:

```json
{ "pageIds": ["100119048388845"] }
```

#### Paste a URL

Already have a Facebook Ads Library URL from your browser? Drop it straight into `urls` — country, ad type, and status encoded in the URL are read automatically:

```json
{ "urls": ["https://www.facebook.com/ads/library/?active_status=active&country=US&q=running+shoes"] }
```

All three can be combined in the same run, and each one becomes its own concurrent session.

### Input options

| Field | What it does |
|---|---|
| `urls` | Facebook Ad Library search URLs or Page URLs to scrape. |
| `queries` | Keyword searches to run directly. |
| `pageIds` | Numeric Facebook Page IDs to pull full ad histories from. |
| `limitPerSource` | Cap on ads per individual URL/query/Page ID. |
| `count` | Cap on total ads across the whole run. |
| `scrapePageAds.activeStatus` | `all`, `active`, or `inactive` ads. |
| `scrapePageAds.sortBy` | Sort by impressions or recency. |
| `scrapePageAds.countryCode` | 2-letter country code (e.g. `US`, `IN`, `GB`). |
| `runTag` | A label stamped onto every output row, for telling runs apart downstream. |
| `pageSize` / `maxConcurrency` | Tune throughput per session and across sessions. |
| `dedupe` | Drop ads with a duplicate ID within the same run. |
| `hasVideo` | Require or exclude video creatives. |
| `useResidentialProxy` / `proxyCountry` | Apify residential proxy settings (platform runs only). |

Full field-by-field descriptions are also shown directly in the input form in Console.

### Example output

One row per ad, already ordered so the columns that actually have data (ad ID, advertiser, creative, platforms) come first — the fields Meta usually leaves empty for ordinary commercial ads (spend, reach, targeting) sit at the end instead of pushing the useful columns off-screen:

```json
{
  "id": "25805070919168442",
  "page": {
    "id": "100119048388845",
    "name": "Routine Wellness",
    "profile_picture_url": "https://scontent.xx.fbcdn.net/...",
    "page_url": "https://www.facebook.com/RoutineCos/",
    "likes": 35324,
    "verified": false
  },
  "is_active": true,
  "creatives": [
    {
      "body": "Rose Hips is our best seller!",
      "title": "FREE TRAVEL SIZE WITH CODE: TRAVEL",
      "image_url": "https://scontent.xx.fbcdn.net/...",
      "cta_text": "Shop Now"
    }
  ],
  "publisher_platforms": ["FACEBOOK", "INSTAGRAM", "MESSENGER", "THREADS"],
  "categories": ["UNKNOWN"],
  "delivery_start_time": "2026-04-24T07:00:00",
  "delivery_stop_time": "2026-08-07T07:00:00",
  "collected_at": "2026-08-07T11:34:27Z"
}
```

The Output tab's table view is also configured with a dataset schema, so the advertiser's logo renders as an actual image thumbnail and Page/snapshot URLs render as clickable links — not just raw strings. Alongside the scraped ads, each run also writes a per-source summary (ads collected, errors) for every URL/query/Page ID, plus one overall run summary — both organized as their own collections in the run's Storage tab rather than mixed into one flat key-value store.

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

This Actor runs on Apify's usage-based pricing: you pay for the compute time and (on the platform) residential proxy bandwidth a run consumes, shown on this Actor's **Pricing** tab. As a rough guide, a small, single-query run with no per-ad enrichment is inexpensive — well under a cent in platform usage — while a run spanning many broad queries with high concurrency costs more, mainly in proxy bandwidth. The cheapest way to find your real number: run a small test with `count` set to a handful of ads and check the run's **Usage** tab in Console for the exact compute and proxy cost, then scale that estimate up to the volume you actually need.

### FAQ

**Do I need a Facebook account, login, or cookies?**
No. The Ad Library is a public Meta transparency tool, and this Actor only reads what's already publicly visible there.

**Can I search across all countries at once?**
Meta's own Ad Library UI supports "All countries," but the underlying scraping library this Actor is built on requires a specific 2-letter country code per search — `ALL` isn't accepted. Run one search per country you care about, or add `country=XX` to a specific input URL.

**Can I pull a competitor's entire ad history?**
Yes — use `pageIds` (or an Ad Library URL with `view_all_page_id=`) with `scrapePageAds.activeStatus` set to `all` to include both active and inactive ads.

**How is this different from just browsing the Ad Library manually?**
Speed and structure. Every query or Page runs as its own session in parallel, output is clean structured JSON/CSV instead of a webpage, and you can schedule it, hit it via the API, or pipe it into another tool.

**Does this support the Apify API for programmatic Facebook Ad Library scraping?**
Yes — every input field works identically through the [Apify API](https://docs.apify.com/api/v2) and client libraries, so you can run this Apify Meta Ads Library scraper from your own backend, not just Console.

**Is this a general-purpose Facebook ads library data scraper, or just for specific niches?**
General-purpose. Nothing about it is tied to a particular industry — run it against any keyword or Page, in any supported country, and it returns the same structured schema either way. Whether you need one-off Meta Ads Library scraping for a single competitor or a recurring, scheduled Facebook ads library data scraper feeding a larger pipeline, the same input options cover both.

**What about vanity Page URLs, like facebook.com/SomeBrand?**
Those can't be resolved to a numeric Page ID without an extra lookup step, so they're skipped with a logged warning. Use the numeric Page ID, or an Ad Library URL containing `view_all_page_id=`, instead.

# Actor input Schema

## `urls` (type: `array`):

List of Facebook Ad Library search URLs or Page URLs to scrape ads from. A search URL (containing ?q=...) is scraped as a keyword search; a URL containing view\_all\_page\_id=, or a plain page URL with a numeric ID, is scraped as that page's ads. Any country / ad\_type / active\_status / search\_type already encoded in the URL overrides the matching setting below. Optional if you use 'queries' and/or 'pageIds' instead.

## `queries` (type: `array`):

Keyword searches to run directly, as an alternative or addition to 'urls'. Each query gets its own concurrent session and uses the settings below (country, ad type, active status, sort, date range).

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

Numeric Facebook Page IDs to collect all ads from directly, as an alternative or addition to 'urls'. Each Page ID gets its own concurrent session and uses the settings below.

## `limitPerSource` (type: `integer`):

Maximum number of ads to collect from each individual source (each URL, query, or page ID). Leave blank to collect all available ads per source.

## `count` (type: `integer`):

Stop the whole run once this many ads have been collected in total, across all URLs/queries/page IDs combined. Leave empty for no overall cap.

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

Whether to collect active ads, inactive ads, or both. Overridden by an active\_status value already present in a given URL.

## `scrapePageAds.sortBy` (type: `string`):

Sort by total impressions or by recency. Applies across all URLs.

## `scrapePageAds.countryCode` (type: `string`):

2-letter ISO country code (ISO 3166-1 alpha-2), e.g. US, IN. Unlike Facebook's own Ad Library site, this Actor requires an exact 2-letter code -- 'ALL' / worldwide is not supported and that source will be skipped with a logged error. Overridden by a country value already present in a given URL.

## `runTag` (type: `string`):

Optional label stamped onto every output item's 'runTag' field, useful for telling runs apart downstream.

## `pageSize` (type: `integer`):

Ads fetched per API request. Higher means fewer round trips and faster collection. The API caps this around 30.

## `maxConcurrency` (type: `integer`):

Number of URLs collected in parallel, each with its own session (and its own proxy IP on the platform). This is the main speed lever. Raise it for more throughput, lower it if you start seeing errors.

## `dedupe` (type: `boolean`):

Skip ads with an ID already collected earlier in this run. In-memory only (no disk I/O), shared across all concurrent URLs.

## `hasVideo` (type: `boolean`):

Leave unset to include both. Set true/false to require or exclude video creatives.

## `useResidentialProxy` (type: `boolean`):

On the Apify platform, routes each session through Apify's residential proxy pool for better reliability at scale. Automatically ignored (never used) when running locally -- local runs always connect directly.

## `proxyCountry` (type: `string`):

Optional two-letter country code to target for residential proxy exit IPs. Leave empty for automatic selection.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=solar%20panels"
    }
  ],
  "scrapePageAds.activeStatus": "all",
  "scrapePageAds.sortBy": "impressions_desc",
  "scrapePageAds.countryCode": "US",
  "pageSize": 30,
  "maxConcurrency": 20,
  "dedupe": true,
  "useResidentialProxy": true
}
```

# Actor output Schema

## `ads` (type: `string`):

Every ad collected this run, one item per ad, in the Overview view defined by the dataset schema.

## `sourceSummaries` (type: `string`):

How many ads each input URL/query/Page ID returned, and whether it hit an error.

## `runSummary` (type: `string`):

Overall totals for the run: ads collected, unique ads after dedup, sources processed vs. errored.

# 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 = {
    "urls": [
        {
            "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=solar%20panels"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("code-node-tools/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 = { "urls": [{ "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=solar%20panels" }] }

# Run the Actor and wait for it to finish
run = client.actor("code-node-tools/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 '{
  "urls": [
    {
      "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=solar%20panels"
    }
  ]
}' |
apify call code-node-tools/facebook-ad-library-scraper --silent --output-dataset

```

## MCP server setup

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