Skip to main content
Glama
leyovco

Facebook Ad Library MCP

by leyovco
README.md
# Facebook Ad Library MCP

A small MCP server that scrapes the public Facebook Ad Library for competitive ad research — from your MCP client, with no Facebook account and no API token.

## Install

```bash
git clone https://github.com/leyovco/facebook-ads-library-mcp.git
cd facebook-ads-library-mcp
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
python -m playwright install chromium   # crawl4ai needs a browser
```

### Register with your MCP client

Claude Code:
```bash
claude mcp add facebook-ads -- /abs/path/venv/bin/python /abs/path/facebook_ads_mcp_complete.py
```

Claude Desktop (`claude_desktop_config.json`):
```json
{
  "mcpServers": {
    "facebook-ads": {
      "command": "/abs/path/venv/bin/python",
      "args": ["/abs/path/facebook_ads_mcp_complete.py"]
    }
  }
}
```

Restart the client.

## Usage

```
"Search the Mexico Ad Library for 'automatización con inteligencia artificial',
 group by advertiser, and list the landing domains."

"Scrape https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=MX&q=nike&search_type=keyword_unordered
 with scroll_rounds=15 and summarise the creative angles."
```

## Tools

Two tools:

- **`search_ad_library(query, country="MX", ...)`** — keyword search.
- **`scrape_ad_library_url(url, ...)`** — scrape any Ad Library URL you already have.

Both return structured records per ad:

| field | meaning |
|---|---|
| `advertiser`, `advertiser_handle` | Page name and its `facebook.com/<handle>` |
| `started_running` | first-seen date |
| `ads_using_creative` | how many creatives share this copy — a rough scale signal |
| `landing_url`, `landing_domain` | destination, unwrapped from the `l.facebook.com` redirect |
| `cta` | the button label (`Learn more`, `Sign up`, `Send message`, …) |
| `link_text` | the headline strip under the creative |
| `body` | full ad copy |
| `creative_image` | thumbnail URL |
| `ad_details_url` | deep link to that ad's detail view |

Plus an `advertisers` histogram and the `raw_markdown` of the page so the model can pull anything the parser missed.

## Configuration

- **`scroll_rounds`** (default 8)
- **`wait_seconds`** (default 8)
- **`country`** — ISO code (e.g., `MX`, `US`, `ES`)
- **`advertiser_page_id`** — target one Page's "all ads" view (less reliable than keyword search)

## How it works

`crawl4ai` (`AsyncWebCrawler`) opens the Ad Library URL in headless Chromium, waits for the React app to hydrate, runs a scroll loop to trigger lazy-loaded cards, serialises the DOM to markdown, and a regex parser (`_parse_ad_library_markdown`) splits it on `Library ID:` boundaries and pulls the fields above.

Facebook answers the headless browser with **HTTP 403** but still serves the rendered cards, so the tools judge success by whether cards parsed, not by status code.

## License

MIT — original by Ramses Aguirre (RamsesAguirre777). Adapted and hosted under leyovco.