# Facebook Ad Library Scraper Pro (`constructive_calm/facebook-ad-library-pro`) Actor

Scrape Facebook Ads Library by keyword, page URL, or advertiser name. Returns full creative + CTA + linkUrl + advertiser identity + active dates. 35% cheaper than the leading alternative. No login required, country dropdown, multi-platform/media filters, resume checkpoints.

- **URL**: https://apify.com/constructive_calm/facebook-ad-library-pro.md
- **Developed by:** [Omar Eldeeb](https://apify.com/constructive_calm) (community)
- **Categories:** Social media, Lead generation, E-commerce
- **Features:** Limited permissions
- **Stats:** 483 total users, 44 monthly users, 100.0% runs succeeded, 4 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.49 / 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.

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 Pro — Keyword + Page + Advertiser Search

Scrape **Facebook's public Ad Library** — every ad currently or recently running across Facebook, Instagram, Messenger, and Audience Network. Search by keyword, by page URL, or by advertiser name. Get CTA text, link URLs, full creative (image/video), advertiser info, and active dates.

**$0.49 per 1,000 ads.** No actor-start fee — you pay only for ads delivered.

> No Facebook login required. No developer-app approval. Works on commercial ads, not just political. Country dropdown with 50+ ISO codes. Resume checkpoints pick up an interrupted run where it stopped.

### What does Facebook Ad Library Scraper Pro do?

It pulls structured data from `facebook.com/ads/library` — the public archive of every ad Meta has run on Facebook, Instagram, Messenger, WhatsApp, Threads, and the Audience Network. Unlike the [official Meta Ad Library API](https://www.facebook.com/ads/library/api/) (political/issue ads only, EU-only, no creative or link data), this actor returns full commercial ads with CTA, link URLs, body text, creatives, and advertiser identity.

Built for marketers, competitive intel analysts, agencies, and researchers who need the same insights Meta surfaces in the Ad Library UI — but at scale, in JSON/CSV/Excel.

### Why use Facebook Ad Library Scraper Pro?

- **$0.49 per 1,000 ads.** No actor-start fee. Compare: the most popular community Facebook Ad Library scraper on the Apify Store charges $0.75 per 1,000 results (Store price checked 2026-09-29).
- **Three input modes in one actor.** Paste Ad Library search URLs, raw Facebook page URLs (vanity or `profile.php?id=...`), or just type a `keyword` / `advertiserName` and we'll build the right URL for you.
- **Country dropdown with names, not codes.** Pick "United States (US)" instead of typing `us` or `US` and hoping. Or use the Custom country code field for any of the 240+ ISO-3166 codes.
- **Multi-platform + media-type filters as first-class fields.** Filter by FACEBOOK / INSTAGRAM / MESSENGER / AUDIENCE_NETWORK / THREADS / WHATSAPP and image / video / meme / text-only.
- **CSV-ready output.** Every creative URL, CTA, link, and advertiser field is emitted as a flat column (`linkUrl`, `ctaText`, `imageUrl1..5`, `videoUrl1`) — your Sheets import just works. Nested objects preserved for power users.
- **Dedup'd advertiser About cache.** Resolve an advertiser's verified status, categories, and profile pic *once per page* across the whole run — not once per ad. Saves you money on bulk page scrapes.
- **Resume checkpoints.** Run timed out, crashed, or stopped? Restart it within 6 hours with the same input — we resume from the last cursor instead of re-charging you for already-scraped ads. A run that finished normally is never resumed, so re-running the same search always returns the full result set.
- **EU reach + AAA targeting (optional).** Toggle on `Scrape ad details` to get demographic reach (age × gender × country) and AAA audience metadata for ads Meta labels political or social-issue.
- **Residential proxy built-in.** Default proxy config rotates per request, avoiding the CAPTCHA traps that kill datacenter scrapes.

### How to use Facebook Ad Library Scraper Pro

1. Open the Apify Console and click **Try for free**.
2. Pick a search style — fastest is to type a **Keyword** (e.g., `nike`) or **Advertiser name** (e.g., `Spotify`) and pick a **Country**.
3. Or paste **URLs** — Ad Library search URLs (`https://www.facebook.com/ads/library/?...`) or raw Facebook page URLs (`https://www.facebook.com/ZapierApp`). One per line. A page URL returns only that page's ads: the actor looks up the page's Ad Library ID first. This works for vanity URLs, `profile.php?id=…`, `/people/<Name>/<id>/` and numeric URLs on any Facebook host (`www.`, `web.`, `m.`, `mbasic.`, language subdomains, `fb.me`). If the ID can't be looked up (for example an age-restricted brand page), the actor searches the Ad Library by page name and keeps only ads from that exact page. If that finds nothing, the input returns 0 ads with a warning in the log and the run status, and nothing is charged for it. You never get ads from a different advertiser with a similar name.
4. Set **Total ads cap** (across the whole run) and/or **Limit per input URL** to control spend.
5. (Optional) Enable **Scrape ad details** for EU reach, **Resolve advertiser About** for page-level verification + categories.
6. Click **Save & Start**.
7. When the run finishes, export the dataset as **JSON, CSV, or Excel** from the Storage tab.

### Input examples

**Keyword search (cheapest, fastest):**

```json
{
  "keyword": "nike",
  "country": "US",
  "mediaType": "video",
  "count": 500
}
```

**Page URL — vanity slug:**

```json
{
  "urls": ["https://www.facebook.com/ZapierApp"],
  "limitPerSource": 200
}
```

**Multiple pages + global cap:**

```json
{
  "urls": [
    "https://www.facebook.com/ZapierApp",
    "https://www.facebook.com/Spotify",
    "https://www.facebook.com/airbnb"
  ],
  "count": 1000,
  "resolveAdvertiser": true
}
```

**Advertiser-name search across all of Europe with date filter:**

```json
{
  "advertiserName": "Adidas",
  "country": "DE",
  "period": "last30d",
  "mediaType": "video",
  "platforms": ["FACEBOOK", "INSTAGRAM"]
}
```

**Migrating from the leading competitor — paste their input shape, we accept it:**

```json
{
  "urls": [
    { "url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=IN&q=linkedin&search_type=keyword_unordered&media_type=all" }
  ],
  "count": 100,
  "scrapePageAds.period": "last7d",
  "scrapePageAds.activeStatus": "all",
  "scrapePageAds.sortBy": "impressions_desc",
  "scrapePageAds.countryCode": "ALL"
}
```

### Output

Sample row:

```json
{
  "adArchiveId": "1234567890123456",
  "adId": "987654321",
  "pageId": "20531316728",
  "pageName": "Nike",
  "isActive": false,
  "startDate": 1709251200,
  "endDate": 1713571200,
  "totalActiveTime": 4406400,
  "totalActiveTimeSource": "computed_from_dates",
  "publisherPlatform": ["FACEBOOK", "INSTAGRAM"],
  "country": "US",
  "currency": "USD",
  "displayFormat": "VIDEO",
  "title": "Just Do It.",
  "bodyText": "Run with the new Air Zoom Pegasus 41. Built for breakthroughs.",
  "linkDescription": "Free shipping on orders $50+",
  "ctaText": "Shop Now",
  "ctaType": "SHOP_NOW",
  "linkUrl": "https://nike.com/w/pegasus-41",
  "imageUrl1": "https://scontent.xx.fbcdn.net/v/t39.../creative1.jpg",
  "videoUrl1": "https://video.xx.fbcdn.net/v/t39.../ad-hd.mp4",
  "videoPreviewImageUrl1": "https://scontent.xx.fbcdn.net/v/t39.../preview.jpg",
  "pageVerified": true,
  "pageCategories": ["Sportswear store"],
  "pageProfilePictureUrl": "https://scontent.xx.fbcdn.net/v/t39.../profile.jpg",
  "snapshot": { "...full Facebook payload preserved here..." },
  "runTag": "weekly-pull-2026-05",
  "sourceUrl": "https://www.facebook.com/ads/library/?...&q=nike",
  "scrapedAt": "2026-05-18T14:23:11.482Z"
}
```

**Data fields:**

| Field | Type | Description |
|---|---|---|
| `adArchiveId` | string | Unique Ad Library archive ID — primary key. |
| `adId` | string | Internal Meta ad ID. |
| `pageId` / `pageName` | string | Advertiser identity. |
| `isActive` | boolean | Whether the ad is still running. |
| `startDate` / `endDate` | unix epoch | Start / stop timestamps. |
| `totalActiveTime` | integer | Seconds the ad has been running. Facebook's own figure (second precision) when it sends one, which it only does for very new ads. Otherwise whole calendar days × 86,400, counting both the first and last day (an ad that started today = 1 day). For an ad that is still active the last day is the scrape day; for a stopped ad it is `endDate`. |
| `totalActiveTimeSource` | string | `facebook` or `computed_from_dates` — which of the two `totalActiveTime` came from. |
| `publisherPlatform` | array | Where the ad runs: FACEBOOK / INSTAGRAM / MESSENGER / AUDIENCE_NETWORK / THREADS / WHATSAPP. |
| `country` | string | ISO country code the ad targets. |
| `displayFormat` | string | IMAGE / VIDEO / CAROUSEL / DCO / etc. |
| `title` / `bodyText` / `linkDescription` | string | Ad copy. |
| `ctaText` / `ctaType` | string | Call-to-action button (`Shop Now`, `SHOP_NOW`). |
| `linkUrl` | string | Destination URL of the ad. |
| `imageUrl1..5`, `videoUrl1`, `videoPreviewImageUrl1` | string | Creative CDN URLs, flat. |
| `spendLowerBound` / `spendUpperBound` / `spendCurrency` | number/string | Political/social-issue ads only. |
| `impressionsLowerBound` / `impressionsUpperBound` | number | Political/social-issue ads only. |
| `pageVerified` | boolean | Blue-tick verification status. |
| `pageCategories` / `pageProfilePictureUrl` | array/string | Advertiser metadata. |
| `snapshot` | object | Full original Facebook payload — preserved for power users. |
| `advertiser` | object | Resolved About-page data (when `resolveAdvertiser=true`). |
| `demographicReach` | object | EU age × gender × country reach (when `scrapeAdDetails=true`). |
| `runTag` | string | Echoed from input — useful for joining datasets. |
| `sourceUrl` | string | Which input URL produced this row. |
| `scrapedAt` | ISO 8601 | When we captured the row. |

### How much does it cost to scrape Facebook Ad Library?

**Pay-per-event pricing — only pay for what you get.**

| Event | Price | When it fires |
|---|---|---|
| `ad-scraped` | **$0.00049** ($0.49 / 1,000) | Once per ad extracted with creative, CTA, link, body text. |
| `ad-details-fetched` | **$0.00025** ($0.25 / 1,000) | Only when `scrapeAdDetails=true` AND Meta returns non-empty data. EU reach + AAA targeting metadata. Note: Meta publishes EU reach for ads delivered in the EU/UK; this version requests it only for ads Meta labels political or social-issue. Other ads (including commercial ads) come back without reach, and empty calls are never charged. |
| `advertiser-resolved` | **$0.001** ($1 / 1,000 unique pages) | Only when `resolveAdvertiser=true` — fired ONCE per page across the whole run, not per ad. |

There is no actor-start fee. The monthly platform credit on Apify's free plan can be used to test-drive it.

**Typical run costs:**

| Run | Ads | Details | Advertisers | **Cost** |
|---|---|---|---|---|
| Sample run | 50 | — | — | **$0.0245** |
| Small competitive scan | 500 | — | — | **$0.245** |
| 1K-ad market sweep | 1,000 | — | 20 pages | **$0.49 + $0.02 = $0.51** |
| 10K-ad campaign analysis | 10,000 | — | 200 pages | **$4.90 + $0.20 = $5.10** |
| 10K political/social-issue ads delivered in the EU, with details | 10,000 | up to 10,000 | 200 pages | **up to $4.90 + $2.50 + $0.20 = $7.60** |
| 100K-ad agency audit | 100,000 | — | 2,000 pages | **$49 + $2 = $51** |

Costs are list prices. With **Scrape ad details** on, only ads Meta labels political or social-issue get the details call, and it is charged only when Meta returns reach data (EU-delivered ads). Commercial ads never trigger it, so a 10K commercial-ad run with details on still costs $5.10.

Compare: the most popular community Facebook Ad Library scraper on the Apify Store charges $0.75 per 1,000 results (Store price checked 2026-09-29), so the 10,000 ads above would cost $7.50 there vs $4.90 here (35% less per ad).

### Tips & advanced options

- **Run with the default 256 MB memory.** That's enough — peak observed usage is ~60 MB. The actor is capped at 512 MB; more memory would only increase your Apify compute bill without making the scrape faster.
- **One source per run beats many small ones.** A single keyword/page URL scrape returning 50 ads costs roughly half as much as ten keyword sources of 5 ads each. Bootstrap overhead is per-source. If you need many advertisers, prefer scheduling separate runs over packing 10 URLs into one.
- **`country=ALL`** returns ads from every country Meta indexes. Be cautious — the result count can explode for popular keywords.
- **`mediaType=video`** is one of the highest-signal filters for competitive intel — high-spend advertisers ship video creative.
- **`platforms`** filter is exact-match. Setting `["FACEBOOK", "INSTAGRAM"]` excludes ads that only run on Messenger or Audience Network.
- **`period=last7d`** + `sortBy=most_recent` is the fastest way to surface brand-new ad pushes from a competitor.
- **`resolveAdvertiser=true`** + scraping multiple ads per page costs **almost nothing extra** — we fire the resolve event once per unique pageId, not per ad. Compare to competitors that re-fetch per ad.
- **Schedule it.** Use Apify Schedules to run weekly with `period=last7d` and a stable `runTag`, then JOIN datasets by `pageId` to track advertiser changes over time.
- **Chain into other actors.** Pipe the dataset into a Shopify, web-archive, or LLM-summarization actor for full competitive-intel pipelines.
- **Resume checkpoints.** Leave `enableCheckpoint=true` (the default). If the run hits its timeout, crashes, a source fails after all retries, or you stop it manually, restart with the same input within 6 hours — sources that already finished are skipped, the rest pick up from the last successful pagination cursor, and `limitPerSource` counts the ads already delivered. No double-charge. Runs that finished normally (sources exhausted or `count` reached) are not resumed: scheduled or repeated runs of the same search start fresh and return every matching ad again. Starting a second identical run while the first is still running gives it a fresh start (it does not take over the running one's checkpoint).

### Legal disclaimer

This actor only scrapes data that Facebook makes **publicly available** in its Ad Library — the same data anyone can see by visiting [facebook.com/ads/library](https://www.facebook.com/ads/library). No Facebook login is performed. No private user data is extracted.

Per Meta's [Ad Library Terms](https://www.facebook.com/business/help/2405092116183307), ads in the Ad Library are public. However, your jurisdiction's data-protection laws (GDPR, CCPA, etc.) may impose restrictions on how you process advertiser data. You are responsible for compliance with applicable laws in your use of the output.

If you scrape political/social-issue ads, note that some fields (spend range, impressions range, demographic breakdown) are only available for ads in that category — a Meta policy choice.

### FAQ & support

**Q: Does this work for commercial ads, or only political/issue ads?**
Yes — works for all ads in the public Ad Library. The official Meta API is restricted to political/issue ads; this actor is not.

**Q: The most popular community Ad Library scraper charges $0.75 per 1,000 and you charge $0.49 — is the data the same?**
Same source (`facebook.com/ads/library`), same field coverage. We're cheaper because (a) newer cost structure, (b) we dedup advertiser-About calls per pageId instead of per-ad, (c) we extract the first page free from SSR HTML instead of paying for the GraphQL call.

**Q: My country isn't in the dropdown — what do I do?**
Use the **Custom country code** field underneath the dropdown. Type any 2-letter ISO-3166 code (e.g., `BD`, `PK`, `MA`, `JM`).

**Q: I'm getting fewer ads than expected.**
(1) Some ads are geo-fenced — try `country=ALL`. (2) `activeStatus=active` filters out ended ads — try `activeStatus=all`. (3) Facebook's pagination occasionally returns empty pages mid-run; our retry logic handles up to 2 consecutive empties before stopping that source.

**Q: Can I run this on a schedule?**
Yes. Use Apify Schedules + a stable `runTag` so you can join datasets across runs.

**Q: I'm migrating from another Ad Library scraper — will my old input still work?**
Yes. We accept the `scrapePageAds.period` / `scrapePageAds.activeStatus` / `scrapePageAds.sortBy` / `scrapePageAds.countryCode` dot-notation keys as aliases.

For issues: [open a ticket on Apify](https://apify.com/contact) or reach the maintainer through the Apify Store actor page.

# Actor input Schema

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

Paste Ad Library search URLs (https://www.facebook.com/ads/library/?...) or raw Facebook page URLs (https://www.facebook.com/ZapierApp). Auto-detected. Accepts both string arrays and curious_coder-style \[{url: "..."}] shape for migration. Leave blank if using the Keyword or Advertiser name fields below. Max 10 URLs per run.

## `keyword` (type: `string`):

Type a search term — we'll build the Ad Library search URL for you using the Country + Media type + Ad type filters below. Faster than hand-crafting `q=` params. Example: `nike`. Leave blank if using URLs above.

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

Search by advertiser name instead of keyword (search_type=page). Returns ads from pages matching that name. Example: `Spotify`. Leave blank if using Keyword or URLs above.

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

Two-letter ISO country code. Only used when Keyword or Advertiser name is set, OR to override the country from a pasted URL. If your country isn't listed, use Custom country code below.

## `customCountryCode` (type: `string`):

Overrides the dropdown above. 2-letter ISO 3166-1 alpha-2 code (e.g., `BD` for Bangladesh, `PK` for Pakistan). Leave blank to use the dropdown.

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

Filter by creative format. Maps to the Ad Library `media_type=` URL parameter.

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

Filter by ad category. Political & social ads include extra fields (spend range, impressions range, demographic reach).

## `platforms` (type: `array`):

Filter ads by the platforms they run on. One per line: FACEBOOK, INSTAGRAM, MESSENGER, AUDIENCE_NETWORK, THREADS, WHATSAPP. Leave blank for all.

## `period` (type: `string`):

Limit to ads ACTIVE in this window. Note: many ads run for months/years, so the `startDate` field in the output may show a date older than the window — that's the ad's original run-start date, not when it was indexed. For 'newly launched ads only', also set sortBy=most_recent.

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

Filter by whether the ad is still running.

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

Result ordering. Defaults to highest-impressions-first (matches the Ad Library UI default).

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

Fire a second call per ad to fetch EU demographic reach (age × gender × country breakdown + estimated EU total reach) and AAA targeting metadata. Meta publishes these for ads delivered in the EU/UK. This version only makes the extra call for ads Meta labels political or social-issue; all other ads (including commercial ads) are returned without reach data and are not charged for it. We only charge $0.25/1K when non-empty data comes back. Off by default.

## `resolveAdvertiser` (type: `boolean`):

Fetch each advertiser's public About page (verified status, categories, profile pic) — ONCE per page, regardless of how many ads they have. Costs $1 per 1,000 unique advertisers — much cheaper than competitors who refetch per ad.

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

Cap the number of ads scraped per input URL / keyword. Leave blank to scrape all available ads. Actual count may exceed by up to 30 (one extra paginated batch).

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

Hard ceiling on total ads emitted by this run. Overrides limitPerSource when reached. Clear the field for unlimited.

## `enableCheckpoint` (type: `boolean`):

Save progress every batch to a key-value store. If a run times out, crashes, or is stopped, re-running it within 6 hours with the same input resumes from where it stopped instead of paying for already-scraped ads. Runs that finished normally are never resumed — repeating the same search returns the full result set.

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

Parallel paginations across input URLs. Facebook is sensitive to per-IP load — keep at 2-3 unless using high-rotation residential proxy.

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

Optional label echoed into every output row's `runTag` column. Useful for joining datasets from scheduled runs.

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

Default is RESIDENTIAL — most reliable against Facebook's anti-bot on the public Ad Library endpoint. If you want to trim proxy cost, switch the group to `BUYPROXIES94952` (datacenter, ~13× cheaper); FB serves most public Ad Library requests to datacenter IPs cleanly, but expect a higher rate of 403/challenge on harder advertisers. Country override changes proxy egress (different from the ad-search country).

## Actor input object example

```json
{
  "urls": [
    "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=US&q=nike&search_type=keyword_unordered&media_type=all"
  ],
  "country": "ALL",
  "mediaType": "all",
  "adType": "all",
  "period": "",
  "activeStatus": "all",
  "sortBy": "impressions_desc",
  "scrapeAdDetails": false,
  "resolveAdvertiser": false,
  "count": 50,
  "enableCheckpoint": true,
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Every ad captured from the Facebook Ad Library, with creative + CTA + link + advertiser fields. Download as JSON, CSV, or Excel.

# API

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

## JavaScript example

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

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

// Prepare Actor input
const input = {
    "urls": [
        "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=US&q=nike&search_type=keyword_unordered&media_type=all"
    ],
    "count": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("constructive_calm/facebook-ad-library-pro").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "urls": ["https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=US&q=nike&search_type=keyword_unordered&media_type=all"],
    "count": 50,
}

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

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

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

```

## CLI example

```bash
echo '{
  "urls": [
    "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=US&q=nike&search_type=keyword_unordered&media_type=all"
  ],
  "count": 50
}' |
apify call constructive_calm/facebook-ad-library-pro --silent --output-dataset

```

## MCP server setup

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

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/EeK9bTdScJRwzeLPE/builds/uug2liyvDT7Naru4J/openapi.json
