# Meta (Facebook) Ad Library Scraper - Modern, Fast & Reliable (`whoareyouanas/meta-ad-lite-scraper`) Actor

Scrape Facebook and Instagram ads from Meta Ad Library by keyword, Page ID or search URL. Extract ad copy, image and video URLs, CTAs, dates and platforms. Set an exact ad limit and export JSON or CSV. No Facebook login required.

- **URL**: https://apify.com/whoareyouanas/meta-ad-lite-scraper.md
- **Developed by:** [Anas Nadeem](https://apify.com/whoareyouanas) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.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

## Meta (Facebook) Ad Library Scraper - Modern, Fast & Reliable

Scrape **Facebook and Instagram ads from the Meta Ad Library** by keyword, Facebook Page ID, or Ad Library search URL. Get ad copy, image and video URLs, headlines, calls to action, advertiser names, dates, and publishing platforms in a structured dataset. Set your maximum number of ads and export the results for competitor research, creative analysis, or your own application.

**No Facebook login, cookies to upload, or Meta developer token required.** Run from Apify Console or through the Apify API.

Built by the developer of [Meta Ad Library Scraper](https://apify.com/whoareyouanas/meta-ad-scraper), with a focused workflow for bulk ad discovery.

### What you get

- **Three ways to search:** a keyword, a numeric Facebook Page ID, or a supported Meta Ad Library search URL.
- **Creative data together:** ad text, headlines, CTAs, landing-page links, images, videos, and carousel or dynamic catalog cards when publicly available.
- **An exact upper limit:** `maxAds: 100` delivers at most 100 unique ads, including when the last response contains more results.
- **One row per ad:** duplicate Library IDs are removed within a run. Separate new runs produce independent datasets.
- **Results saved as the search progresses:** inspect partial results and continue an interrupted run using its existing storage.
- **JSON and CSV export:** use the Apify dataset in spreadsheets, reporting pipelines, or API workflows. JSON preserves nested creative cards and media arrays.

### How to scrape Facebook Ad Library ads

1. Enter one search source: **Search keyword**, **Facebook Page ID**, or **Ad Library search URL**.
2. For a keyword or Page ID, select the country, ad status, and media type. A supplied search URL controls its own filters.
3. Set **Maximum ads**. Start with 100; increase it when you need a larger sample.
4. The fresh form contains a one-ad `nike` example with proxy disabled. Replace or clear the example keyword for your search, enable Residential proxy for larger searches if needed, and click **Start**.
5. Open the run's dataset to inspect or export the ads.

One run accepts one search. To monitor several brands, create separate Apify tasks and schedule them as needed. Comparing changes between runs is a downstream step; the actor does not label ads as new or ended.

#### Search ads by keyword

Find public ads returned by Meta for “dinosaur” in the United States:

```json
{
  "searchQuery": "dinosaur",
  "country": "US",
  "activeStatus": "active",
  "maxAds": 100
}
```

#### Scrape a competitor's Facebook Page ads

Collect up to 100 ads for Burger King in the United States:

```json
{
  "pageId": "134615383218473",
  "country": "US",
  "activeStatus": "active",
  "mediaType": "all",
  "maxAds": 100
}
```

The Page ID is the number in `view_all_page_id` in the advertiser's Ad Library search URL. Ordinary Facebook Page/profile URLs are not accepted as `targetUrl`.

#### Use a Meta Ad Library search URL

Paste a supported search URL to preserve its country, status, media, and sorting settings. This example searches Boat's active ads in India:

```json
{
  "targetUrl": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=IN&media_type=all&search_type=page&view_all_page_id=786827864757998&sort_data[mode]=total_impressions&sort_data[direction]=desc",
  "maxAds": 100
}
```

### Input reference

Provide exactly one of `searchQuery`, `pageId`, or `targetUrl`. Combining them produces a clear input error.

| Input | Default | Description |
|---|---|---|
| `searchQuery` | - | Keyword search, up to 500 characters. |
| `pageId` | - | Numeric Facebook Page ID, supplied as a string. |
| `targetUrl` | - | Full HTTPS Ad Library search URL. Its filters take precedence over the form's country, status, and media settings. |
| `country` | `US` | Two-letter country code, such as `US` or `IN`, or `ALL`. Used for keyword/Page ID input. |
| `activeStatus` | `active` | `active`, `inactive`, or `all`. Used for keyword/Page ID input. |
| `mediaType` | `all` | `all`, `image`, `video`, `meme`, or `none`. Used for keyword/Page ID input. |
| `maxAds` | `100` via API; `1` in fresh form | Maximum unique ads to deliver, from 1 to 10,000. Availability, budget, and runtime limits can stop a run earlier. |
| `proxyConfiguration` | Residential via API; disabled in fresh form | The automatic daily check uses the one-ad example without a proxy. Custom proxy providers may charge separately. |

Supported URL parameters: `country`, `q`, `view_all_page_id`, `active_status`, `media_type`, `ad_type`, `search_type`, `is_targeted_country`, indexed `content_languages[n]`, indexed `publisher_platforms[n]`, `sort_data[mode]`, and `sort_data[direction]`.

Search types are `page`, `keyword_unordered`, and `keyword_exact_phrase`, according to the search source. Sort modes are `total_impressions`, `relevance`, and `start_date`, with `asc` or `desc` direction. Ad categories are `all`, `political_and_issue_ads`, `housing`, `employment`, and `credit`. Unsupported URL filters are rejected. Advanced filter translation is implemented; live verification so far covers the US/IN searches described below and an exact-phrase empty search.

### Output: ad copy, creatives, and advertiser data

Each dataset row represents one ad identified by `libraryID`. Fields contain the public data supplied by Meta; availability varies by ad.

| Data | Output fields |
|---|---|
| Ad identity | `libraryID`, `adLibraryUrl` |
| Advertiser | `pageId`, `brand`, `brandLogo` |
| Copy and headline | `body`, `linkTitle`, `linkDescription` |
| Call to action and destination | `ctaText`, `ctaUrl`, `linkUrl` |
| Creative media | `images`, `videos`, `cards`, `format` |
| Status and distribution | `active`, `platforms`, `totalPlatforms` |
| Dates | `startDate`, `endDate`, `scrapeDate` |
| Additional context | `similarAdCount`, `multipleVersions`, `runningTAT`, `sourceUrl` |

`images` contains objects with a `url`. `videos` contains `url` and `duration`, which is `null` when unavailable. Each entry in `cards` preserves its own body, title, description, link, CTA, and media.

`format` is `image`, `video`, `carousel`, `dynamic`, or `unknown`. For dynamic catalog ads, top-level copy selects available concrete card text when Meta supplies a product placeholder. Card ordering can vary between searches. Unknown text is empty; unknown status, dates, counts, and duration use `null`. A carousel alone does not establish multiple ad versions. `runningTAT` is elapsed days since the reported start date for an active ad, not a performance metric.

Media URLs point to Meta's hosting and can expire. The actor returns links; it does not download or archive the files.

### Tested on real Meta ads

Live tests on September 8, 2026 used the public Ad Library with Apify Residential proxies and 512 MB memory:

| Search | Unique ads delivered | Runtime | Outcome |
|---|---:|---:|---|
| Boat, India | 81 | 25 seconds | Meta reported no next page |
| Burger King, United States | 719 | 315 seconds | Meta reported no next page |
| “dinosaur”, United States | 1,000 | 311 seconds | Reached the configured cap |

All three datasets had **zero duplicate Library IDs**. Independent browser checks matched all 281 sampled visible IDs. Comparisons of 261 overlapping raw ad records found no differences in the checked identity, copy, status, date, platform, and media-path fields, allowing for catalog variants.

Boundary tests also verified exact 1- and 31-ad caps, a genuine empty search, and recovery from an aborted run: 30 saved ads were retained as the run continued to 150 without duplicates.

These are measured examples, not speed guarantees or proof of complete inventory. Meta's approximate result count can differ from delivered unique ads, and availability changes over time.

### Switching from Curious Coder or another Facebook ads scraper

If you use Curious Coder's Facebook Ad Library Scraper, you can reuse a supported **Ad Library search URL** as `targetUrl`. Run one source at a time and set `maxAds` to your desired upper limit.

| Existing workflow | Meta Ad Library Scraper equivalent |
|---|---|
| Curious Coder `urls` containing Ad Library searches | One `targetUrl` per run |
| Per-source result limit | `maxAds` - exact upper limit |
| Facebook Page URL | Extract the numeric Page ID and pass `pageId` |
| Country/status options for a Page | `country` and `activeStatus`; set them explicitly to match your previous task |
| Multiple input URLs | Separate runs or scheduled tasks |
| Raw output consumed by a script | Map to the field names above, particularly `libraryID`, `brand`, `images`, and `videos` |

This actor uses a separate input/output contract. It does not accept another actor's complete configuration unchanged. Curious Coder documents additional details and date-range options; this actor does not provide those enrichment or date-range features. Check the [current Curious Coder input reference](https://apify.com/curious_coder/facebook-ads-library-scraper/input-schema) when migrating an existing task.

For users of our [main Meta Ad Library Scraper](https://apify.com/whoareyouanas/meta-ad-scraper), this actor retains familiar fields such as `libraryID`, `brand`, `body`, `images`, and `videos`. Choose this actor for Page and keyword discovery; use the main actor for its single-ad workflow.

### Use the scraper through the Apify API

Start a run from your application using an Apify API token. You do not need a Meta API token. This request starts the run asynchronously and returns its run ID and default dataset ID:

```bash
curl --request POST \
  'https://api.apify.com/v2/acts/qWCMu9IA87yv3nB3e/runs' \
  --header "Authorization: Bearer ${APIFY_TOKEN}" \
  --header 'Content-Type: application/json' \
  --data '{"searchQuery":"dinosaur","country":"US","maxAds":100}'
```

Follow the run status, then retrieve the default dataset. The actor's **API** tab provides ready-to-use integration examples. See Apify's [run API reference](https://docs.apify.com/api/v2/actors-runs-post) and [dataset export documentation](https://docs.apify.com/platform/storage/dataset).

This is an independently developed scraper using Apify's API, not Meta's official Ads Library API.

### Pricing

Check the actor's **Pricing** tab before running for the current charges. Included output fields do not require a separate creative-detail or advertiser-enrichment toggle.

### Frequently asked questions

#### Can I scrape Instagram ads too?

Yes, when Meta returns Instagram placements in Ad Library results. The `platforms` array identifies the reported publishing platforms. This searches ads in Meta Ad Library, not Instagram posts or profiles.

#### Do I need a Facebook account?

No Facebook login or uploaded cookies are required for public results. Ads with login or age restrictions may have empty creative fields. An Apify account is needed to run the actor on Apify; API access uses your Apify token.

#### Why can an active search contain inactive ads?

Meta can return records marked inactive even when the search requests active ads. This actor preserves each record's returned status. Filter `active === true` in your exported data when you require strictly active rows. Three such inactive records appeared in our 1,000-ad keyword test.

#### Can I get spend, impressions, reach, or ROAS?

This actor does not output spend, impressions, reach, or ROAS. Sorting by total impressions does not expose the underlying impression figures. Use the available copy, creative, date, and advertiser data for research without treating them as performance measurements.

#### Can I retrieve a single ad by Library ID?

This actor accepts search URLs, keywords, and Page IDs. Individual `?id=` URLs are not supported. See our [main Meta Ad Library Scraper](https://apify.com/whoareyouanas/meta-ad-scraper) for single-ad input.

#### Why did I receive fewer ads than `maxAds`?

`maxAds` is a ceiling, not a promised count. Results can end earlier, or a run can reach its budget or runtime limit. Open `RUN_SUMMARY` in the run's key-value store: `complete: true` means Meta reported no next page. A cap or budget stop produces a partial result. A blocked request or incompatible Meta response marks the run failed while preserving ads already saved.

#### Can I request 10,000 ads?

The input accepts up to 10,000. Large searches are subject to a 500-page safety limit and a 540-second HTTP deadline; they may fail with partial saved results. Live validation currently extends to 1,000 ads, so 10,000-ad completion is not guaranteed.

#### Can I export ads to CSV or use them in a spreadsheet?

Yes. Export the dataset from Apify. Use JSON when you need the complete nested `cards`, `images`, and `videos` structure. Use CSV for flat fields such as brand, copy, Library ID, and dates.

### Support

Report an issue through the actor's **Issues** tab with your run URL, search input, and the affected Library IDs. Include the behavior you expected and what you received. Keep API tokens and proxy credentials out of your report.

**Start with one advertiser or keyword and 100 ads to check the output against your workflow.**

# Actor input Schema

## `targetUrl` (type: `string`):

Provide a search URL OR a keyword OR a Page ID. URL filters take precedence over form defaults. Single-ad URLs are not supported.

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

Search public ads by keyword. The example searches nike. Clear it when using a URL or Page ID.

## `pageId` (type: `string`):

Numeric advertiser Page ID. Leave blank when using a URL or keyword.

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

Two-letter country code or ALL. Used for keyword/Page ID searches.

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

Filter by status. Applies to keyword/Page ID searches.

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

Filter by media type. Applies to keyword/Page ID searches.

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

Maximum unique ads delivered in this run. Scraping may stop earlier when results end or the run budget is reached.

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

The fresh form and automatic daily check use no proxy for a one-ad example. Enable Apify Residential for larger searches if needed. API inputs that omit this field retain the Residential default. Custom proxy charges depend on your provider.

## Actor input object example

```json
{
  "searchQuery": "nike",
  "country": "US",
  "activeStatus": "active",
  "mediaType": "all",
  "maxAds": 1,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `summary` (type: `string`):

No description

# API

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

## JavaScript example

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

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

// Prepare Actor input
const input = {
    "searchQuery": "nike",
    "maxAds": 1,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("whoareyouanas/meta-ad-lite-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 = {
    "searchQuery": "nike",
    "maxAds": 1,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("whoareyouanas/meta-ad-lite-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 '{
  "searchQuery": "nike",
  "maxAds": 1,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call whoareyouanas/meta-ad-lite-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,whoareyouanas/meta-ad-lite-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/qWCMu9IA87yv3nB3e/builds/6qwtvUEZPCgw4ZQwd/openapi.json
