# Facebook Ads Library Scraper (`harvestlab/facebook-ads-library-scraper`) Actor

Programmatic access to Meta Ad Library. Extract ad creative, spend ranges, impressions, demographic targeting, and active status for any advertiser or keyword. Official Graph API v21.0 + web fallback. AI analysis via 5 LLM providers. $0.005/ad PPE.

- **URL**: https://apify.com/harvestlab/facebook-ads-library-scraper.md
- **Developed by:** [Nick](https://apify.com/harvestlab) (community)
- **Categories:** Marketing, Business, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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 - Competitor Ad Intelligence
> Part of the harvestlab MCP suite - 36 RAG-ready, AI-agent-payment-ready Apify actors covering ecommerce, social, travel, news, jobs, EU B2B, dev-tools, and government data. [See the full suite](https://apify.com/harvestlab)

See every ad your competitors are running on Facebook and Instagram. Spend ranges, creative text, demographic targeting, active/inactive status - from the official Facebook Ad Library API. $0.005/ad. No expensive spy tools.

The Facebook Ad Library is Meta's mandatory public transparency database - every ad running on Facebook, Instagram, Messenger, and the Audience Network is logged there. This actor gives you programmatic access at $0.005 per ad via the official Graph API v21.0, with no SaaS subscription, no seats, and no artificial export limits.

---

### Key Features

| Feature | Detail |
|---------|--------|
| **Graph API v21.0** | Official Facebook endpoint - stable, documented, supported by Meta |
| **Spend ranges** | Lower and upper bound estimates from Meta per ad |
| **Impression ranges** | Estimated reach (lower/upper bound) per ad |
| **Demographic breakdown** | Age, gender, and regional distribution (Graph API path only) |
| **Active/inactive status** | Filter to live ads only, historical ads, or all |
| **Country filtering** | Any ISO country code or search globally |
| **Political/issue ads** | Full `POLITICAL_AND_ISSUE_ADS` category with mandated disclosure data |
| **Creative fields** | Body text, link title, link description, display URL, call-to-action |
| **Ad snapshot URL** | Link to rendered ad preview image on Facebook |
| **Web fallback path** | No-token fallback using the internal Ad Library async endpoint |
| **AI creative analysis** | 5 LLM providers: OpenRouter, Anthropic, Google, OpenAI, Ollama |
| **Deduplication** | Automatic dedup by Ad ID within each run |
| **Pagination** | Cursor-based pagination follows Graph API up to your `maxResults` cap |
| **Retry logic** | Exponential backoff on 429/503 with configurable retries |
| **PPE pricing** | $0.005/ad - pay only for what you use |

---

### Why This vs. Paid Spy Tools

| Tool | Cost | Data Source | Limits |
|------|------|-------------|--------|
| AdSpy | $149/mo | Crawled | Export limits, seat limits |
| BigSpy | $99/mo | Crawled | Daily download caps |
| Pathmatics / Sensor Tower | $1,000+/mo | Crawled + panel | Enterprise contracts |
| PowerAdSpy | $49/mo | Crawled | 50-ad daily cap on base tier |
| **This actor** | **$0.005/ad PPE** | **Official Graph API v21.0** | **No subscription, no caps** |

The official Graph API gives you Meta's own structured data - the same data Meta's ad-transparency reporters use - rather than a third-party crawl that may lag 24-72 hours or miss ads entirely. Pay for exactly what you scrape, nothing more.

---

### Use Cases

#### 1. Competitive Ad Intelligence (Marketing Agency)
Track every creative your client's competitors are running in real time. Monitor when rivals launch new campaigns, which countries they are targeting, how long campaigns have been live, and estimated spend. Schedule weekly runs to build a historical archive and catch messaging pivots as they happen.

#### 2. Political Ad Transparency (Journalist / Researcher)
Set `adType` to `POLITICAL_AND_ISSUE_ADS` to pull political campaign ads, issue advocacy, and PAC spend. The official Graph API path provides full demographic and spend data for political ads - the same data Meta is legally required to disclose. Useful for investigative journalism, academic research, and compliance teams.

#### 3. Brand Safety Monitoring
Audit which advertisers are running ads alongside sensitive keywords. Identify whether your brand name is being used in competitor ads, trademark-infringing creatives, or misleading comparative advertising. Run daily and pipe results to a Slack alert via webhook.

#### 4. Creative Inspiration and A/B Research
Search any keyword to discover what messaging is working in your niche. Filter by active status to see only live campaigns. Use AI analysis to automatically score creative quality and identify the top-performing hooks in your category. Real A/B variants from real brands - no guessing.

#### 5. Market Entry Research
Filter by country to understand how global brands localize creative for different markets. Compare messaging between US, UK, and German versions of the same brand's ads. Map the competitive landscape before launching paid social in a new geography.

#### 6. Influencer and Creator Partnership Audit
Find which brands are running Facebook and Instagram ads featuring specific influencers, product categories, or content styles. Discover niche brands that are actively spending on paid social before they become mainstream - and identify potential partnership targets before your competitors do.

#### 7. SaaS Competitor Spend Analysis
Search for SaaS, fintech, or enterprise software category keywords. Identify which vendors are actively buying paid awareness, what their value propositions are, and what calls-to-action convert. Build a complete competitive intelligence map without talking to a sales rep.

#### 8. Facebook Policy Compliance Check
Verify that your own ads - and your clients' ads - comply with Meta advertising policy before a campaign goes live. Cross-reference creative against the Ad Library to confirm proper disclosure on political or financial ads.

---

### Input Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchQuery` | string | **required** | Keyword, brand name, or topic. Alias: `q` |
| `advertiserName` | string | - | Optional: filter by Facebook page name |
| `country` | string | `ALL` | ISO country code (US, GB, DE, etc.) or ALL |
| `adType` | string | `ALL` | `ALL` or `POLITICAL_AND_ISSUE_ADS` |
| `activeStatus` | string | `active` | `active`, `inactive`, or `all` |
| `maxResults` | integer | `50` | 1-1000. Alias: `maxItems` |
| `facebookAccessToken` | string | - | Facebook Graph API access token (recommended). See Authentication section below |
| `proxyConfiguration` | proxy | RESIDENTIAL | Proxy settings. Residential strongly recommended for web fallback |
| `enableAiAnalysis` | boolean | `false` | Enable per-ad AI competitive analysis (+$0.005/ad) |
| `llmProvider` | string | `openrouter` | `openrouter`, `anthropic`, `google`, `openai`, or `ollama` |
| `llmModel` | string | - | Override model. Leave blank for provider default |
| `openrouterApiKey` | string | - | OpenRouter API key |
| `anthropicApiKey` | string | - | Anthropic API key |
| `googleApiKey` | string | - | Google AI API key |
| `openaiApiKey` | string | - | OpenAI API key |
| `ollamaBaseUrl` | string | `http://localhost:11434` | Self-hosted Ollama endpoint |

---

### Authentication

#### Option A - Official Graph API (Recommended)

Provide a `facebookAccessToken` for stable, structured data with full demographic breakdowns and accurate spend/impressions ranges.

**How to get a token:**
1. Go to [Meta for Developers](https://developers.facebook.com/)
2. Create an app (any app type works for Ad Library access)
3. Generate a User Access Token with `ads_read` permission
4. For Political/Issue ads, also complete Meta's Identity Verification

**Benefits:** Stable endpoint, official support, demographic data, reliable cursor pagination, accurate spend/impressions, no proxy required.

#### Option B - Web Scraping Fallback

If no `facebookAccessToken` is provided, the actor falls back to the internal async endpoint that the Ad Library website itself calls.

- Requires **residential proxy** (pre-configured as default)
- Provides fewer demographic fields
- May break if Meta changes internal API structure
- Works without any Facebook account or developer registration

---

### Output Schema

Each ad record follows this structure:

```json
{
  "url": "https://www.facebook.com/ads/library/?id=1234567890",
  "adId": "1234567890",
  "pageId": "987654321",
  "pageName": "Acme Corporation",
  "adCreativeBody": "Summer sale - up to 50% off all products. Shop now before it's gone!",
  "adCreativeLinkTitle": "Shop the Summer Sale",
  "adCreativeLinkDescription": "Free shipping on orders over $50",
  "adCreativeLinkCaption": "acme.com",
  "adSnapshotUrl": "https://www.facebook.com/ads/archive/render_ad/?id=1234567890",
  "adDeliveryStartTime": "2024-06-01T00:00:00+0000",
  "adDeliveryStopTime": null,
  "currency": "USD",
  "spend": {
    "lower_bound": "1000",
    "upper_bound": "5000"
  },
  "impressions": {
    "lower_bound": "100000",
    "upper_bound": "200000"
  },
  "demographics": {
    "gender": [
      {"value": "female", "percentage": "0.6431"},
      {"value": "male", "percentage": "0.3569"}
    ],
    "age": [
      {"value": "25-34", "percentage": "0.2891"},
      {"value": "35-44", "percentage": "0.2341"}
    ],
    "region": [
      {"value": "California", "percentage": "0.1523"}
    ]
  },
  "platforms": ["facebook", "instagram"],
  "isActive": true,
  "country": ["US"],
  "adType": "ALL",
  "callToAction": "SHOP_NOW",
  "mediaType": "image",
  "aiAnalysis": {
    "category": "Ecommerce",
    "targeting_inference": "Women 25-44 interested in fashion and home goods, likely previous website visitors",
    "creative_strategy": "urgency + discount - time-limited sale with free shipping threshold to increase AOV",
    "key_messages": [
      "50% off - strong discount anchor",
      "Free shipping incentive to overcome checkout friction",
      "Summer seasonal relevance"
    ],
    "competitive_score": 7,
    "summary": "Classic direct-response ecommerce ad using urgency and discount stacking. The free shipping threshold is a smart AOV play. Headline is clear but generic - a brand differentiator would lift this from a 7 to a 9."
  },
  "scraped_at": "2024-06-15T10:23:45.123456+00:00"
}
````

**Field reference:**

| Field | Source | Notes |
|-------|--------|-------|
| `url` | Constructed | Direct link to the ad in the Ad Library |
| `adId` | Graph API / web | Meta's unique ad archive ID |
| `pageName` | Graph API / web | Advertiser's Facebook page name |
| `adCreativeBody` | Graph API / web | Main ad body text |
| `spend.lower_bound` / `upper_bound` | Graph API / web | Meta's spend estimate range |
| `impressions.lower_bound` / `upper_bound` | Graph API / web | Meta's reach estimate range |
| `demographics` | Graph API only | Age, gender, regional split - not available in web fallback |
| `isActive` | Graph API / web | Whether the ad is currently running |
| `platforms` | Graph API / web | Facebook, Instagram, Messenger, Audience Network |
| `callToAction` | Graph API / web | CTA button type (SHOP\_NOW, LEARN\_MORE, etc.) |
| `aiAnalysis` | LLM enrichment | Only present when `enableAiAnalysis: true` |

***

### Usage Examples

#### Example 1 - Monitor a competitor's current campaigns

```json
{
  "searchQuery": "Notion",
  "country": "US",
  "activeStatus": "active",
  "maxResults": 100,
  "facebookAccessToken": "YOUR_TOKEN"
}
```

Returns all active US ads mentioning "Notion" - current messaging, estimated spend, demographic split, and platform distribution.

#### Example 2 - Political ad research

```json
{
  "searchQuery": "climate change",
  "adType": "POLITICAL_AND_ISSUE_ADS",
  "country": "GB",
  "activeStatus": "all",
  "maxResults": 200,
  "facebookAccessToken": "YOUR_TOKEN"
}
```

#### Example 3 - AI-powered competitive intelligence sweep

```json
{
  "searchQuery": "project management software",
  "country": "US",
  "activeStatus": "active",
  "maxResults": 50,
  "facebookAccessToken": "YOUR_TOKEN",
  "enableAiAnalysis": true,
  "llmProvider": "openrouter",
  "openrouterApiKey": "YOUR_OPENROUTER_KEY"
}
```

Each ad gets an AI-generated breakdown: industry category, inferred target audience, creative strategy, key messages, and a 1-10 competitive score.

#### Example 4 - Web fallback (no token required)

```json
{
  "q": "fitness app",
  "country": "US",
  "activeStatus": "active",
  "maxResults": 30,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

No Facebook access token or developer account needed. Residential proxy is required and pre-configured.

***

### Technical Details

#### Graph API v21.0

The official Facebook Graph API endpoint (`https://graph.facebook.com/v21.0/ads_archive`) is the recommended data path:

- Officially documented and supported by Meta
- Structured demographic breakdowns (gender/age/region percentage splits)
- Accurate spend and impressions range data
- Reliable cursor-based pagination
- 200 API calls/hour per app per user - at 100 ads per page that is ~20,000 ads/hour before rate limits
- Does not require proxy (though proxy can be used for IP hygiene)

The following fields are requested from the Graph API: `id`, `page_id`, `page_name`, `ad_creative_bodies`, `ad_creative_link_titles`, `ad_creative_link_descriptions`, `ad_creative_link_captions`, `ad_snapshot_url`, `ad_delivery_start_time`, `ad_delivery_stop_time`, `currency`, `spend`, `impressions`, `demographic_distribution`, `publisher_platforms`, `is_active`, `reached_countries`, `estimated_audience_size`, `call_to_action_types`, `languages`, `media_type`.

#### Web Scraping Fallback

The fallback targets the internal `async/search_ads/` endpoint that powers the Ad Library website. The actor loads the Ad Library page to extract the LSD CSRF token and session cookies, then calls the internal search endpoint with those credentials.

- Works without authentication
- Residential proxy is required - Facebook returns 403 or login redirects without it
- Fewer demographic fields than the Graph API path
- Meta can change the internal endpoint response format at any time

#### Rate Limiting and Retry Logic

The actor includes exponential backoff on HTTP 429 and 503 responses. The web fallback adds 2-3 second jitter delays between requests. The Graph API path paginates using cursor-based pagination and automatically follows `after` cursors until your `maxResults` limit is reached.

#### AI Analysis

When `enableAiAnalysis` is enabled, each ad with body text is sent to your chosen LLM provider for analysis. The model returns:

- **category** - Inferred industry/vertical (Ecommerce, SaaS, Finance, Health, etc.)
- **targeting\_inference** - Likely target audience based on creative and messaging
- **creative\_strategy** - Creative approach (urgency, social proof, benefit-led, storytelling, discount stacking)
- **key\_messages** - Array of the 3 main messages the ad communicates
- **competitive\_score** - Integer 1-10 reflecting hook strength, clarity, and CTA effectiveness
- **summary** - 2-3 sentence competitive positioning assessment

Default models per provider: OpenRouter `google/gemini-2.0-flash-001`, Anthropic `claude-sonnet-4-20250514`, Google `gemini-2.0-flash`, OpenAI `gpt-4o-mini`, Ollama `llama3.1`.

#### Data Freshness

The Ad Library is updated approximately every 24 hours by Meta. Spend and impressions data are estimates with lower/upper bound ranges - exact figures are never exposed. Ad start/stop times are accurate to the day.

***

### Integrations

Pair this actor with others in the harvestlab suite for full social and competitive intelligence pipelines:

- **[Reddit Scraper](https://apify.com/harvestlab/reddit-scraper)** - Compare what brands say in Facebook ads vs. what communities say on Reddit. The gap between paid messaging and organic conversation surfaces authenticity risks and PR landmines.
- **[YouTube Scraper](https://apify.com/harvestlab/youtube-scraper)** - Cross-reference Facebook ad spend signals with YouTube video performance for the same brand. Identify whether brands are running integrated paid social + video strategies.
- **[Contact Extractor](https://apify.com/harvestlab/contact-extractor)** - Combine ad intelligence with contact extraction: pull emails, LinkedIn profiles, and tech-stack signals from the advertiser's landing page domain to build targeted B2B prospect lists.
- **[News Monitor](https://apify.com/harvestlab/news-monitor)** - Pair ad spend signals with Google News coverage on the same brand. Distinguish paid amplification from organic media attention.
- **[Google Search Scraper](https://apify.com/harvestlab/google-search-scraper)** - Correlate Facebook ad creative themes with branded SERP ownership. See whether a brand's paid social narrative is winning on search too.

***

### Scheduling and Automation

Schedule weekly competitor ad-monitoring runs in Apify Console under Schedules to track when rivals launch new campaigns or change spend. Connect a `webhookUrl` in n8n or Make to push new ad creatives into a Slack channel or Airtable swipe file the moment a run finishes. Build a living competitive intelligence archive without manual checks.

***

### Legal and Compliance

#### Facebook Ad Library Terms of Service

The Facebook Ad Library is a **public transparency database** mandated by Meta under their political advertising disclosure policies. Access to the public interface and the Ad Library API is governed by:

- [Meta's Terms of Service](https://www.facebook.com/terms.php)
- [Facebook Ad Library API Terms of Service](https://www.facebook.com/ads/library/api/)

Users are responsible for ensuring their use of scraped data complies with Meta's ToS and applicable laws. This actor is designed for legitimate use cases including academic research, competitive intelligence, journalism, and political transparency monitoring.

#### Political Advertising Data

Political and issue ad data is publicly disclosed by law - Meta is legally required to make this data available for transparency purposes. If you are a journalist, researcher, or transparency organization using this data for public interest purposes, document your methodology and data retention policies. If you are a political campaign or advocacy organization, ensure compliance with applicable campaign finance and disclosure laws.

#### API Terms

If using the official Graph API path: use of the `ads_archive` endpoint is subject to Meta's Platform Terms and Data Policy. Do not redistribute raw API data commercially without Meta's authorization.

#### GDPR and Data Protection

The Ad Library contains advertiser information (page names, page IDs) and aggregate demographic targeting data. This data is deliberately made public by Meta for transparency purposes and is anonymized at the individual level - no personal user data is exposed. Store and process scraped data in accordance with GDPR, CCPA, and other applicable data protection regulations. Do not use this data to build targeted marketing lists against individual Facebook users.

#### No Warranty

This actor accesses publicly available data and is provided as-is. The actor authors make no warranty that the data is complete, accurate, or up to date. Meta may change the Ad Library interface or API at any time.

***

### Pricing

This actor uses **pay-per-event** pricing - you only pay for what you scrape.

| Event | Price | When it fires |
|-------|-------|--------------|
| `ad-scraped` | $0.005 | Each ad record extracted from the Ad Library |
| `ai-analysis-completed` | $0.005 | Per ad when AI competitive analysis runs |

**Comparison with commercial alternatives:**

- Supermetrics: $99/mo for Facebook Ads connector
- Funnel.io: $399/mo
- AdSpy: $149/mo with export restrictions
- Pathmatics / Sensor Tower: $1,000+/mo enterprise contracts

This actor: $0.005/ad with no subscription, no developer approval wait, and no monthly minimum. A 1,000-ad competitive sweep costs $5.00. The same sweep in AdSpy would require a $149/mo subscription.

**x402-ready** - supports micropayment-per-use via Apify's pay-per-event infrastructure.

***

### About

Built by an independent developer as part of a portfolio of Apify Actors for data extraction and competitive intelligence. For support, feature requests, or data quality issues, contact the actor author through the Apify Store.

# Actor input Schema

## `searchQuery` (type: `string`):

Keyword, brand name, or topic to search in the Facebook Ad Library.

## `advertiserName` (type: `string`):

Optional: filter results by a specific advertiser's Facebook page name.

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

ISO country code (e.g. US, GB, DE) or ALL to search globally.

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

Filter by ad type category.

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

Filter by whether ads are currently active.

## `maxResults` (type: `integer`):

Maximum number of ads to scrape.

## `facebookAccessToken` (type: `string`):

Facebook Graph API access token for the official Ad Library API (recommended). Get yours at https://developers.facebook.com. Without this, the actor falls back to web scraping (requires residential proxy).

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

Proxy settings. Residential proxy strongly recommended for web scraping fallback.

## `enableAiAnalysis` (type: `boolean`):

Use an LLM to analyze each ad for category, target audience inference, creative strategy, key messages, and competitive score (1-10). Adds $0.005/ad.

## `llmProvider` (type: `string`):

AI provider to use for ad analysis.

## `llmModel` (type: `string`):

Override the default model for your chosen provider. Leave blank to use the recommended default.

## `openrouterApiKey` (type: `string`):

API key for OpenRouter. Get yours at https://openrouter.ai/keys

## `anthropicApiKey` (type: `string`):

API key for Anthropic Claude. Get yours at https://console.anthropic.com/settings/keys

## `googleApiKey` (type: `string`):

API key for Google Gemini. Get yours at https://aistudio.google.com/app/apikey

## `openaiApiKey` (type: `string`):

API key for OpenAI. Get yours at https://platform.openai.com/api-keys

## `ollamaBaseUrl` (type: `string`):

Base URL for your local Ollama instance. Install at https://ollama.com/download

## `q` (type: `string`):

Alias for searchQuery.

## `maxItems` (type: `integer`):

Alias for maxResults.

## Actor input object example

```json
{
  "country": "ALL",
  "adType": "ALL",
  "activeStatus": "active",
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "enableAiAnalysis": false,
  "llmProvider": "openrouter",
  "ollamaBaseUrl": "http://localhost:11434"
}
```

# Actor output Schema

## `datasetOutput` (type: `string`):

Dataset containing scraped Facebook and Instagram ad records plus optional AI analysis records.

# 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 = {
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("harvestlab/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 = { "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    } }

# Run the Actor and wait for it to finish
run = client.actor("harvestlab/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 '{
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call harvestlab/facebook-ads-library-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Facebook Ads Library Scraper",
        "description": "Programmatic access to Meta Ad Library. Extract ad creative, spend ranges, impressions, demographic targeting, and active status for any advertiser or keyword. Official Graph API v21.0 + web fallback. AI analysis via 5 LLM providers. $0.005/ad PPE.",
        "version": "0.1",
        "x-build-id": "JyWXeo21HMiOxRNK1"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/harvestlab~facebook-ads-library-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-harvestlab-facebook-ads-library-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/harvestlab~facebook-ads-library-scraper/runs": {
            "post": {
                "operationId": "runs-sync-harvestlab-facebook-ads-library-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/harvestlab~facebook-ads-library-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-harvestlab-facebook-ads-library-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "searchQuery"
                ],
                "properties": {
                    "searchQuery": {
                        "title": "Search Query",
                        "type": "string",
                        "description": "Keyword, brand name, or topic to search in the Facebook Ad Library."
                    },
                    "advertiserName": {
                        "title": "Advertiser Page Name",
                        "type": "string",
                        "description": "Optional: filter results by a specific advertiser's Facebook page name."
                    },
                    "country": {
                        "title": "Country",
                        "type": "string",
                        "description": "ISO country code (e.g. US, GB, DE) or ALL to search globally.",
                        "default": "ALL"
                    },
                    "adType": {
                        "title": "Ad Type",
                        "enum": [
                            "ALL",
                            "POLITICAL_AND_ISSUE_ADS"
                        ],
                        "type": "string",
                        "description": "Filter by ad type category.",
                        "default": "ALL"
                    },
                    "activeStatus": {
                        "title": "Active Status",
                        "enum": [
                            "all",
                            "active",
                            "inactive"
                        ],
                        "type": "string",
                        "description": "Filter by whether ads are currently active.",
                        "default": "active"
                    },
                    "maxResults": {
                        "title": "Maximum Results",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Maximum number of ads to scrape.",
                        "default": 50
                    },
                    "facebookAccessToken": {
                        "title": "Facebook Access Token",
                        "type": "string",
                        "description": "Facebook Graph API access token for the official Ad Library API (recommended). Get yours at https://developers.facebook.com. Without this, the actor falls back to web scraping (requires residential proxy)."
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "Proxy settings. Residential proxy strongly recommended for web scraping fallback."
                    },
                    "enableAiAnalysis": {
                        "title": "Enable AI Analysis",
                        "type": "boolean",
                        "description": "Use an LLM to analyze each ad for category, target audience inference, creative strategy, key messages, and competitive score (1-10). Adds $0.005/ad.",
                        "default": false
                    },
                    "llmProvider": {
                        "title": "LLM Provider",
                        "enum": [
                            "openrouter",
                            "anthropic",
                            "google",
                            "openai",
                            "ollama"
                        ],
                        "type": "string",
                        "description": "AI provider to use for ad analysis.",
                        "default": "openrouter"
                    },
                    "llmModel": {
                        "title": "LLM Model Override",
                        "type": "string",
                        "description": "Override the default model for your chosen provider. Leave blank to use the recommended default."
                    },
                    "openrouterApiKey": {
                        "title": "OpenRouter API Key",
                        "type": "string",
                        "description": "API key for OpenRouter. Get yours at https://openrouter.ai/keys"
                    },
                    "anthropicApiKey": {
                        "title": "Anthropic API Key",
                        "type": "string",
                        "description": "API key for Anthropic Claude. Get yours at https://console.anthropic.com/settings/keys"
                    },
                    "googleApiKey": {
                        "title": "Google AI API Key",
                        "type": "string",
                        "description": "API key for Google Gemini. Get yours at https://aistudio.google.com/app/apikey"
                    },
                    "openaiApiKey": {
                        "title": "OpenAI API Key",
                        "type": "string",
                        "description": "API key for OpenAI. Get yours at https://platform.openai.com/api-keys"
                    },
                    "ollamaBaseUrl": {
                        "title": "Ollama Base URL",
                        "type": "string",
                        "description": "Base URL for your local Ollama instance. Install at https://ollama.com/download",
                        "default": "http://localhost:11434"
                    },
                    "q": {
                        "title": "Search Query (alias)",
                        "type": "string",
                        "description": "Alias for searchQuery."
                    },
                    "maxItems": {
                        "title": "Max Items (alias)",
                        "type": "integer",
                        "description": "Alias for maxResults."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
