# Facebook Ads Library Scraper (`valev-lab/facebook-ads-library`) Actor

Scrape Facebook / Meta Ad Library for competitor ads. Search by keyword, Page URL, or pasted Ads Library URL. Extract creatives, copy, links, media, platforms & spend when available. No login or Meta API token. From $0.40 per 1,000 ads.

- **URL**: https://apify.com/valev-lab/facebook-ads-library.md
- **Developed by:** [Daniel Valev](https://apify.com/valev-lab) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.22 / 1,000 ad scrapeds

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 ads from the [Facebook / Meta Ad Library](https://www.facebook.com/ads/library/) at scale. Search by **keyword**, **advertiser Page URL**, or a **pasted Ads Library URL**. Extract creatives, copy, CTAs, destination links, images, videos, platforms, and spend when Meta makes it available — in a flat, spreadsheet-ready format. **No Facebook login, Meta app review, or Ad Library API token required.**

### What does Facebook Ads Library Scraper do?

This Actor reads the **public Meta Ad Library** (the same transparency archive anyone can open in a browser) and returns one structured row per ad. Use it as a **Facebook Ads Library API alternative** for competitor research, creative inspiration, brand monitoring, and agency audits across Facebook, Instagram, Messenger, and Audience Network.

Provide at least one target. Each keyword, page URL, or Ads Library URL is a separate task (up to 20 total per run). Set `maxAds` to control how many matching ads to keep per task (cap: 500). Optional date bounds collect ads whose activity window overlaps an inclusive campaign period. Overlapping results are **deduplicated by Ad Library ID** before output and per-ad charging.

### Who is it for?

- **Digital marketers** — Research competitor creatives, CTAs, and landing pages.
- **Competitive intelligence teams** — Monitor what rivals advertise, where, and for how long.
- **Brand monitoring** — Spot unauthorized or partner ads that mention your brand.
- **Agencies** — Audit client competitors across Meta placements.
- **Researchers & analysts** — Export Ad Library data for trends and reporting (commercial ads).

### Why scrape the Meta Ad Library?

- **No Meta API setup** — Skip app creation, review, and token rotation.
- **No login required** — Works from the public Ad Library experience.
- **Three search modes** — Keyword, Facebook Page URL, or pasted `facebook.com/ads/library/` results URL (mix freely).
- **Structured export** — Consistent field names ready for Google Sheets, Excel, Airtable, or a database.
- **Rich creatives** — Direct image URLs, video URLs, and video previews when present.
- **Platform breakdown** — See Facebook, Instagram, Messenger, and Audience Network flags.
- **Apify platform** — Schedule runs, call the API, connect Zapier/Make/n8n, and monitor from Console.

### What data can you extract?

| Field | Description |
| --- | --- |
| `adArchiveId` / `adLibraryUrl` | Unique Ad Library ID and deep link |
| `pageId` / `pageName` / `pageUrl` | Advertiser identity |
| `pageProfilePictureUrl` / `pageCategories` / `pageLikeCount` | Page metadata when present |
| `isActive` / `startDate` / `endDate` | Delivery status and activity dates |
| `platforms` | Where the ad ran (Facebook, Instagram, …) |
| `bodyText` / `title` / `ctaText` / `ctaType` | Primary creative copy and CTA |
| `linkUrl` / `linkCaption` / `linkDescription` | Destination link fields |
| `displayFormat` | Format reported by Meta (image, video, carousel, …) |
| `imageUrls` / `videoUrls` / `videoPreviewUrls` | Media URLs |
| `categories` / `containsAiMedia` | Category and AI-media flags |
| `impressions` / `spend` / `currency` | Estimates when Meta exposes them (often null for commercial ads) |
| `gatedType` / `collationCount` / `cardsCount` | Gating, collation size, carousel card count |

The full dataset uses a stable **31-field** contract (same key order every row). See the **Output** and **Dataset** tabs for the complete schema.

### How to scrape Facebook Ads Library

1. Open **Facebook Ads Library Scraper** on Apify Store and click **Try for free**.
2. Enter at least one of: search keywords (e.g. `running shoes`), advertiser Page URLs (e.g. `https://www.facebook.com/nike`), or Ads Library URLs copied from your browser.
3. Optionally set country (default `US`), active status, media type, and date bounds.
4. Set `maxAds` (default `100` per target).
5. Click **Start** and wait for the run to finish.
6. Download JSON, CSV, Excel, HTML, or send results to an integration.

No coding required for Console runs. Developers can use the **API** tab or `apify call`.

### How much does it cost to scrape Facebook ads?

Pricing is [pay-per-event](https://docs.apify.com/platform/actors/running/pay-per-event): you pay for runs you start and ads you actually receive — no monthly minimum from this Actor.

| Event | Free / no discount | Description |
| --- | ---: | --- |
| **Actor start** | $0.005 | Once per Actor run |
| **Ad scraped** | $0.0004 / ad ($0.40 / 1,000) | Per unique delivered ad |

Volume discounts on higher Apify plans:

| Plan | Per-ad price | Per 1,000 ads |
| --- | ---: | ---: |
| No discount (Free) | $0.0004 | $0.40 |
| Bronze | $0.00035 | $0.35 |
| Silver | $0.00028 | $0.28 |
| Gold | $0.00022 | $0.22 |

**Example (Free plan):** 50 ads from one search ≈ `$0.005 + (50 × $0.0004) = $0.025`.

Filtered-out, duplicate, and undelivered ads are **not** charged. Platform compute/proxy usage is billed by Apify separately from these event prices.

> Configure the same numbers in Console **Publishing → Monetization** before you publish. If you change tiers later, update this table to match.

### Input

See the **Input** tab for the full form. Summary:

| Field | Default | Notes |
| --- | --- | --- |
| `searchQueries` | — | Keyword searches (e.g. `shopify`) |
| `pageUrls` | — | Public Facebook Page URLs (e.g. `https://www.facebook.com/nike`) |
| `adsLibraryUrls` | — | Full results URLs from `facebook.com/ads/library/` |
| `country` | `US` | ISO code or `ALL` (applies to keywords and page URLs) |
| `activeStatus` | `all` | `all` / `active` / `inactive` |
| `mediaType` | `all` | `all` / `image_and_meme` / `video` |
| `onlyAdsNewerThan` / `onlyAdsOlderThan` | empty | `YYYY-MM-DD` or relative (`30 days`, `2 weeks`, `3 months`) |
| `maxAds` | `100` | Per target, after dedupe and date filtering (max 500) |

**Tips**

- You must provide at least one target. You can mix all three source types in one run.
- Pasted Ads Library URLs keep their own `country` / `active_status` / `media_type` / keyword or page ID. Unsupported URL parameters (language, platform, region, sort, embedded dates, …) are **rejected with a clear error** rather than silently ignored.
- Single-ad URLs (`?id=…`) are not supported — use search or page targets.
- Page URLs are resolved inside the Ad Library (handle → numeric page ID). Pages with no discoverable Ad Library history under that handle fail clearly.

### Output

You can download the dataset as **JSON, CSV, Excel, HTML**, or XML. Example row (trimmed media URLs):

```json
{
  "adArchiveId": "1238141341576372",
  "adLibraryUrl": "https://www.facebook.com/ads/library/?id=1238141341576372",
  "pageId": "20409006880",
  "pageName": "Shopify",
  "pageUrl": "https://www.facebook.com/shopify/",
  "pageProfilePictureUrl": "https://…",
  "pageCategories": ["Software"],
  "pageLikeCount": 4538696,
  "isActive": false,
  "startDate": "2026-01-13",
  "endDate": "2026-08-09",
  "platforms": ["FACEBOOK", "INSTAGRAM", "MESSENGER"],
  "bodyText": "When it’s time to start your business, it’s time for Shopify.",
  "title": "Get going and keep growing",
  "ctaText": "Sign up",
  "ctaType": "SIGN_UP",
  "linkUrl": "https://www.shopify.com/free-trial",
  "linkCaption": "shopify.com",
  "linkDescription": "{{product.description}}",
  "displayFormat": "DCO",
  "imageUrls": ["https://…"],
  "videoUrls": [],
  "videoPreviewUrls": [],
  "categories": ["UNKNOWN"],
  "containsAiMedia": false,
  "impressions": null,
  "spend": null,
  "currency": null,
  "gatedType": "ELIGIBLE",
  "collationCount": 1,
  "cardsCount": 2
}
```

A `RUN_SUMMARY` record in the run’s key-value store reports delivered / filtered / duplicate counts, pages fetched, and timing.

### Tips for better runs

- Start with `maxAds: 20–50` while testing filters, then raise the limit.
- Prefer `active` + a tight date window when you only care about live campaigns.
- Split very large exports across multiple keywords or runs instead of one 500-ad task.
- For a specific advertiser, a Page URL is usually cleaner than a broad keyword.
- Schedule daily/weekly runs in Apify to build a monitoring feed.

### Limitations

- **Commercial Ad Library search** (`ad_type=all`) is supported. Political / issue ads are not scraped yet and are rejected clearly if requested via URL.
- Spend and impression fields are often `null` for commercial ads — that is Meta’s public data, not a delivery bug.
- Page-URL resolution needs Ad Library ads discoverable under the page’s handle as a keyword within a bounded search; obscure pages may fail to resolve.
- This Actor does not log into Facebook or call the official Marketing / Ad Library Graph API.

### FAQ

#### Is this a Facebook Ads Library API?

It is an **API alternative**: you get structured Ad Library data through Apify (Console, REST, or integrations) without Meta developer approval. It is not Meta’s official Ad Library API.

#### Do I need a Facebook account?

No. The scraper uses the public Ad Library.

#### Can I scrape Instagram ads?

Yes — Instagram placements appear in Meta Ad Library results and in the `platforms` field when Meta reports them.

#### Why are spend and impressions null?

Meta often omits spend/impression estimates for ordinary commercial ads. When present, they are included; when absent, the fields are `null`.

#### How do I scrape Facebook ads by Page URL?

Paste URLs like `https://www.facebook.com/nike` into `pageUrls`. The Actor resolves the page inside the Ad Library, then collects that advertiser’s ads with your filters.

#### What if my run finds zero ads?

Broaden the keyword, switch country to `ALL`, set status to `all`, clear date bounds, or open the same search in a browser to confirm Ad Library returns results.

### Legal and ethics

> This Actor only collects information that advertisers and Meta have made public in the Ad Library. It does not extract private user profile data such as personal emails, gender, or private location. Results may still include publicly shown business or page information. Personal data is protected by the GDPR in the EU and by other laws worldwide. Scrape and use data only when you have a legitimate purpose. If you are unsure, consult your lawyers. Respect Meta’s terms and applicable advertising/transparency rules.

### Support

- Use the **Issues** tab on this Actor’s Store page for bugs and feature requests.
- Use the **API** tab for programmatic runs, webhooks, and dataset access.
- Built for reliable scheduled monitoring on the Apify platform.

# Actor input Schema

## `searchQueries` (type: `array`):

Keyword searches to run against the Ad Library, e.g. "shopify". Matching is case-insensitive for deduplication; the first spelling is kept.

## `pageUrls` (type: `array`):

Public Facebook page URLs, e.g. https://www.facebook.com/nike. Resolved to the page's numeric Ad Library ID by searching the Ad Library for the page's own handle text — this only finds a page that has Ad Library history discoverable under that handle within a bounded search. Pages that cannot be resolved fail with a clear error.

## `adsLibraryUrls` (type: `array`):

Full Ad Library results URLs pasted from a browser, e.g. https://www.facebook.com/ads/library/?active\_status=active\&country=US\&q=nike. Only the country, active\_status, media\_type, ad\_type, q, and view\_all\_page\_id parameters are read; other parameters (language, platform, region, sort, and similar) are rejected rather than silently ignored. Single-ad URLs (?id=...) are not supported.

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

Two-letter country code (e.g. US, GB, DE) or ALL.

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

Whether to include active, inactive, or all ads.

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

Restrict results to ads containing this media type.

## `onlyAdsNewerThan` (type: `string`):

Lower bound on ad activity: an ISO date (YYYY-MM-DD) or a relative duration such as "30 days", "2 weeks", or "3 months", resolved against the run's start time in UTC.

## `onlyAdsOlderThan` (type: `string`):

Upper bound on ad activity, in the same YYYY-MM-DD or relative-duration format as "Only ads newer than".

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

Maximum number of unique, matching ads to deliver per target (keyword, page, or URL), after deduplication and date filtering. Ads beyond this limit, filtered out, or duplicated across targets are never charged.

## Actor input object example

```json
{
  "searchQueries": [
    "shopify"
  ],
  "country": "US",
  "activeStatus": "all",
  "mediaType": "all",
  "onlyAdsNewerThan": "",
  "onlyAdsOlderThan": "",
  "maxAds": 100
}
```

# Actor output Schema

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

No description

## `runSummary` (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 = {
    "searchQueries": [
        "shopify"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("valev-lab/facebook-ads-library").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 = { "searchQueries": ["shopify"] }

# Run the Actor and wait for it to finish
run = client.actor("valev-lab/facebook-ads-library").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 '{
  "searchQueries": [
    "shopify"
  ]
}' |
apify call valev-lab/facebook-ads-library --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,valev-lab/facebook-ads-library"
        }
    }
}
```

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/h30WiV3gzAOemWjLC/builds/4v1BBfJYaZ8lyjkyp/openapi.json
