# Facebook Ads Library Scraper \[NO COOKIES] ✅ (`unseenuser/meta-ads`) Actor

See every creative variant your competitors are testing, not just one ad per campaign. Scrape the Meta Ad Library by keyword, brand or ad ID for full copy, CTA, media and landing URL. No login, no cookies, no Business Manager. Political ad spend and EU reach where Meta publishes them.

- **URL**: https://apify.com/unseenuser/meta-ads.md
- **Developed by:** [Unseen User](https://apify.com/unseenuser) (community)
- **Categories:** Social media, Developer tools, Lead generation
- **Stats:** 103 total users, 22 monthly users, 100.0% runs succeeded, 5 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

$5.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

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

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Facebook & Instagram Ad Library Scraper - a Meta Ads API Alternative

The only meta ad library scraper that covers **all 6 Meta surfaces** in one tool: Facebook, Instagram, Messenger, Audience Network, Threads, and Meta's partner network. Scrape facebook ads, instagram ads, and everything in between - no Meta Business Manager, no app review, no Marketing API credentials needed.

Use it as a **Meta Ads API** alternative when the official Marketing API is more than you need: no Meta Developer app, no business verification, no access token to refresh, and it returns other advertisers' ads rather than only your own accounts.

### Free plan limit

Free Apify users get up to **50 results per run**. Paying users are not affected and receive results normally.

This limit was set by the Actor developer, not by Apify. To remove it and receive unlimited results, upgrade to any paid Apify plan: https://apify.com/pricing

When a free plan run hits the cap, the Actor finishes successfully (status `SUCCEEDED`) and the run's status message explains what happened. No error is raised, so the first 50 results are fully usable as normal.

### Why this scraper instead of Meta's official API?

| | This Scraper | Meta Marketing API |
|---|---|---|
| Setup time | 30 seconds | Days (app review + business verification) |
| Business Manager required | No | Yes |
| App review required | No | Yes |
| Surfaces covered | All 6 (FB, IG, Messenger, AN, Threads, Partners) | Ad Library API only |
| Competitor ads | Yes - any advertiser | Only your own accounts |
| Political ad spend/impressions | Yes (where Meta publishes it) | Limited |
| Rate limits | Managed for you | You manage tokens + rate limits |
| EU DSA transparency data | Yes | Manual compliance |

### Is there a no-code way to use the Meta Ads API?

Yes, and this is the usual reason people arrive here.

Meta's Marketing API needs a Developer app, business verification and app review before it returns a single row, and even then it only shows you your own ad accounts. The Ad Library API is separate, needs its own access token, and is limited in what it will filter on.

This Actor needs none of that. Paste a keyword, a brand name, a page ID or an ad ID, press Start, and get structured rows out. No developer app, no token to refresh, no rate limit to manage yourself, and it returns any advertiser's public ads rather than only your own.

If you do want programmatic access, every run is reachable through the Apify API and the output field names are stable, so you can treat this as a drop-in meta ad library api without applying to Meta for anything.

### Do I need a Facebook account, cookies or login?

No. Nothing at all.

You do not need a Facebook account, a Business Manager, an app review, a Marketing API token, browser cookies, or a session copied from somewhere. You paste a keyword or a brand name and press Start.

This matters more than it sounds. Meta's own Marketing API needs business verification and app review before it returns anything, and it only shows you your own ad accounts. Everything here comes from the public Meta Ad Library, which Meta publishes under transparency rules and which is available to anyone.

There is also nothing to keep alive. Scrapers that depend on a logged-in session break whenever that session expires, which is why "it stopped working" is such a common complaint in this category. There is no session here to expire.

### What you can do with it

| Use case | How |
|---|---|
| **E-commerce competitor spy** | Search by keyword or brand to see every ad your competitors run, with creative, copy, CTA, and landing URL |
| **Agency creative briefs** | Pull winning ad formats (single image, video, carousel, collection) as structured JSON for your creative team |
| **Ad-format benchmarking** | Compare display formats (IMAGE, VIDEO, DPA, DCO, MEME) across competitors at scale |
| **Political ad research** | Track political ad spending, impression ranges, and demographic breakdowns for journalism or academic research |
| **EU DSA compliance** | Access transparency data Meta publishes under the Digital Services Act |
| **Brand-safety monitoring** | Detect counterfeit or unauthorized ads using your brand name or trademarks |
| **Influencer vetting** | Verify if claimed brand partnerships actually have running ads |
| **Swipe-file automation** | Pipe ad creatives into Airtable, Google Sheets, or Notion via Apify integrations |

### Four modes

| Mode | What you get |
|---|---|
| **Find ads by keyword** | Keyword search across every advertiser on Meta. Cursor-paginated. Returns ad copy, images, videos, CTA, landing URL. |
| **Get all ads from a brand / page** | Every active (or inactive) ad for a specific Facebook page. Supports brand-name auto-resolve. |
| **Look up a brand's page ID** | Company-to-page-ID lookup. Returns name, category, likes, verification status, Instagram handle + followers. |
| **Get full details for a specific ad** | Complete detail for one ad, including all creative variants (carousel cards), link URL, CTA, and optional video transcript. |

### How to use it

1. Pick a **mode** from the dropdown.
2. Paste your **search terms** - one per line (keywords, brand names, page IDs, or ad URLs depending on the mode).
3. Optionally select countries, status, or max items.
4. Click **Start**.

Everything else is in the collapsed **Advanced** section with sensible defaults.

### Example inputs

**Keyword search - find facebook ads by topic**

```json
{
    "searchMode": "search_ads",
    "searchTerms": ["running shoes", "trail runners"],
    "countries": ["US"],
    "maxItems": 500
}
```

**Scrape all instagram ads from a brand**

```json
{
    "searchMode": "company_ads",
    "searchTerms": ["Nike"],
    "countries": ["US"]
}
```

**Look up a company's Facebook page ID**

```json
{
    "searchMode": "search_companies",
    "searchTerms": ["nike", "lululemon", "on running"]
}
```

**Get full ad details with video transcript**

```json
{
    "searchMode": "ad_details",
    "searchTerms": ["702369045530963"],
    "getTranscript": true
}
```

### Output by ad format

The JSON structure varies by ad format. Here's what to expect:

**Single image ad** - `snapshot.display_format: "IMAGE"`, creative in `snapshot.images[]`

**Video ad** - `snapshot.display_format: "VIDEO"`, creative in `snapshot.videos[]` with HD/SD URLs + preview image. Optional `transcript` field when `getTranscript: true`.

**Carousel ad** - `snapshot.display_format: "MULTI_IMAGES"`, each slide in `snapshot.cards[]` with its own body, title, image, link\_url, and CTA.

**Dynamic Creative ad** - `snapshot.display_format: "DCO"`. Also uses `snapshot.cards[]`, but here each card is an alternative version of the ad being tested rather than a slide in one ad. Turn on creative analysis to get these split out as `creative.variants[]`.

**Dynamic Product Ad (DPA)** - `snapshot.display_format: "DPA"`, product cards in `snapshot.cards[]` with individual product URLs, prices in `link_description`, and product images.

**Collection ad** - `snapshot.display_format: "DCO"`, mix of video + image cards in `snapshot.cards[]`.

Every item includes a `_meta` field for traceability:

```json
"_meta": {
    "searchMode": "search_ads",
    "query": "running shoes",
    "country": "US",
    "page": 2,
    "scrapedAt": "2026-05-07T12:00:00.000Z"
}
```

Null values, empty strings, and empty arrays are automatically stripped from output for clean, compact data.

### What you can extract

Every run returns one row per ad. These are the fields you get without turning anything on:

- **Identity** - `ad_archive_id`, `page_id`, `page_name`, `url` (the ad's own Ad Library link)
- **Status and timing** - `is_active`, `start_date`, `end_date`, and ISO-formatted `start_date_string` / `end_date_string`
- **Placement** - `publisher_platform`, listing every Meta surface the ad runs on
- **Creative** - `snapshot.title`, `snapshot.body.text`, `snapshot.caption`, `snapshot.link_description`
- **Call to action** - `snapshot.cta_text`, `snapshot.cta_type`, `snapshot.link_url`
- **Media** - `snapshot.videos[]` with HD, SD and preview URLs; `snapshot.images[]` with original and resized URLs; `snapshot.cards[]` for Dynamic Creative
- **Advertiser** - `snapshot.page_like_count`, `snapshot.page_categories`, `snapshot.page_profile_uri`
- **Grouping** - `collation_id` and `collation_count` to group variants of the same ad
- **Meta disclosures** - `contains_digital_created_media`, `contains_sensitive_content`, `gated_type`, `regional_regulation_data`
- **Traceability** - `_meta` records which input produced the row

A real row, from an actual run (media URLs shortened for readability):

```json
{
    "ad_archive_id": "1547621160391125",
    "page_id": "101958012238497",
    "page_name": "Memorygram",
    "is_active": true,
    "publisher_platform": ["FACEBOOK", "INSTAGRAM", "AUDIENCE_NETWORK", "MESSENGER", "THREADS"],
    "start_date": 1784098800,
    "end_date": 1787641200,
    "start_date_string": "2026-07-15T07:00:00.000Z",
    "end_date_string": "2026-08-25T07:00:00.000Z",
    "collation_id": "1940433273246103",
    "collation_count": 3,
    "contains_digital_created_media": false,
    "url": "https://www.facebook.com/ads/library?id=1547621160391125",
    "snapshot": {
        "display_format": "VIDEO",
        "title": "A Book of Mom's Life",
        "body": { "text": "If your mom is still here, do this. My sister had Memorygram make one for our mom before she passed..." },
        "caption": "Memorygram.com",
        "cta_text": "Shop now",
        "cta_type": "SHOP_NOW",
        "link_url": "https://checkout.memorygram.com/",
        "link_description": "Easily Record Mom's Life Story",
        "page_like_count": 18,
        "page_categories": ["Baby goods/kids goods"],
        "videos": [{
            "video_hd_url": "https://video-lga3-2.xx.fbcdn.net/o1/v/t2/f2/m366/AQ...",
            "video_sd_url": "https://video-lga3-2.xx.fbcdn.net/o1/v/t2/f2/m412/AQ...",
            "video_preview_image_url": "https://scontent-lga3-3.xx.fbcdn.net/v/t39.35426-6/7..."
        }]
    },
    "_meta": {
        "searchMode": "company_ads",
        "pageId": "101958012238497",
        "companyName": "Memorygram",
        "country": "US",
        "page": 1,
        "scrapedAt": "2026-08-25T09:47:48.371Z"
    }
}
```

### How do I analyze competitor ads step by step?

A repeatable competitor ad analysis in four passes.

**1. Pull everything they are running.** Use "Get all ads from a brand / page" with the brand name. Names are resolved to page IDs automatically, so you do not need to find the ID first.

```json
{
    "searchMode": "company_ads",
    "searchTerms": ["Nike"],
    "countries": ["US"],
    "status": "ACTIVE"
}
```

**2. Find what they keep paying for.** Turn on creative analysis and sort by `signals.days_running`, descending. Meta publishes no performance data for commercial ads, so time-on-air is the closest honest proxy: advertisers stop paying for creative that does not work.

**3. See what they are testing.** Ads with `creative.variant_count` above 1 are Dynamic Creative, and `creative.variants[]` lists each alternative with its own copy, headline, button and destination. That is the competitor's live A/B test, visible.

**4. Watch it over time.** Schedule the same input weekly. `signals.launched_last_7_days` shows what is new since the last pull, which turns a one-off audit into ongoing competitor ad tracking.

### Creative analysis (optional)

Tick **Add creative analysis fields** and every ad gains extra columns, built from data already in the response. No extra API calls, no slowdown worth noticing, and it runs at about 1ms per ad.

Switch the dataset to the **Creative analysis** view to see them as sortable columns.

**`creative.variants[]` is the one to know about.** Advertisers running Dynamic Creative test several versions of an ad at once. Meta buries each version inside `snapshot.cards[]`, where almost nobody looks. This lifts each one out as a complete creative in its own right:

```json
"creative": {
  "format": "DCO",
  "headline": "#1 Gift For Mom & Dad",
  "variant_count": 2,
  "variants": [
    {
      "index": 0,
      "title": "#1 Gift For Mom & Dad",
      "body": "Record your loved one's life story in a book",
      "cta_text": "Shop Now",
      "cta_type": "SHOP_NOW",
      "link_url": "https://checkout.example.com/",
      "media": [{ "type": "video", "url": "https://...mp4/" }]
    },
    { "index": 1, "title": "Preserve Their Story", "cta_text": "Learn More", "...": "..." }
  ],
  "media": [{ "type": "video", "url": "...", "sd_url": "...", "preview_url": "..." }],
  "collation_id": "1234567890",
  "collation_count": 3,
  "partner": { "page_name": "Creator Name", "page_id": "..." }
}
```

That answers "show me every headline and creative this brand is testing" in one query.

**`signals.long_running`** flags ads that have been live past a threshold you set (default 30 days). Advertisers don't keep paying for creative that isn't working, so a long-running ad is usually a proven winner. Sort by `signals.days_running` to rank them.

```json
"signals": {
  "days_running": 47,
  "long_running": true,
  "long_running_threshold_days": 30,
  "is_active": true,
  "platform_count": 2,
  "page_like_count": 4210
}
```

Also added: `landing.domain` (where the ad sends people), `landing.query_params`, and `enrichment.language` (detected from the ad copy, since Meta doesn't provide it).

**What to expect in practice.** Measured across a 1,032-ad sample: format, ad copy, CTA, destination domain, days running and language are present on ~100% of ads; media on 71%; creative variants on 29% (only Dynamic Creative ads have them); paid-partnership data on 6%.

A few of Meta's own disclosure flags are passed through too (`signals.ai_generated_media`, `is_reshared`, `gated_type`). Be aware these were a constant value across the whole sample, so treat them as available-if-Meta-sets-them rather than as a reliable filter.

Leaving the option off returns exactly the output the actor has always returned, so existing saved tasks and integrations are unaffected.

### How do I find a competitor's best-performing ad?

Meta does not publish click-through or conversion data for commercial ads, so nobody can tell you which ad performed best. What you can see is how long an advertiser has been willing to keep paying for it, which is the next best thing.

Turn on **Add creative analysis fields** and every ad gets `signals.days_running`, plus `signals.long_running` for anything past a threshold you set.

```json
{
    "searchMode": "company_ads",
    "searchTerms": ["Nike"],
    "countries": ["US"],
    "enrichment": true,
    "longRunningDays": 45
}
```

Then sort the dataset by **Days running**, descending. The ads at the top have survived longest.

Two things worth knowing when you read the result:

- The default threshold of 30 days flags a lot of ads for advertisers running evergreen campaigns. If most of a brand's ads come back flagged, raise the threshold until the flag means something. On one real advertiser, 30 days flagged 38% of ads while 45 days flagged 11%.
- An ad can be long-running because it works, or because nobody has reviewed the account in six months. It is a strong signal, not proof.

### AI analysis (optional, bring your own key)

Two further options read the ad copy with Claude. Both are off by default, and both need **your own** Anthropic API key: get one at [console.anthropic.com](https://console.anthropic.com) and paste it into the **Your Anthropic API key** input field. It is stored encrypted, never appears in the log or the output, and the usage is billed to your Anthropic account.

**Tag each ad with its persuasion angle** adds `llm.primary_angle`, `llm.angles` and `llm.tone`:

```json
"llm": {
  "primary_angle": "social_proof",
  "angles": ["social_proof", "authority", "aspirational"],
  "tone": "emotional"
}
```

Angles: `offer`, `social_proof`, `authority`, `fear`, `curiosity`, `urgency`, `problem_solution`, `testimonial`, `comparison`, `aspirational`, `educational`. This is what lets you ask "show me every competitor ad leading with social proof" instead of reading a thousand ads yourself.

**Write a strategy summary per advertiser** adds one extra row per brand:

```json
{
  "_type": "advertiser_strategy",
  "advertiser": "Example Co",
  "summary": "Runs a heavy gifting angle concentrated around occasions...",
  "positioning": "...",
  "target_audience": "...",
  "creative_strategy": "...",
  "dominant_angles": ["social_proof", "aspirational"]
}
```

It only runs when at least 10 ads were collected for that advertiser, because there is nothing worth saying about two ads.

**Cost.** Lower than you would expect, because the same ad copy is never analysed twice.

Advertisers reuse copy heavily across ad IDs. In a real 1,032-ad run there were only **174 distinct copy blocks**, so 83% of the ads needed no analysis at all - their verdict was already known. The Actor sends each distinct block once and reuses the result, which cuts both the token count and the number of requests by around 80% (52 requests become 9). The fixed instructions are prompt-cached on top of that.

Estimated cost per 1,000 ads tagged, measured on that run:

| Model | Cost |
|---|---|
| Claude Opus 5 (default) | **~$0.27** |
| Claude Sonnet 5 | ~$0.11 |
| Claude Haiku 4.5 | ~$0.05 |

Because even the best model comes to well under a cent per hundred ads, Opus 5 is the default rather than the cheapest option. Drop to Haiku for very large runs where speed matters more than nuance. The strategy summary is one request per advertiser, so it scales with brands rather than results.

Every run logs exactly how many blocks were classified, how many were reused, and the token totals.

**If a call fails** the actor retries a few times, then returns the ad without tags rather than failing the row or the run. Untagged ads are not billed at the enriched rate, so you never pay for analysis that did not happen.

### Does it work for political ads and EU transparency data?

Yes, and this is where the Ad Library publishes far more than it does for commercial ads.

Set **Ad category** to "Political & issue ads only":

```json
{
    "searchMode": "search_ads",
    "searchTerms": ["election"],
    "countries": ["US"],
    "adType": "political_and_issue_ads",
    "status": "ALL"
}
```

On a verified 30-ad run, every ad returned spending and reach data that commercial ads do not carry:

```json
{
    "spend": "$350K - $400K",
    "currency": "USD",
    "impressions_with_index": { "impressions_text": ">1M", "impressions_index": 39 },
    "reach_estimate": ">1M"
}
```

Field coverage measured on that run: `spend` and `currency` on 30 of 30 ads, `impressions_with_index` on 30 of 30, `reach_estimate` on 29 of 30.

For **EU audience breakdowns** by age, country and gender, use "Get full details for a specific ad". That mode returns `aaa_info`, which the list modes do not carry:

```json
{
    "aaa_info": {
        "targets_eu": false,
        "gender_audience": "All",
        "eu_total_reach": 3,
        "age_country_gender_reach_breakdown": [
            { "country": "DE", "age_gender_breakdowns": [ { "age_range": "25-34", "male": 1 } ] }
        ]
    }
}
```

Three things to understand about this data:

- **Spend and impressions are ranges, not numbers.** Meta publishes `"$350K - $400K"` and `">1M"`, not exact figures. Treat them as buckets, and note the currency varies: EUR and JPY both appear alongside USD.
- **Political funding data and EU audience data rarely appear on the same ad.** In a 30-ad EU run, 17 ads carried `spend` and 13 carried `is_aaa_eligible: true`, with no overlap between them.
- **Creative analysis works on political ads too.** All 30 rows carried the full `creative`, `signals` and `enrichment` fields.

Worth knowing when comparing tools: several scrapers in this category advertise `spend` and `impressions`. Those fields are empty for ordinary commercial ads there as well, because Meta does not publish them. If you are researching e-commerce or SaaS advertisers, no tool will give you spend, and one that appears to is showing you empty columns.

### What are the limitations?

Every scraper in this category has these constraints. Most do not write them down.

**No performance data for commercial ads.** No click-through rate, no conversions, no spend, no impressions. Meta only publishes those for political and issue ads. For commercial advertisers, use `signals.days_running` as a proxy for what is working.

**Spend and impressions are ranges.** Even where Meta does publish them, you get `"$350K - $400K"` and `">1M"`, never an exact figure.

**Demographic breakdowns are narrower still.** Age, gender and location splits appear only where Meta is legally required to publish them, chiefly EU-targeted ads, and only through the single-ad detail mode.

**Media URLs expire.** Image and video links point at Meta's CDN and stop resolving after a while. Download anything you need to keep rather than storing the URL.

**Roughly 1,500 results per keyword.** The Ad Library itself stops paginating around there. For wider coverage, split a broad keyword into narrower ones, or search by brand instead.

**Only what Meta publishes today.** There is no archive of deleted ads and no history for ads that stopped running long ago.

**The same ad in several countries counts once.** If an ad runs in the US and the UK and you select both, you get one row, not two, and the run summary reports how many duplicates were suppressed. This is deliberate: you should not pay twice for one ad. If you need per-country presence, run one country at a time.

**Language detection is a guess.** `enrichment.language` is inferred statistically from the ad copy. Reliable on a paragraph, unreliable on three words. Meta does not provide a language field.

**AI tags are judgements, not facts.** Persuasion angles and tone come from a language model reading the copy. Useful in aggregate; any single tag is an opinion.

**Some Meta disclosure flags are usually constant.** `contains_digital_created_media`, `is_reshared` and `gated_type` are passed straight through from Meta. Across a verified 1,032-ad commercial sample each held a single value throughout. They are included in case Meta populates them for your advertisers; check before building a filter on them.

### FAQ

**Q: Does this return EU spend and impression data?**
A: Yes. For ads targeting EU countries, Meta publishes spend ranges, impression ranges, and demographic breakdowns under DSA requirements. This data appears in the `aaa_info` field (ad-details mode) or the `impressions_with_index` / `spend` fields (list modes) when Meta makes it available.

**Q: What data varies by country?**
A: Political ad transparency data (spend, impressions, audience demographics) is only available in countries where Meta is legally required to publish it (US, EU, UK, Canada, Australia, others). Non-political ads show creative + metadata everywhere but no spend/impression data.

**Q: Does it flag AI-generated content?**
A: Yes. Meta's `contains_digital_created_media` boolean field indicates whether the ad was flagged as containing AI-generated or digitally manipulated content.

**Q: Can I access the actual media files (images/videos)?**
A: The output includes direct CDN URLs to images (`original_image_url`, `resized_image_url`) and videos (`video_hd_url`, `video_sd_url`). These are temporary Meta CDN links - download them promptly or they may expire.

**Q: What's the maximum number of results?**
A: The keyword search (GET) caps at ~1,500 results per query due to cursor size limits. For larger sweeps, narrow by country, date range, or more specific keywords and run multiple jobs.

**Is the Meta Ads API free?**
Meta's Marketing API has no per-call fee, but getting to it costs time: a Developer app, business verification and app review, and it only returns your own ad accounts. This Actor charges $5.00 per 1,000 ad results with no application process, and returns any advertiser's public ads. See the Pricing tab for current figures.

**Is the Meta Ad Library API free?**
The Ad Library API is free to call but needs its own access token and identity confirmation, and its filtering is limited. This Actor needs neither, and adds creative, media and landing URL fields the official endpoint does not return.

**What are the rate limits for the Meta Ads API?**
Meta enforces per-app and per-account rate limits that you have to manage yourself, and hitting them stops your pipeline. Here there is nothing for you to manage. The only ceiling is the Ad Library's own limit of roughly 1,500 results per keyword search.

**Do I need to authenticate or authorize anything?**
No. No OAuth flow, no access token, no app permissions, no cookies. Run it and get data.

**Is there a no-code way to use the Meta Ads API?**
This is it. Fill in a form, press Start, download CSV, JSON or Excel. If you later want code, the same run is reachable through the Apify API.

**How can I scrape the Meta Ad Library with Python?**
Run this Actor and read the dataset with the `apify-client` package, or call the dataset endpoint directly. You get parsed, deduplicated rows instead of writing and maintaining a parser against Meta's markup.

**Are there legal risks in scraping the Meta Ad Library?**
The Ad Library is public data Meta publishes under advertising transparency rules. Even so, how you use it is your responsibility. The Terms of Service section below sets out what this Actor does and does not permit, and it is worth reading before you build on it.

**Which Meta Ad Library scraper is best?**
Depends what you need. If you want one ad row per ad, several tools do that. What is unusual here: Dynamic Creative ads are split into their individual variants, the same ad matched in several countries is returned once rather than once per country, and empty runs explain themselves instead of returning nothing.

**Can I download the videos and images from the ads?**
Yes. Every ad returns direct CDN URLs for its videos and images, including HD, SD and preview versions. Download promptly; Meta's CDN links expire.

**Do I need a Facebook account or cookies?**
No. Nothing to log into, nothing to expire, nothing to maintain.

**How much does it cost?**
Ad result: $5.00 per 1,000. Ad result with creative analysis: $9.00 per 1,000, and creative analysis is off by default. Advertiser strategy report: $0.20 per report, produced at most once per advertiser and only when you switch it on. Platform usage is included.

**Will I get charged twice for the same ad?**
No. An ad matching several country or language queries is returned once, and the run summary reports how many duplicates were suppressed.

**Do I get charged when a run finds nothing?**
No. Rows describing no results, bad input or API errors carry no charge.

**Is there a cap on results?**
Set the limit fields to `0` for everything. The only real ceiling is the Ad Library's own limit of roughly 1,500 results per keyword.

**Can I see every version of a Dynamic Creative ad?**
Yes. Turn on creative analysis and each alternative appears in `creative.variants[]` with its own copy, headline, button, destination and media.

**Why did my run return nothing?**
It will tell you. An empty run returns a row explaining the likely cause and what to change, rather than an empty dataset with no explanation.

**How quickly are issues answered?**
Within 24 hours. This Actor currently has zero open issues and has never had one.

### Example tasks

Each of these is a saved, pre-configured task. Open one, press Start, and you get results without filling in a single field. They are also the fastest way to see what a given input combination actually returns before you commit to writing your own.

**Competitor and brand tracking**

- [Spy on Competitor Facebook Ads in US E-commerce](https://apify.com/unseenuser/meta-ad-library-scraper/examples/meta-ads-spy-ecom-competitors-us) - keyword search across active US e-commerce ads
- [Track a Brand's Active Facebook and Instagram Ads](https://apify.com/unseenuser/meta-ad-library-scraper/examples/meta-ads-track-brand-active-ads) - everything one advertiser is running right now
- [Monitor Competitor Ads in Europe With DSA Data](https://apify.com/unseenuser/meta-ad-library-scraper/examples/meta-ads-competitor-ads-europe-dsa) - EU ads with reach, demographics and payer disclosure
- [Monitor Facebook Ads for Brand Safety Violations](https://apify.com/unseenuser/meta-ad-library-scraper/examples/meta-ads-brand-safety-trademark-monitor) - watch for your trademarks in other advertisers' copy

**Creative extraction**

- [Scrape Facebook Video Ad Creatives With Transcripts](https://apify.com/unseenuser/meta-ad-library-scraper/examples/meta-ads-video-ad-creatives-with-transcript) - video ads with the spoken script transcribed
- [Download Facebook Ad Video and Image Creatives](https://apify.com/unseenuser/meta-ad-library-scraper/examples/meta-ads-download-video-image-creatives) - direct media URLs for every creative in a run
- [Scrape Multi-Card and Carousel Ad Creatives](https://apify.com/unseenuser/meta-ad-library-scraper/examples/meta-ads-carousel-ads-scraper) - carousel, DCO and multi-image ads split one row per card
- [Get Full Details for a Facebook Ad by ID or URL](https://apify.com/unseenuser/meta-ad-library-scraper/examples/meta-ads-get-single-ad-details) - one ad, every field, including variants and transcript

**Lookup and research**

- [Find Any Brand's Facebook Page ID Instantly](https://apify.com/unseenuser/meta-ad-library-scraper/examples/meta-ads-find-brand-facebook-page-id) - resolve a brand name to its page ID and profile
- [Scrape Instagram Ads by Keyword From Meta Ad Library](https://apify.com/unseenuser/meta-ad-library-scraper/examples/meta-ads-instagram-ads-by-keyword) - filter a keyword search down to Instagram placements
- [Track Political Ad Spending on Facebook and Instagram](https://apify.com/unseenuser/meta-ad-library-scraper/examples/meta-ads-political-ad-spending-tracker) - issue and electoral ads with spend and impression ranges

### Integration ideas

- **Slack alerts** - Use Apify's Slack integration to get notified when a competitor launches new ads
- **Airtable swipe file** - Pipe ad creatives directly into an Airtable base for your creative team to browse
- **Make / n8n / Zapier** - Trigger workflows when new ads match your keywords
- **Google Sheets** - Auto-export to a shared spreadsheet for weekly competitor reports
- **Custom dashboards** - Feed the Apify dataset API into your BI tool of choice

### Demo video

New to Apify? Schedule this actor to run automatically:

[How to schedule your Apify actors](https://www.youtube.com/watch?v=GRFW_Loo2dk)

Connect this actor to your stack:

[Apify integrations - send data anywhere](https://www.youtube.com/watch?v=bNACk1_S_6w)

### Related scrapers

Full cross-platform ad spy - track competitors everywhere they advertise:

- [LinkedIn Ad Library Scraper](https://apify.com/unseenuser/LinkedIn-ads) - B2B ad intelligence
- [Google Ads Transparency Scraper](https://apify.com/unseenuser/Google-ads) - Search, YouTube, Display, Shopping
- [Reddit Scraper + Ads Library](https://apify.com/unseenuser/Reddit-Scraper) - Reddit content + ads
- [Facebook Page Posts and Reels Scraper](https://apify.com/unseenuser/fb-posts) - organic Facebook content from the same pages you track ads for
- [Instagram Content Scraper - Posts and Reels](https://apify.com/unseenuser/IG-posts) - organic Instagram content to compare against paid

[See all 16 scrapers by unseenuser](https://apify.com/unseenuser)

***

### Terms of Service

**By running this Actor, you accept the Terms below.**

***

#### Apify Actor - Terms of Service

**Version:** 4.0
**Effective Date:** May 5, 2026

##### 0. ACCEPTANCE BY USE - IMPORTANT

These Terms of Service ("Terms") form a binding legal agreement between you ("User," "you," "your") and UnseenUser, the Publisher of this Apify actor ("UnseenUser," "the Publisher," "we," "us," "our").

**0.1 How You Accept These Terms**

You accept these Terms by any of the following actions:

(a) Running the Actor - Initiating any execution of the Actor on the Apify platform
(b) Using any output returned by the Actor for any purpose
(c) Continuing to access the Actor's listing or documentation after these Terms are visible

**0.2 Continuing Acceptance**

Each time you run the Actor or use its outputs, you reaffirm your acceptance of the then-current Terms. If you do not agree, you must stop using the Actor immediately.

**0.3 No Anonymous Acceptance**

You cannot disclaim acceptance by failing to read these Terms, running the Actor through automated systems, or sharing your Apify account with others. By running the Actor on Apify, you bind yourself, your organization, and any individuals or systems acting on your behalf.

**0.4 If You Do Not Accept**

If you do not agree to these Terms, you must not run the Actor. No use is authorized without acceptance.

***

##### PREAMBLE - UNDERSTANDING THE ARCHITECTURE

**The Data Flow**

```
You (User) -> Apify Platform -> Actor (software) -> Scrape Creators API -> Meta Ad Library
                                                          |
You (User) <- Apify Platform <- Actor (software) <- Scrape Creators API
```

**What Each Party Does**

- **You (the User):** Run the Actor on the Apify platform with input parameters you choose
- **Apify:** Operates the cloud infrastructure that hosts and executes Actors
- **The Publisher (us):** Publishes software code (the Actor) on Apify's platform. The Actor is a thin wrapper that translates your input into requests to a third-party API and returns the API's responses to you. The Publisher does not operate scraping infrastructure, store data, or see/log/process personal data in Actor outputs.
- **Third-Party API Provider:** Scrape Creators (https://scrapecreators.com). An independent third-party company that operates scraping infrastructure and returns data from source platforms.
- **Source Platform:** Meta (Facebook, Instagram). The platform whose publicly visible Ad Library data is accessed.

These Terms operate alongside but do not replace: Apify's Terms of Service, Scrape Creators Terms of Service, Meta's Terms of Service, and applicable law in your jurisdiction.

***

##### 1. NATURE OF THE SERVICE

**1.1 What the Actor Is**

The Actor is a software program that: (a) Accepts structured input from you; (b) Translates that input into HTTP requests to Scrape Creators' API; (c) Receives HTTP responses; (d) Returns the response data to you on the Apify platform.

**1.2 What the Actor Is Not**

The Actor is not: (a) A scraping tool - the Publisher does not operate scraping infrastructure; (b) A direct connection to Meta; (c) A data storage or retention service; (d) A licensed access channel to Meta/Facebook/Instagram; (e) Affiliated with, endorsed by, or authorized by Meta.

**1.3 The Publisher's Limited Role**

The Publisher is a software vendor - similar to a developer who publishes an app on an app store. The Publisher is not a data provider, data broker, data processor, or data controller for purposes of GDPR, CCPA, Israel's Privacy Protection Law, or equivalent.

***

##### 2. WHO MAY USE THE ACTOR

You may use the Actor only if: (a) You are at least 18 years old; (b) You have legal capacity to enter contracts; (c) You are not in a sanctioned country; (d) You are not on any prohibited persons list.

***

##### 3. PERMITTED USES

The Actor may be used for any lawful purpose, including: market research, competitive analysis, academic research, journalism, business intelligence, brand monitoring, and building products that further process publicly available information lawfully.

***

##### 4. PROHIBITED USES

**4.1 Illegal Activity** - Activity illegal under any applicable law.

**4.2 Harassment, Stalking, and Personal Targeting** - Compiling profiles for harassment, stalking, or doxxing. Tracking individuals without their knowledge. Building profiles of vulnerable populations for retaliatory purposes.

**4.3 Discrimination** - Using outputs for discriminatory decisions based on protected characteristics.

**4.4 Spam and Unsolicited Commercial Communication** - Sending unsolicited marketing in violation of CAN-SPAM, CASL, GDPR, PECR, Israeli Anti-Spam Law, or equivalent. Building "lead lists" without consent. Reselling contact data for spam.

**4.5 Fraud and Deception** - Identity theft, fake reviews, election interference, securities fraud.

**4.6 Source Platform Abuse** - Circumventing technical protections, creating fake accounts, engagement manipulation, building competitive substitutes for source platforms.

**4.7 Reselling the Actor's Service** - Reselling raw outputs as your own data product. Sharing credentials for third-party access. Building competing APIs.

**4.8 AI Training Without Authorization** - Using outputs as training data for commercial AI/ML models without licensing from the source platform.

**4.9 Sensitive Targeting** - Targeting or profiling based on health, sexual orientation, religion, politics, or other sensitive characteristics. Targeting children under 16.

**4.10 Privacy Law Violations** - Processing personal data without complying with applicable privacy law. Failing to honor data subject requests.

***

##### 5. SOURCE PLATFORM TERMS - YOUR RESPONSIBILITY

You are solely responsible for ensuring your downstream use complies with Meta's Terms of Service. The Publisher makes no representation that any specific use is permitted under Meta's terms. If you receive a cease-and-desist from Meta: (a) Cease immediately; (b) Notify UnseenUser within 48 hours via https://apify.com/UnseenUser; (c) Cooperate as needed.

***

##### 6. DATA PROTECTION

**6.1 Roles Under Privacy Law**

- **You** are the Data Controller of any personal data you obtain and process
- **Scrape Creators** bears responsibility for the data collection itself
- **The Publisher** acts solely as a software vendor (does not store, retain, or process personal data)

**6.2 No Data Retention by the Publisher**

The Publisher does not maintain a database of personal data, does not access your outputs, and does not view or analyze Actor results.

**6.3 Your Obligations**

Where your use involves personal data, you must: establish a lawful basis, provide notice, honor data subject rights, implement security measures, and comply with cross-border transfer requirements.

**6.4 Israel's Amendment 13**

If your use involves Israeli residents' personal data, comply with the Privacy Protection Law as amended (Amendment 13, effective August 14, 2025).

**6.5 Sensitive Data Restrictions**

Do not use the Actor to target or profile based on: health, religion, politics, sexual orientation, genetics/biometrics, criminal history, or children under 16.

***

##### 7. INTELLECTUAL PROPERTY

The Actor's source code, schemas, documentation, and branding are owned by the Publisher. You receive a limited, non-exclusive, revocable license. The Publisher claims no ownership over public data returned. You may not reverse engineer or reuse the Actor's code in a competing actor.

***

##### 8. PRICING AND PAYMENT

Pricing is administered through Apify. The Publisher may change pricing with at least 14 days' notice. No refunds for breach-related termination.

***

##### 9. SERVICE AVAILABILITY

The Actor depends on Apify, Scrape Creators, and Meta's continued accessibility. The Publisher makes no uptime guarantees and may discontinue the Actor at any time.

***

##### 10. DISCLAIMERS

THE ACTOR IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTIES OF ANY KIND, INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR PURPOSE, NON-INFRINGEMENT, OR ACCURACY OF DATA. The Publisher makes no representation that your use is lawful in your jurisdiction.

***

##### 11. LIMITATION OF LIABILITY

AGGREGATE LIABILITY SHALL NOT EXCEED THE GREATER OF: (a) US $100, OR (b) AMOUNTS PAID IN THE 3 MONTHS PRECEDING THE EVENT. THE PUBLISHER IS NOT LIABLE FOR INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES. Claims must be brought within 1 year.

***

##### 12. INDEMNIFICATION

You agree to defend, indemnify, and hold harmless the Publisher from claims arising from your use, violations of these Terms, violations of law, violations of Source Platform terms, or your processing of personal data.

***

##### 13. SUSPENSION AND TERMINATION

The Publisher may terminate access for material breach, illegal use, or credible legal demand. You may stop using the Actor at any time.

***

##### 14. DISPUTE RESOLUTION

14.1 Send disputes to https://apify.com/UnseenUser and wait 60 days before formal claims.
14.2 Governed by the laws of the State of Israel.
14.3 Exclusive jurisdiction: civil courts of Tel Aviv-Jaffa, Israel.
14.4 Individual claims only (no class actions).
14.5 Prevailing party recovers attorneys' fees.

***

##### 15. MISCELLANEOUS

Entire agreement. Severability applies. No assignment without consent. Sections 0, 4, 5, 6, 7, 10, 11, 12, 14, and 15 survive termination. English controls. Publisher contact: https://apify.com/UnseenUser

***

##### 16. ACKNOWLEDGMENT

By using this Actor, you acknowledge that: (a) You have read these Terms; (b) You understand the architecture; (c) You accept responsibility for your use; (d) Indemnification covers third-party claims; (e) Disputes are resolved in Israeli courts; (f) Publisher identity is obtainable through valid legal process via Apify.

***

#### Actor-Specific ToS Addendum - Facebook & Instagram Ad Library Scraper

This addendum supplements the Master Terms V4.0.

**A. Architectural Disclosure** - This Actor calls Scrape Creators API endpoints and returns the response. UnseenUser does not store, log, or process the data.

**B. Nature of Data Returned** - Ad creative (images, video, carousel), ad copy, CTAs, page identity, dates, platforms, demographic targeting (political ads), spend ranges (political ads). Where output includes personal data, you are the data controller.

**C. Permitted Use Cases** - DTC competitor research, creative inspiration, brand-safety monitoring, influencer-vetting, election integrity research, agency proof-of-spend.

**D. Specifically Prohibited Uses** - Republishing ad creative without licensing, building substitute Ad Library databases for resale, harassing advertisers, impersonation/trademark dilution, voter suppression, publishing targeting data for manipulation.

**E. Platform Terms** - Meta restricts commercial reuse of Ad Library data. If Meta issues a cease-and-desist, notify UnseenUser within 48 hours via https://apify.com/UnseenUser.

**F. Ad Creative Copyright** - Ad creative is copyrighted by the advertiser. Analysis is typically fair use; republishing requires licensing.

**G. Political Ads** - May be used for journalism, research, voter education, election monitoring. May NOT be used for voter suppression, microtargeting "swing voter" lists, disinformation, or election interference.

**H. Page Identity** - When a page name corresponds to an individual, treat as personal data in your downstream processing.

**I. Cross-Platform Aggregation** - Do not aggregate with other ad platforms + personal data to build cross-platform identity profiles. This creates GDPR/CCPA exposure.

**J. Restricted Content** - Do not target minors, do not promote regulated products in prohibited jurisdictions, comply with industry-specific advertising restrictions.

***

### Links

- Publisher contact: https://apify.com/UnseenUser
- ScrapeCreators API docs: https://docs.scrapecreators.com
- Meta Ad Library: https://www.facebook.com/ads/library

# Actor input Schema

## `searchMode` (type: `string`):

Pick one. The box below changes meaning based on your choice.

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

One per line. What to put here depends on the mode above:

• **Find ads by keyword** - keywords, e.g. `running shoes`, `skincare`
• **Get all ads from a brand / page** - brand names (e.g. `Nike`) or numeric Facebook page IDs (e.g. `15087023444`). Names are auto-resolved to IDs.
• **Look up a brand's Facebook page ID** - brand names, e.g. `nike`, `lululemon`
• **Get full details for a specific ad** - ad IDs (e.g. `702369045530963`) or full Meta Ad Library URLs

## `countries` (type: `array`):

*Applies to: Find ads by keyword, Get all ads from a brand / page.*

Pick one or more countries. Leave on **All countries** for worldwide. If you select multiple, the actor runs the search once per country and merges results (ScrapeCreators accepts one country at a time).

## `status` (type: `string`):

*Applies to: Find ads by keyword, Get all ads from a brand / page.*

Only show ads that are currently running, or include paused/ended ads too.

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

*Applies to: Find ads by keyword, Get all ads from a brand / page.*

Only include ads running on or after this date. Click to pick from a calendar.

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

*Applies to: Find ads by keyword, Get all ads from a brand / page.*

Only include ads running on or before this date. Click to pick from a calendar.

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

*Applies to: Find ads by keyword, Get all ads from a brand / page.*

Filter by creative format.

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

*Applies to: Find ads by keyword.*

Only used when finding ads by keyword.

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

*Applies to: Find ads by keyword, Get all ads from a brand / page.*

Applies to ad-returning modes.

## `languages` (type: `array`):

*Applies to: Get all ads from a brand / page.*

Click to pick one or more languages to filter ads by. Leave empty for no language filter. Multiple languages will fan out (one API call per language).

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

*Applies to: Find ads by keyword.*

Restrict to political / issue ads (they come with extra fields like spend and audience).

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

*Applies to: Find ads by keyword, Get all ads from a brand / page, Look up a brand's page ID.*

Total number of ads to collect across all search terms. `0` = return all ads found. When set, the budget is split evenly across your terms (e.g. 100 / 8 terms = 13 per term).

## `maxItemsPerTerm` (type: `integer`):

*Applies to: Find ads by keyword, Get all ads from a brand / page.*

Cap per individual search term. `0` = no per-term limit (auto-distributes the total budget evenly when a total limit is set).

## `maxPagesPerQuery` (type: `integer`):

*Applies to: Find ads by keyword, Get all ads from a brand / page.*

Maximum number of pagination pages to fetch per search term. `0` = fetch all available pages.

## `enrichment` (type: `boolean`):

*Applies to: Find ads by keyword, Get all ads from a brand / page, Get full details for a specific ad.*

Adds extra columns to every ad, built from data already in the response (no extra API calls, no slowdown worth noticing):

• **creative.variants** - each alternative creative in a Dynamic Creative ad split out separately, with its own copy, button and destination
• **creative.media** - all image and video URLs tidied into one list
• **creative.partner** - the paid-partnership page, when there is one
• **landing.domain** - where the ad sends people
• **signals.days\_running** - how long the ad has been live
• **enrichment.language** - detected language of the ad copy

Leave this off and the output is exactly what it has always been.

## `longRunningDays` (type: `integer`):

Ads live for at least this many days get `signals.long_running: true`. Advertisers do not keep paying for creative that is not working, so a long-running ad is usually a proven winner.

`30` is the usual rule of thumb. Raise it to surface only the strongest performers, lower it to catch newer winners. Only used when the checkbox above is on.

## `getTranscript` (type: `boolean`):

*Applies to: Get full details for a specific ad.*

Works on videos under 2 minutes.

## `trim` (type: `boolean`):

Strip rarely-used fields from each ad for a lighter dataset.

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

Required only if you turn on either AI option below. Get a key at https://console.anthropic.com, then paste it here.

Usage is billed to **your** Anthropic account, not to this Actor. The field is stored encrypted and never appears in the run log or the output.

## `llmAnalysis` (type: `boolean`):

*Applies to: Find ads by keyword, Get all ads from a brand / page.*

Reads each ad's copy and tags what it is doing to persuade you: `offer`, `social_proof`, `authority`, `fear`, `curiosity`, `urgency`, `problem_solution`, `testimonial`, `comparison`, `aspirational` or `educational`, plus an overall tone. Lands in `llm.primary_angle`, `llm.angles` and `llm.tone`.

Lets you ask things like "show me every competitor ad leading with social proof".

**Needs your own Anthropic API key** in an `ANTHROPIC_API_KEY` environment variable, and you pay Anthropic directly for it. Costs scale with the number of ads. If a request fails the ad is still returned, just without tags.

## `strategySummary` (type: `boolean`):

*Applies to: Get all ads from a brand / page.*

Adds one extra row per advertiser summarising their overall approach: positioning, who they seem to target, and patterns in how they build and test creative.

Only runs when at least 10 ads were collected for that advertiser, since there is nothing useful to say about two ads. One API call per advertiser, so the cost scales with advertisers rather than with results.

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

Which Claude model does the analysis.

Estimated cost per 1,000 ads tagged, measured against a real 1,032-ad run:
• **Opus 5** - highest quality, about **$0.27**
• **Sonnet 5** - about **$0.11**
• **Haiku 4.5** - fastest, about **$0.05**

These are low because the Actor only sends each distinct piece of ad copy to the model once. Advertisers reuse copy heavily across ad IDs, so in that sample 1,028 ads contained just 174 distinct blocks, cutting the cost by around 80%.

Because even the best model lands well under a cent per hundred ads, Opus 5 is the default. Drop to Haiku for very large runs where speed matters more than nuance.

## Actor input object example

```json
{
  "searchMode": "search_ads",
  "searchTerms": [
    "nike"
  ],
  "countries": [
    "ALL"
  ],
  "status": "ACTIVE",
  "mediaType": "ALL",
  "searchType": "keyword_unordered",
  "sortBy": "total_impressions",
  "languages": [],
  "adType": "all",
  "maxItems": 0,
  "maxItemsPerTerm": 0,
  "maxPagesPerQuery": 0,
  "enrichment": false,
  "longRunningDays": 30,
  "getTranscript": false,
  "trim": false,
  "llmAnalysis": false,
  "strategySummary": false,
  "llmModel": "claude-opus-5"
}
```

# Actor output Schema

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

One item per ad, or per company in the page-ID lookup mode. Key fields: ad\_archive\_id, page\_id, page\_name, is\_active, publisher\_platform, snapshot (body, images, videos, cards, CTA, landing URL), start\_date\_string, end\_date\_string, url.

# 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 = {
    "searchMode": "search_ads",
    "searchTerms": [
        "nike"
    ],
    "countries": [
        "ALL"
    ],
    "status": "ACTIVE",
    "mediaType": "ALL",
    "searchType": "keyword_unordered",
    "sortBy": "total_impressions",
    "adType": "all",
    "maxItems": 0,
    "maxItemsPerTerm": 0,
    "maxPagesPerQuery": 0,
    "longRunningDays": 30,
    "llmModel": "claude-opus-5"
};

// Run the Actor and wait for it to finish
const run = await client.actor("unseenuser/meta-ads").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 = {
    "searchMode": "search_ads",
    "searchTerms": ["nike"],
    "countries": ["ALL"],
    "status": "ACTIVE",
    "mediaType": "ALL",
    "searchType": "keyword_unordered",
    "sortBy": "total_impressions",
    "adType": "all",
    "maxItems": 0,
    "maxItemsPerTerm": 0,
    "maxPagesPerQuery": 0,
    "longRunningDays": 30,
    "llmModel": "claude-opus-5",
}

# Run the Actor and wait for it to finish
run = client.actor("unseenuser/meta-ads").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 '{
  "searchMode": "search_ads",
  "searchTerms": [
    "nike"
  ],
  "countries": [
    "ALL"
  ],
  "status": "ACTIVE",
  "mediaType": "ALL",
  "searchType": "keyword_unordered",
  "sortBy": "total_impressions",
  "adType": "all",
  "maxItems": 0,
  "maxItemsPerTerm": 0,
  "maxPagesPerQuery": 0,
  "longRunningDays": 30,
  "llmModel": "claude-opus-5"
}' |
apify call unseenuser/meta-ads --silent --output-dataset

```

## MCP server setup

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

```

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/YsmdANgwz81r6fAXO/builds/Gbhg8DrR88xKdOwCi/openapi.json
