# Facebook Ad Library Scraper (Meta Ads Library) (`xmolodtsov/facebook-ads-library-scraper`) Actor

Scrape the Facebook Ads Library (Meta Ad Library) by keyword, page ID or URL: ad copy, images, videos, CTAs, landing pages, dates, platforms and page info, plus EU reach, targeting and payer data. Every ad in a group, deduplicated. No login, cookies or proxy setup.

- **URL**: https://apify.com/xmolodtsov/facebook-ads-library-scraper.md
- **Developed by:** [Yevhenii Molodtsov](https://apify.com/xmolodtsov) (community)
- **Categories:** Social media, Marketing, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.55 / 1,000 ad 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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

![Facebook Ad Library Scraper (Meta Ads Library) logo](https://api.apify.com/v2/key-value-stores/2DxCOvbMjhvK3S1qP/records/facebook-ads-library-scraper-avatar-128)

### What does Facebook Ad Library Scraper do?

Facebook Ad Library Scraper collects ads from the public Facebook Ad Library, also called the
[Meta Ads Library](https://www.facebook.com/ads/library/), by keyword, Facebook page ID or pasted Ad Library URL. Every
ad comes back as one row with its copy, headline, call to action, landing page, image and video URLs, carousel cards,
dates, platforms and advertiser page. Turn on ad details to add EU reach with its age, gender and country breakdown,
targeting, and who paid for the ad.

#### Use cases

- **Competitor creative research:** pull the active ads the Ad Library shows for a rival brand in your country, with copy,
  call to action, landing page and media, and keep them as a swipe file.
- **Agency client reporting:** schedule a weekly run on a client's or competitor's page ID and see which ads started,
  stopped or changed format.
- **Ad-spy and lead-gen tools:** run a keyword list such as "shopify" or "dropshipping" through the API every day and
  get the advertisers and landing pages behind each ad.
- **Political ad research:** collect issue and election ads for one country and date window, with spend and impression
  ranges, audiences and payers.

#### Why this Facebook Ads Library scraper

- **No Facebook account.** It reads the Ad Library logged out: no login, cookies or tokens. Proxies are built in and
  included in the price.
- **EU reach and payer data at no extra charge.** Reach by country, age and gender, targeting, payer and beneficiary
  cost the same as a plain ad.
- **Every ad in a group.** Meta collapses near-identical ads into one result ("24 ads use this creative"). This scraper
  returns each as its own row: 3.5× more ads than one row per group on a broad search like "shopify".
- **Deduplicated, stable columns.** Each ad appears once per run and is never billed twice. Meta's own field names,
  with every detail key on every row (`null` when details are off).
- **Honest run status.** A blocked run ends FAILED with a reason code, never as a quiet empty dataset.

### What data you get

| Field | Example | Description |
|---|---|---|
| `ad_archive_id`, `ad_library_url` | `2858097847888338` | The ad's ID and its Ad Library link |
| `page_id`, `page_name` | `Sneakerjagers Deutschland` | The advertiser's Facebook page |
| `is_active` | `true` | Whether the ad is running now |
| `start_date_formatted`, `end_date_formatted` | `2026-08-29T07:00:00.000Z` | Start and end (also `start_date`, `end_date` in Unix seconds) |
| `publisher_platform` | `["FACEBOOK", "INSTAGRAM"]` | Facebook, Instagram, Messenger, Threads, Audience Network |
| `snapshot.body.text`, `snapshot.title` | `Nike V5 RNR` | Ad copy and headline |
| `snapshot.link_url` | `https://sneakerjagers.com/d/dRgK4E` | Landing page |
| `snapshot.cta_text`, `snapshot.cta_type` | `Shop now`, `SHOP_NOW` | Call-to-action button |
| `snapshot.display_format` | `IMAGE` | `IMAGE`, `VIDEO`, `CAROUSEL`, `DCO`, `DPA` and more |
| `snapshot.images[]`, `snapshot.videos[]` | `https://scontent…fbcdn.net/…jpg` | Full-size and 600 px images; HD and SD videos with preview image |
| `snapshot.cards[]` | | Carousel and catalog cards, each with its own text, link and media |
| `snapshot.page_like_count` | `112840` | Page likes, plus page categories, profile link and picture |
| `collation_id`, `collation_count` | `4` | Meta's group of near-identical ads and its size |
| `categories`, `spend`, `impressions_with_index` | `">$1M"` | `POLITICAL` marks issue and political ads; only those carry spend and impression ranges |
| `position`, `inputUrl` | `6`, `nike` | Rank in Meta's results, and the input that found the ad |

**With ad details on:**

| Field | Example | Description |
|---|---|---|
| `eu_total_reach` | `1700174` | Total EU reach (also in `aaa_info`) |
| `transparency_by_location.eu_transparency` | `DE`, `25-34`, `male: 196543` | Reach by country, age and gender, plus targeted locations, ages and gender |
| `aaa_info.payer_beneficiary_data` | `Sneakerjagers B.V.` | Who paid for the ad and who benefits |
| `advertiser.ad_library_page_info` | `ig_followers: 8662` | Page likes, Instagram account and followers, category, verification |
| `insights` | | Political and issue ads: audience by age, gender and region |

Meta publishes reach and targeting only for ads delivered in the EU, so `eu_total_reach` is `null` for ads that ran
only elsewhere.

### How to scrape Facebook ads from the Ad Library

1. Click **Try for free** and open the **Input** tab.
2. Enter **Search terms**, **Facebook page IDs** or **Ad Library URLs**, pick a country and filters, and set
   **Maximum ads**. Switch on **Scrape ad details** for EU reach, targeting and payer data.
3. Click **Start**, then export the ads from the **Output** tab as JSON, CSV or Excel.

Tip: search the Ad Library in your browser, then paste the URL from the address bar into **Ad Library URLs** to reuse
its filters.

Via API, run synchronously and get the ads back in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/xmolodtsov~facebook-ads-library-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms": ["nike"], "country": "US", "maxItems": 20}'
```

AI agents can call it as a tool through the Apify MCP server as `xmolodtsov/facebook-ads-library-scraper` (see
Integrations below).

### Pricing

Pay per result: you pay only for ads delivered to your dataset. Platform usage and proxies are included, with no
separate usage charge.

| Apify plan | Price per 1,000 ads |
|---|---|
| Free | $0.90 |
| Bronze (Starter) | $0.75 |
| Silver (Scale) | $0.65 |
| Gold (Business), Platinum, Diamond | $0.55 |

- **No start fee:** a run that finds nothing costs nothing.
- **Ad details and every ad in a group included** at the same per-ad price.
- **Duplicates never charged:** an ad found under several search terms is billed once.
- **Spending cap respected:** set a maximum cost per run and the scraper stops when it is reached.

Example: 5,000 ads with details on the Silver plan cost $3.25.

#### Is it free?

You can try it on the free Apify plan, with limits set by the developer, not by Apify: **10 ads per run** and
**5 runs per calendar month** per account, resetting on the 1st (UTC). A capped run ends SUCCEEDED and its status message
shows how many free runs you have used. Once all 5 are used, a run ends SUCCEEDED with no ads and a status message saying
why. Any paid Apify plan removes both limits.

### Input

Fill in at least one of **Search terms**, **Facebook page IDs** or **Ad Library URLs**.

| Field | Default | What it does |
|---|---|---|
| `searchTerms` | | Keywords; each term is its own Ad Library search |
| `pageIds` | | Numeric Facebook page IDs; returns the ads that page runs |
| `urls` | | Search, page or single-ad (`?id=`) Ad Library URLs. Each keeps its own filters; the fields below don't apply to it |
| `country` | `ALL` | `ALL` or one 2-letter country code (`US`, `GB`, `DE` …) |
| `adType` | `all` | `all`, `political_and_issue_ads`, `housing_ads`, `employment_ads`, `credit_ads` |
| `activeStatus` | `active` | `active`, `inactive` or `all` |
| `mediaType` | `all` | `all`, `image`, `video`, `meme`, `image_and_meme`, `none` |
| `searchType` | `keyword_unordered` | Any of the words, or `keyword_exact_phrase` (search terms only) |
| `startDate`, `endDate` | | `YYYY-MM-DD`: ads that had impressions in this window, not only ads that started in it |
| `sortBy` | `impressions_desc` | `impressions_desc`, `impressions_asc` or `most_recent` |
| `maxItems` | `100` | Unique ads across the whole run (free plan: capped at 10) |
| `maxItemsPerQuery` | no cap | Optional cap per search term, page ID or URL |
| `expandAdGroups` | `true` | Every ad in a group as its own row; `false` = one row per group |
| `scrapeAdDetails` | `false` | Adds EU reach, targeting, payer and advertiser info; slower, no extra charge |

The form takes one country per run; for several, paste one Ad Library URL per country. Inputs written for other Ad
Library tools carry over: `startUrls` works as `urls`, `keywords` as `searchTerms`, and `count` or `resultsLimit` as
`maxItems`.

Example: video ads shown in the UK in September, newest first, for the exact phrase "running shoes" and for Nike's
page (the filters apply to both), with ad details, plus one single ad by URL:

```json
{
    "searchTerms": ["running shoes"],
    "searchType": "keyword_exact_phrase",
    "country": "GB",
    "mediaType": "video",
    "startDate": "2026-09-01",
    "endDate": "2026-09-30",
    "sortBy": "most_recent",
    "pageIds": ["15087023444"],
    "urls": [{ "url": "https://www.facebook.com/ads/library/?id=925321173274919" }],
    "scrapeAdDetails": true,
    "maxItems": 300,
    "maxItemsPerQuery": 150
}
```

### Output

Each ad is one dataset item. The **Overview** table in the Output tab shows the key fields; exports carry every field.
Real rows from a run with search "moda", country Italy and ad details on:

![Facebook Ad Library Scraper (Meta Ads Library) output: page, headline, CTA, format, start date, platforms, EU reach, audience and payer](https://api.apify.com/v2/key-value-stores/2DxCOvbMjhvK3S1qP/records/facebook-ads-library-scraper-output-table.png)

One item, trimmed (long URLs shortened, many keys left out):

```json
{
    "ad_archive_id": "2858097847888338",
    "ad_library_url": "https://www.facebook.com/ads/library/?id=2858097847888338",
    "page_id": "632738836863808",
    "page_name": "Sneakerjagers Deutschland",
    "is_active": true,
    "collation_count": 1,
    "start_date_formatted": "2026-08-29T07:00:00.000Z",
    "publisher_platform": ["FACEBOOK", "INSTAGRAM", "MESSENGER", "THREADS"],
    "spend": null,
    "snapshot": {
        "body": { "text": "NEU EINGETROFFEN. Der Nike V5 RNR „Burgundy Crush“ ist jetzt erhältlich! …" },
        "title": "Nike V5 RNR",
        "cta_text": "Shop now",
        "display_format": "IMAGE",
        "link_url": "https://sneakerjagers.com/d/dRgK4E",
        "images": [{ "original_image_url": "https://scontent.fksc1-1.fna.fbcdn.net/…_n.jpg?…" }],
        "page_like_count": 112840
    },
    "position": 6,
    "inputUrl": "nike",
    "aaa_info": {
        "payer_beneficiary_data": [{ "payer": "Sneakerjagers B.V.", "beneficiary": "Sneakerjagers B.V." }]
    },
    "transparency_by_location": {
        "eu_transparency": {
            "location_audience": [{ "name": "Germany", "type": "countries", "excluded": false }],
            "age_audience": { "min": 18, "max": 65 },
            "age_country_gender_reach_breakdown": [
                { "country": "DE", "age_gender_breakdowns": [{ "age_range": "25-34", "male": 196543, "female": 161477 }] }
            ]
        }
    },
    "eu_total_reach": 1700174
}
```

#### Coming from a scraper that outputs camelCase fields?

This scraper keeps Meta's original snake_case names. Map your columns once:

| camelCase field | Field in this scraper |
|---|---|
| `adArchiveID` | `ad_archive_id` |
| `pageID` | `page_id` |
| `pageName` | `page_name` |
| `startDate` | `start_date` (Unix seconds) or `start_date_formatted` (ISO 8601) |
| `endDate` | `end_date` (Unix seconds) or `end_date_formatted` (ISO 8601) |
| `publisherPlatform` | `publisher_platform` |
| `snapshot.body.text` | `snapshot.body.text` (unchanged) |
| `snapshot.linkUrl` | `snapshot.link_url` |
| `snapshot.ctaText` | `snapshot.cta_text` |
| `snapshot.displayFormat` | `snapshot.display_format` |
| `isActive` | `is_active` |
| `collationCount` | `collation_count` |

### Guarantees and failure semantics

- **SUCCEEDED with ads:** "N ads scraped." If a query fails partway or another query fails, the run keeps the ads it
  got and the status message adds, for example, "1/3 queries stopped early (blocked)". Each query's `failureReason`
  is in `STATISTICS`.
- **SUCCEEDED with "No results":** Meta answered and the search has no matches.
- **FAILED, 0 ads:** Meta blocked or errored. The status message starts with a machine token, such as
  `blocked: 0 ads — …`, so your integration can retry.
- **FAILED with `outdated: …`:** Meta occasionally rotates the private query IDs behind the Ad Library, and the
  scraper rediscovers them automatically. If that self-heal fails, the run fails, never ending as an empty success,
  and the scraper needs an update.
- **Ads pushed before a failure stay in the dataset.**

| Token | Meaning | What to do |
|---|---|---|
| `blocked` | Meta refused or rate-limited every retry | Retry later |
| `network`, `timeout`, `server` | Connection or server errors on every retry | Retry |
| `quota`, `geo` | Meta answered HTTP 429 (too many requests) or 451 (unavailable in that region) | Retry later |
| `invalid` | Bad input, such as a non-numeric page ID (the field is named), or Meta rejected the request shape | Fix the input; if the input is fine, report it |
| `outdated` | Meta changed the Ad Library and the automatic fix failed | Report it in the Issues tab |
| `unknown` | Any other error; the log has the details | Retry, then report it with the run ID |

Per-query numbers, including Meta's own total per query (`totalCount`), are in the run's `STATISTICS` record.

### Integrations

- **API:** the [Apify API](https://apify.com/xmolodtsov/facebook-ads-library-scraper/api) and the JavaScript and Python
  clients, for example:

  ```js
  import { ApifyClient } from 'apify-client';

  const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
  const run = await client.actor('xmolodtsov/facebook-ads-library-scraper').call({ pageIds: ['15087023444'], maxItems: 100 });
  const { items } = await client.dataset(run.defaultDatasetId).listItems();
  ```

- **AI agents (MCP):** connect any MCP client to `https://mcp.apify.com?tools=xmolodtsov/facebook-ads-library-scraper`
  and ask "what ads is this brand running in Germany right now?"

- **n8n, Make, Zapier:** run the scraper with the Apify node or app and pass the ads on.

- **Schedules and webhooks:** re-run a search daily and get notified when results are ready.

### More scrapers from this developer

**TikTok:** [TikTok Search Scraper](https://apify.com/xmolodtsov/tiktok-search-scraper): videos and creators for any keyword, pay per result · [TikTok Profile Scraper (Pay Per Result)](https://apify.com/xmolodtsov/tiktok-profile-scraper): profiles, followers and latest posts by username · [TikTok Comments Scraper](https://apify.com/xmolodtsov/tiktok-comments-scraper): comments and full reply threads from any video · [TikTok Hashtag Scraper](https://apify.com/xmolodtsov/tiktok-hashtag-scraper): videos for any hashtag, with views, likes and music · [TikTok Sound & Music Scraper](https://apify.com/xmolodtsov/tiktok-sound-scraper): videos that use a sound or song

**Social & news:** [Reddit Search Scraper](https://apify.com/xmolodtsov/reddit-scraper): posts by keyword, subreddit or author · [Google News Scraper](https://apify.com/xmolodtsov/google-news-scraper): Google News results as clean full-text articles

**E-commerce:** [Prom.ua Product Search Scraper](https://apify.com/xmolodtsov/prom-ua): Prom.ua product search results, no browser needed · [Amazon Product Search & Bestsellers Scraper](https://apify.com/xmolodtsov/amazon-search-scraper): search results, Best Sellers and product details from Amazon

**Maps & leads:** [Google Maps Scraper](https://apify.com/xmolodtsov/google-maps-scraper): places, leads and emails from Google Maps

**Video:** [YouTube Transcript Scraper](https://apify.com/xmolodtsov/youtube-transcript-scraper): transcripts, subtitles and captions from YouTube videos

### FAQ

#### How many ads can I get per search?

Meta serves 30 results per page, and the scraper keeps paging until Meta runs out or **Maximum ads** is reached; deep
paging was measured at more than 6,000 unique ads for one keyword. For very large pulls, split by country or date
window and set **Maximum ads per query**.

#### Why did I get fewer ads than Maximum ads?

Meta has fewer results for your filters; duplicates were removed; Meta listed fewer group members than
`collation_count` says (4 of 180 groups in our tests); **Maximum ads per query** or your maximum cost per run stopped a query;
or the free plan capped the run at 10 ads.

#### What do the sort options do?

"Most recent" is Meta's own order, grouped by month, so sort by `start_date` after export for a strict order.
Impression sorting only reorders political and issue ads, the only ads Meta reports impressions for.

#### Why are spend and impressions null?

Meta publishes `spend`, `impressions_with_index` and `reach_estimate` only for political and issue ads, as ranges. For
other ads they are `null`: that is the Ad Library's data, not a scraping gap. For commercial ads shown in the EU, turn on
ad details and use `eu_total_reach`.

#### Can I find a page ID from a page name?

Not logged out: Meta resolves advertiser names only for logged-in users. Open the advertiser's ads in the Ad Library and
copy the number after `view_all_page_id=`, or paste the whole URL into **Ad Library URLs**. A keyword search for the
brand also shows its `page_id`.

#### Do image and video links expire?

Yes. Media URLs are signed Meta CDN links that stop working after a while, so download what you want to keep soon after
the run. `ad_library_url` stays valid.

#### Why does a headline show `{{product.name}}`?

That is a catalog ad (`display_format: "DPA"`), a template Meta fills in per viewer. The actual products, each with
title, link and image, are in `snapshot.cards`.

#### How is this different from the official Meta Ad Library API?

The official API needs a developer app, identity verification and an access token, covers only political and issue ads
plus ads delivered in the EU and UK, and returns a snapshot link instead of media files. This scraper reads the public
Ad Library website: no app review or access token, commercial ads from any country, and direct image and video URLs.

#### Is it legal to scrape the Facebook Ads Library?

This scraper collects only what the Ad Library shows to a visitor who is not logged in. It never logs in and uses no
cookies or accounts.

- **Public by law.** Under the EU Digital Services Act (Article 39), very large online platforms must keep a public,
  searchable repository of the ads they show in the EU. Meta's Ad Library is that repository.
- **Court precedent.** A 2024 US court ruling (N.D. Cal., January) found that logged-off scraping of public data did
  not breach Meta's terms. It is a district-court ruling and does not settle every question everywhere.
- **Personal data.** Payer and beneficiary names can identify a person, such as a sole trader or a politician, which
  makes them personal data under the GDPR and similar laws such as the CCPA. You need your own lawful basis to process
  them.

This is general information, not legal advice. If you are unsure whether your use is lawful, consult a lawyer.

### Support

Found a bug or need a field? Open an issue in the **Issues** tab on this page and include the run ID.

# Changelog

This Actor's version history is a separate document: https://apify.com/xmolodtsov/facebook-ads-library-scraper/changelog.md

# Actor input Schema

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

Keywords to search the Ad Library for, such as a brand (nike), a product (running shoes) or a topic. Each term runs as its own search. Fill in at least one search term, page ID or Ad Library URL.

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

Numeric Facebook page IDs; returns the ads that page runs. Copy the number after view_all_page_id= in the page's Ad Library URL. Page names don't work: Meta resolves them only for logged-in visitors.

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

Where the ads were shown: ALL, or one 2-letter country code such as US, GB, DE, FR or BR. Applies to search terms and page IDs. For several countries, paste one Ad Library URL per country.

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

Stop after this many unique ads across the whole run. You pay only for ads delivered. Free Apify plan: capped at 10 ads per run (and 5 runs per calendar month), a limit set by the developer, not by Apify.

## `scrapeAdDetails` (type: `boolean`):

Adds the ad's detail panel: EU total reach with the age, gender and country breakdown, targeting, payer and beneficiary, and the advertiser's page info (likes, Instagram, category). Meta publishes reach and targeting only for ads shown in the EU. Slower, no extra charge.

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

Search, page or single-ad (?id=) URLs copied from facebook.com/ads/library. Each URL keeps its own filters (country, ad type, status, media, dates, sort, language); the Country field and the filter fields below don't apply to URLs.

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

Meta's Ad Library category. Only political and issue ads carry spend and impression ranges.

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

Ads running now, ads that have stopped, or both.

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

Only ads with this kind of creative.

## `searchType` (type: `string`):

How search terms match the ad text: any of the words, or the exact phrase. Applies to search terms only.

## `startDate` (type: `string`):

Only ads that had impressions on or after this date (YYYY-MM-DD), not only ads that started then. Leave empty for no limit.

## `endDate` (type: `string`):

Only ads that had impressions on or before this date (YYYY-MM-DD). Leave empty for no limit.

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

Result order. Most recent is Meta's month-grouped order. Meta reports impressions only for political and issue ads, so low to high reorders only those.

## `maxItemsPerQuery` (type: `integer`):

Optional cap per search term, page ID or URL, so one big query can't use up the whole run. Leave empty for no cap.

## `expandAdGroups` (type: `boolean`):

Meta groups near-identical ads into one result ("24 ads use this creative"). On: one row per ad, every variant included. Off: one row per group. Each delivered ad is priced the same.

## Actor input object example

```json
{
  "searchTerms": [
    "nike"
  ],
  "country": "US",
  "maxItems": 20,
  "scrapeAdDetails": false,
  "adType": "all",
  "activeStatus": "active",
  "mediaType": "all",
  "searchType": "keyword_unordered",
  "sortBy": "impressions_desc",
  "expandAdGroups": true
}
```

# Actor output Schema

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

One item per unique ad: Meta's full Ad Library record (snapshot with copy, media and links, dates, platforms, page info) plus ad details when enabled.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchTerms": [
        "nike"
    ],
    "country": "US",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("xmolodtsov/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 = {
    "searchTerms": ["nike"],
    "country": "US",
    "maxItems": 20,
}

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

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

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

```

## CLI example

```bash
echo '{
  "searchTerms": [
    "nike"
  ],
  "country": "US",
  "maxItems": 20
}' |
apify call xmolodtsov/facebook-ads-library-scraper --silent --output-dataset

```

## MCP server setup

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