# Meta Ad Library & Facebook Ad Library Checker (`kaleidoscopelabs/facebook-ads-library-checker`) Actor

Facebook Ads Library checker: see whether a Facebook Page or brand runs ads, its ad count, the day its latest ad started, and its latest ads with text, links and dates. Enter Page links, IDs or brand names; a Page with no ads is answered too.

- **URL**: https://apify.com/kaleidoscopelabs/facebook-ads-library-checker.md
- **Developed by:** [Kaleidoscope Labs](https://apify.com/kaleidoscopelabs) (community)
- **Categories:** Social media, Lead generation, E-commerce
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.80 / 1,000 lookups

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

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

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

## How to integrate an Actor?

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

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

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

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

# README

### What can Facebook Ad Library Checker do?

**Check in the Facebook Ads Library whether a Facebook Page or a brand runs ads: how many, the day its latest ad started, and its latest ads, one record per Page or name.**

- 🔎 **Is it advertising?** Each Page or brand gets a clear answer under your filters, a Page with no ads included.
- 🔢 **How many ads:** the library's own count of the Page's ads, for a country or anywhere, running now or all.
- 📅 **Since when:** the day its newest ad started.
- 🖼️ **The latest ads:** up to 1,000 per Page, newest first, with their text, headline, link, button, dates, platforms and format.
- 🔗 **Page links:** a Page ID or an Ad Library link of a Page goes straight to that Page; a Facebook Page link is found by its username, and when it can't be, the record says so and isn't charged.
- 🏷️ **Brand names:** enter a brand as you would type it in the library's search box; the run takes the first Page the library suggests with that name (accents, punctuation and a legal form such as Inc aside), and says how sure the match is.

Run it from Apify Console, through the API, on a schedule, or from an AI agent.

![Four Pages checked for active ads in all countries: HubSpot runs 277, the latest started 31 Oct; Zendesk 154; Freshworks 17; and one Page runs none.](https://assets.kaleidoscopelabs.io/afy/fb-checker/pages-running-ads.ffbc3cce.png)

### What data can you get from the Facebook Ad Library?

One record per Page or name:

| Data | Field |
|---|---|
| The line as you gave it, whether it was a Page or a name, and the record's type | `query`, `queryType`, `recordType` |
| Whether the Page runs ads under the filters | `runsAds` |
| The library's count of its ads, and whether it shows more than 50,000 | `adCount`, `adCountCapped` |
| The day its newest ad started | `latestStart` |
| The Page's ID, name, link, picture, categories and likes | `pageId`, `pageName`, `pageUrl`, `pagePictureUrl`, `pageCategories`, `pageLikes` |
| The Page's list in the Ad Library, as the run read it (Most recent) | `libraryUrl` |
| Whether the Page is labelled as a person's (to leave such Pages out) | `personLabelled` |
| How the Page was found, whether Meta verified it, at least how many other Pages carry the same name, the match's place among the library's suggestions, how its name compares with yours, and how sure the match is | `matchedBy`, `pageVerified`, `sameNamePages`, `suggestionPlace`, `matchedTier`, `retriedBare`, `matchStrength` |
| Its latest ads: ID, link, dates and days active, text, headline, link with its description and domain, button, platforms, format, versions, the AI-media flag, image and video links, and a carousel's cards | `ads` |
| With a monitor: the new ads, whether anything changed, and how many ads were read (see below) | `newAds`, `changed`, `adsChecked` |
| The filters the record was read under, and when | `country`, `activeOnly`, `readAt` |
| What the record lacks, and why | `missing` |

![One lookup record for monday.com, shortened: the Page's ID, name and category, its 553 active ads and the day the latest started, then its latest ads, each with its ID, dates, platforms and format.](https://assets.kaleidoscopelabs.io/afy/fb-checker/page-record.bd474ff8.png)

With **Only ads running now** on, `runsAds: false` means no ads running now, not that the Page never advertised. When the library counts a Page's ads but shows none of them, the record answers with the count (`runsAds`, `adCount`) and says its ads were not given (`missing`). Start dates are days: ads that started on the same day have no order among them. A carousel ad's cards come with it, each with its own text, link, button and media.

Media links (`imageUrls`, `videos`, the cards' and `pagePictureUrl`) are Meta's and expire, usually within a few days: `mediaExpires` gives the day for an ad's links. Download them within your run's flow.

### How to use Facebook Ad Library Checker

1. Create a free Apify account and open Facebook Ad Library Checker.
2. In **Facebook Page links or IDs**, enter Pages, one per line (a Page ID or an Ad Library link is the surest); or in **Brand or Page names**, enter names, for the best match.
3. Choose the **Country** (a two-letter code, or ALL), whether to count only ads running now, and how many of each Page's latest ads you want.
4. Click **Start**. Records appear in the Output tab; export them as JSON, CSV or Excel, or read them from the API.

### How to monitor Pages for new ads

Enter a **Monitor name** and run the same input on a schedule. Each run checks every Page and name, one record each, and carries only ads the monitor has not seen before:

- `newAds` counts every ad that is new since the monitor's last run. The record carries the newest of them, up to 30 unless **Latest ads per Page** is set; the rest are counted, not returned, and later runs do not return them. With 0 the monitor counts new ads and returns none.
- A new ad is one that started after you began monitoring the Page, or any ad newly listed while the Page fits in one read (30 ads or fewer). An older ad that only now comes among the 30 a check reads is not new, so a monitor can show fewer new ads than a plain comparison of two lookups.
- On a Page with more than 30 ads in the current month, the library lists them by relevance, so a run sees 30 of them; a new ad past them is returned in a later run, once it is among them.
- `adsChecked` is how many ads the run read, the first the library lists for the Page (up to 30); `newAds` counts the new ones among them.
- `changed` is true when the Page has new ads, or started or stopped running ads, since the monitor's last run. Filter on `changed` for alerts.
- Each Page's first run returns its latest ads as a lookup does, 3 unless Latest ads per Page is set, and `newAds` and `changed` are absent: there is no earlier run to compare with. The monitor starts from that run: the ads it returned are never returned again, and an ad that ran before it is not new later, unless it is newly listed on a Page that fits in one read.

The monitor keeps what it has seen in a key-value store of its own in your account, `fb-ads-monitor-<name>`. If a run cannot save what it found, after trying again at its end, it says so in its status, and its next run may return those ads again. To start a monitor over, delete that store or use a new name; a Page checked under another Country or Only ads running now setting starts over too. Let a monitor's runs not overlap: two at once may both return the same new ads. A Page given twice in one input (by its link and its ID, or by a name that finds it) is checked twice, and its new ads come in one of the two records. Each check is charged as a lookup, and each ad a record carries as an ad.

![One monitor on 2 Pages: the first run carries 60 ads; run again a minute later, it carries no new ads, and the 60 it checked are not charged again.](https://assets.kaleidoscopelabs.io/afy/fb-checker/monitor-new-ads.51318110.png)

### How much does it cost to check a Page's ads?

Facebook Ad Library Checker is priced per event, with no usage fees on top:

| Event | Price | When |
|---|---|---|
| Lookup | $0.004 each | each Page or name looked up, whether it runs ads or not |
| Ad | $0.00075 each | each ad a record carries: **Latest ads per Page**, 3 when left empty (a monitor's later runs: up to 30 new ads), 0 for the check only |

The platform also charges $0.00005 when a run starts. A line that is not a Page, a Facebook Page link whose Page could not be found, or a line the run could not look up, is not charged, and a Page with fewer ads than you ask for costs less. The prefilled input (one name, a lookup with 3 ads) costs at most $0.00625, plus the start. A run's spending limit must cover a whole record, a lookup and its ads: below that, nothing is stored.

| You check | Latest ads per Page | It costs at most |
|---|---|---|
| 1,000 Pages or names | 0 (the check only) | $4.00 |
| 1,000 Pages or names | 3 (left empty) | $6.25 |
| 1,000 Pages or names | 30 | $26.50 |

- **Apify's free plan credit of $5 a month** covers about 1,250 checks, or 800 lookups with 3 ads each.

### Input example

A Page link and two brand names, in the United States, the check only:

```json
{
  "pages": ["https://www.facebook.com/mondaydotcom"],
  "names": ["Pipedrive", "HubSpot"],
  "country": "US",
  "activeOnly": true,
  "adsPerPage": 0
}
```

### Output example

The record for HubSpot from a run of the input above, as returned (the picture link shortened). With **Latest ads per
Page** at 0 it carries no ads, and `missing` says they were not asked for:

```json
{
  "recordType": "lookup",
  "query": "HubSpot",
  "queryType": "name",
  "matchedBy": "name",
  "country": "US",
  "activeOnly": true,
  "readAt": "2026-11-02T20:33:07Z",
  "pageId": "6039999393",
  "pageName": "HubSpot",
  "pageUrl": "https://facebook.com/hubspot",
  "pagePictureUrl": "https://scontent…fbcdn.net/v/…",
  "pageCategories": [
    "Product/service"
  ],
  "pageLikes": 2130286,
  "pageVerified": true,
  "sameNamePages": 4,
  "suggestionPlace": 1,
  "matchedTier": "exact",
  "retriedBare": false,
  "matchStrength": "strong",
  "personLabelled": false,
  "runsAds": true,
  "adCount": 108,
  "adCountCapped": false,
  "latestStart": "2026-10-30",
  "libraryUrl": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&is_targeted_country=false&media_type=all&search_type=page&view_all_page_id=6039999393&sort_data[direction]=desc&sort_data[mode]=relevancy_monthly_grouped",
  "ads": [],
  "missing": [
    {
      "group": "ads",
      "reason": "notRequested"
    }
  ]
}
```

Did it save you time? A rating on this page helps others find it; an Issue tells us what to fix.

### FAQ

#### Is it legal to read the Facebook Ad Library?

The Ad Library is public: Meta publishes it so that anyone can see the ads Pages run. This Actor reads what any visitor sees, without an account. Check the rules that apply to your use of the data.

#### Does it collect personal data?

The names, links, categories and likes of persons' Pages (public figures, creators, artists) and the creators of partnership ads are left out by default: such a Page's record keeps whether it runs ads, the count, the latest start and its ads, without naming the Page. Turn **Pages of persons** or **Creators of partnership ads** on only with a lawful basis of your own under the GDPR. Each record's `personLabelled` field lets you leave persons' Pages out. A Page whose category can't be read is treated as a person's. Apify runs in the United States.

#### How sure is a match by name?

A Page ID or an Ad Library link of a Page goes straight to that Page, with no match to make. A name is matched to one Page, and the record shows which: `pageName`, `pageId` and `pageUrl` (a person's Page aside, above). The match is the first Page the library suggests whose name is yours, or yours with other accents, punctuation or "&" for "and" (`matchedTier` marks), or with a legal form such as Inc, plc or Group added or left out (`matchedTier` suffix). Many brands' own Pages are not verified, and a common word can be the name of several Pages, or of another business than the one you mean. `matchStrength` says how sure the match is: strong when Meta verified the Page and suggested it first for the name, weak otherwise. Weak matches are worth a look. Enter the name as the Page writes it (monday.com, not Monday), or for a sure answer, the brand's Page ID or Ad Library link.

#### Why does a name find no Page?

No Page the library suggests carries that name, even with other accents or punctuation, or with or without a legal form; when the library suggests nothing at all, the name is tried once more without its legal form (`retriedBare`). Enter the brand's Page ID or Ad Library link instead, or the name as the Page writes it.

#### A record has no Page name: was no Page found?

Not always. When no Page is found, `missing` says so (the Page not found, or not found by link) and `runsAds` stays empty. When a Page is found but its category is one persons use, the run withholds its name, link, categories and likes, and for a name or username also its ID: `personLabelled` is true and `missing` says the Page was not requested. `runsAds` and `adCount` then answer for that Page. If you looked up a business by name, such a match is often another Page with the same name: check `matchStrength`, or enter the brand's Page ID or Ad Library link.

#### Why does a Facebook Page link find no Page?

A Facebook Page link (facebook.com/name) carries the Page's username, which the Ad Library does not look up directly. The run looks for the Page whose username is exactly that one, and never takes another Page instead. When it can't find it, the record says so in `missing` (the Page not found by link), `runsAds` and `adCount` stay empty (never false), and the line is not charged. Enter that Page's ID or its Ad Library link instead: a Page's Ad Library link carries its ID (view_all_page_id).

### Support and feedback

Open an issue on the Issues tab with the run's ID and the Ref from the run's last message: it tells us what happened without your data.

### Other Actors

| Actor | Use it with this one to |
|---|---|
| [Google Ads Transparency Center Scraper & Monitor](https://apify.com/kaleidoscopelabs/google-ads-transparency-data) | See whether the same companies advertise on Google too, and what their ads say |

*Facebook Ad Library Checker is an independent tool, not affiliated with, endorsed by or sponsored by Meta Platforms, Inc. Facebook is a trademark of Meta Platforms, Inc.*

# Changelog

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

# Actor input Schema

## `pages` (type: `array`):

One per line: a Page's numeric ID or an Ad Library link of a Page (with view_all_page_id), which go straight to that Page; or a Facebook Page link (facebook.com/<name>), whose Page is looked up by its username, never another Page: when it can't be found, the record says so and is not charged. An Ad Library link's own filters apply to its line (country, ad status, media type, platforms, languages, start dates), over the ones below; a filter it leaves out is the one below. A line that is none of these, or a link with a filter the run does not apply, is skipped, not charged, and its record says why.

## `names` (type: `array`):

One per line: a brand or a Page's name, as you would type it in the Ad Library's search box: a best match, the first Page the library suggests with that name (accents, punctuation and a legal form such as Inc aside), verified or not; the record says how sure the match is. A name no Page carries is answered so. For a sure answer, enter the Page link.

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

Where the ads ran: a two-letter country code such as US or DE, or ALL for anywhere.

## `activeOnly` (type: `boolean`):

On: the ads running now. Off: ended ads too.

## `adsPerPage` (type: `integer`):

How many of a Page's latest ads its record carries, 0 to 1,000 (30 with a monitor); each costs one ad. Past 30 the Page's list is read further, about 5 seconds for every 10 more ads. Left empty: 3 for a lookup and a monitor's first run of a Page, then up to 30 new ads a run. 0 returns no ads: whether it runs ads, the count and the latest start day are read either way, and with a monitor, 0 counts the new ads and returns none.

## `monitorName` (type: `string`):

Name a monitor (letters, digits, hyphens) to get, on every run, only the ads new since its last run, with newAds and changed on each record. Each Page's first run returns its latest ads, as a lookup does. Leave empty for plain lookups.

## `includePersonPages` (type: `boolean`):

On: the name, link, categories and likes of Pages whose category is one persons use (a public figure, a creator, an artist). Off, those Pages' records keep whether they run ads, the count, the latest start and the ads, without naming the Page; a Page whose category can't be read is treated as a person's. Personal data under the GDPR: turn it on only with a lawful basis of your own.

## `includeCreators` (type: `boolean`):

On: the Page of the creator a partnership ad is shown under. Personal data under the GDPR: turn it on only with a lawful basis of your own.

## Actor input object example

```json
{
  "pages": [
    "https://www.facebook.com/mondaydotcom",
    "https://www.facebook.com/ads/library/?view_all_page_id=6039999393",
    "161613810523306"
  ],
  "names": [
    "monday.com",
    "Pipedrive"
  ],
  "country": "US",
  "activeOnly": true,
  "includePersonPages": false,
  "includeCreators": false
}
```

# Actor output Schema

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

One record per Page or name in the run's default dataset: whether it runs ads, how many, the latest start, its latest ads, and what the record lacks.

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

What the run did: the lookups stored, the names with no Page, what could not be looked up, and the Ref to quote in an issue.

## `progress` (type: `string`):

The Pages and names the run could not look up: written when the platform moves the run and at its end, so a run moved or resurrected counts them once.

# 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 = {
    "pages": [],
    "names": [
        "monday.com"
    ],
    "country": "ALL"
};

// Run the Actor and wait for it to finish
const run = await client.actor("kaleidoscopelabs/facebook-ads-library-checker").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 = {
    "pages": [],
    "names": ["monday.com"],
    "country": "ALL",
}

# Run the Actor and wait for it to finish
run = client.actor("kaleidoscopelabs/facebook-ads-library-checker").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 '{
  "pages": [],
  "names": [
    "monday.com"
  ],
  "country": "ALL"
}' |
apify call kaleidoscopelabs/facebook-ads-library-checker --silent --output-dataset

```

## MCP server setup

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

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/fcbbZVKE1FeDkim21/builds/9UoU2ZTm637vsX7Go/openapi.json
