Skip to main content
Thirdwatchthirdwatch
Social media

Scrape Facebook Ad Library for Competitive Intel (2026)

Pull active Facebook and Instagram ads for any brand from Meta's Ad Library. Returns ad count, creative text, CTA buttons, platforms, and start dates.

May 26, 2026 · 6 min read · 1,299 words
See the scraper →

Thirdwatch's Facebook Ad Library Scraper extracts active ad data from Meta's public Ad Library for any brand -- ad count, creative text, call-to-action buttons, start dates, and platform distribution across Facebook, Instagram, Messenger, and Audience Network. No Facebook account required. Built for growth marketers, competitive analysts, and agency strategists who need structured ad intelligence at scale.

Why scrape the Facebook Ad Library for competitive intel

Meta's Ad Library is one of the few places where you can see exactly what ads a competitor is running right now. According to Meta's transparency report, the Ad Library contains ads from over 200 countries and territories, covering billions of active impressions. Research from eMarketer projects global digital ad spending to exceed $700 billion in 2026, with Meta capturing a significant share. For growth teams, the Ad Library is the closest thing to a real-time window into competitor acquisition strategy.

The job-to-be-done is clear. A DTC brand manager wants to know how many ads Allbirds is running this week, what messaging they lead with, and whether they skew toward Facebook or Instagram placement. A performance agency pitching a new client needs a creative audit of the top five players in the category. A startup founder reverse-engineering a competitor's go-to-market wants to see which CTAs they test and how long each creative runs. All of these reduce to brand name + country + ad type queries returning structured rows with creative-level detail. The actor is the data layer.

How does this compare to the alternatives?

Three options for getting Facebook Ad Library data into a pipeline:

Approach Pricing Reliability Setup time Maintenance
Meta Ad Library API (official) Free, rate-limited Restricted to political/issue/housing/employment/credit ads only 2-4 weeks (business verification required) You handle API changes
DIY scraper with Playwright/Puppeteer Free compute, weeks of dev Brittle -- Meta changes DOM frequently 4-8 weeks You own anti-bot + DOM selectors
Thirdwatch Facebook Ad Library Scraper Pay per result Covers all ad categories, no verification needed 5 minutes Thirdwatch tracks Meta changes

The key gap with Meta's official API is coverage: it only returns regulated ad categories (political, housing, employment, credit) in most markets. The Facebook Ad Library Scraper covers all ad categories visible in the Ad Library, including standard commercial ads, with no business verification or approval process.

How to scrape Facebook Ad Library for competitive intel in 4 steps

Step 1: How do I set up my Apify API token?

Sign in at apify.com (free tier, no credit card required), open Settings, then Integrations, and copy your personal API token. Every example below assumes the token is exported:

export APIFY_TOKEN="apify_api_xxxxxxxxxxxxxxxx"

Step 2: How do I pull active ads for competitor brands?

Pass brand names in brands, set country to filter by market, and maxCreatives to control how many individual ad samples you want.

import os, requests, pandas as pd

ACTOR = "thirdwatch~fb-ad-library-scraper"
TOKEN = os.environ["APIFY_TOKEN"]

resp = requests.post(
    f"https://api.apify.com/v2/acts/{ACTOR}/run-sync-get-dataset-items",
    params={"token": TOKEN},
    json={
        "brands": ["allbirds", "on running", "hoka"],
        "country": "ALL",
        "adType": "all",
        "maxCreatives": 50,
    },
    timeout=600,
)
df = pd.DataFrame(resp.json())
print(f"{len(df)} brands analyzed")
for _, row in df.iterrows():
    print(f"  {row['brand']}: {row['adCount']} active ads, {row['creativeCount']} creatives captured")

Three brands with up to 50 creatives each. The country parameter accepts ISO codes (US, IN, GB, CA, AU) or ALL for worldwide. The adType field defaults to all -- use political_and_issue_ads, housing_ads, employment_ads, or credit_ads to narrow to regulated categories.

Step 3: How do I analyze competitor creative strategy?

Once you have the dataset, explode the creatives array to analyze messaging patterns, CTA distribution, and platform mix.

import json

records = resp.json()
rows = []
for brand_data in records:
    for creative in brand_data.get("creatives", []):
        rows.append({
            "brand": brand_data["brand"],
            "adCount": brand_data["adCount"],
            "text": creative.get("textSnippet", ""),
            "cta": creative.get("cta", ""),
            "startDate": creative.get("startDate", ""),
            "platforms": ", ".join(creative.get("platforms", [])),
        })

creative_df = pd.DataFrame(rows)

# CTA distribution per brand
cta_counts = creative_df.groupby(["brand", "cta"]).size().reset_index(name="count")
print(cta_counts.sort_values(["brand", "count"], ascending=[True, False]))

# Platform mix
platform_counts = creative_df["platforms"].value_counts()
print(f"\nPlatform distribution:\n{platform_counts}")

This tells you whether a competitor leans on "Shop Now" vs "Learn More" CTAs, whether they favor Instagram-only placement or cross-platform distribution, and which creatives have been running the longest (oldest startDate).

Step 4: How do I schedule recurring competitive audits?

Set up an Apify schedule to pull competitor ad data on a weekly cadence and push results to a webhook.

curl -X POST "https://api.apify.com/v2/schedules?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "competitor-ad-audit-weekly",
    "cronExpression": "0 9 * * 1",
    "timezone": "America/New_York",
    "isEnabled": true,
    "actions": [{
      "type": "RUN_ACTOR",
      "actorId": "thirdwatch~fb-ad-library-scraper",
      "runInput": {
        "brands": ["allbirds", "on running", "hoka", "nike running", "brooks running"],
        "country": "US",
        "adType": "all",
        "maxCreatives": 30
      }
    }]
  }'

Add an ACTOR.RUN.SUCCEEDED webhook pointing at your analytics pipeline or Slack channel. Every Monday at 9 AM Eastern, you get a fresh snapshot of competitor ad activity. Store each weekly snapshot and diff adCount values over time to detect when a competitor scales up or pauses campaigns.

Sample output

A single dataset item for one brand looks like this:

{
    "brand": "allbirds",
    "country": "US",
    "adType": "all",
    "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=allbirds",
    "active": true,
    "adCount": 42,
    "creatives": [
        {
            "startDate": "Mar 18, 2026",
            "platforms": ["Facebook", "Instagram"],
            "cta": "Shop Now",
            "textSnippet": "New Tree Runners. Made with eucalyptus. Comfortable from your first step."
        },
        {
            "startDate": "Apr 2, 2026",
            "platforms": ["Instagram"],
            "cta": "Learn More",
            "textSnippet": "Plant-based materials. Real carbon reduction. Meet Allbirds."
        }
    ],
    "creativeCount": 20,
    "scraped_at": "2026-05-26T10:30:00.000Z"
}

adCount is the total active ads Meta reports for that brand and country filter. creatives contains up to maxCreatives individual ad samples. Each creative includes startDate (when the ad launched), platforms (which Meta surfaces the ad appears on), cta (the call-to-action button text), and textSnippet (the ad copy visible in the Library card view). active: false means the brand has no ads running under that country and ad-type filter.

Common pitfalls

Three things trip up production Ad Library pipelines. EU/UK/US coverage gaps -- Meta restricts the Ad Library in these markets to political, issue, housing, employment, and credit ads only. If you search for a consumer brand in the US and get zero results, it is not a bug; switch to country: "ALL" or target a non-restricted market like India or Brazil. Brand name ambiguity -- searching "apple" returns ads from Apple Inc. but also Apple Federal Credit Union, Apple Vacations, and dozens of other pages. Use the most specific brand or page name possible. Creative truncation -- textSnippet captures the text visible in the Ad Library card, not the full ad copy. Longer ads get truncated. For full creative text, the Ad Library detail page has more, but the snippet is sufficient for competitive pattern analysis.

Thirdwatch's actor handles the anti-bot work and page rendering so you get structured JSON without managing browser sessions or DOM selectors. The actor tracks Meta's Ad Library changes so your pipeline stays current.

For broader competitive intelligence, combine Ad Library data with social media profile insights. Pull engagement metrics from Instagram profiles to see how a competitor's organic content strategy complements their paid campaigns. Overlay TikTok profile data to understand whether a brand is shifting ad budget toward short-form video platforms. The Ad Library gives you the paid side; organic social data gives you the earned side. Together they form a complete picture of competitor acquisition strategy across Meta, Instagram, and TikTok.

Related use cases

Frequently asked questions

Do I need a Facebook account to scrape the Ad Library?

No. Meta's Ad Library is a public transparency tool. The scraper accesses it without any login, cookies, or Facebook account. You only need an Apify API token to run the actor.

Which countries show commercial ads in the Ad Library?

Meta shows all ad categories in most countries outside the EU, UK, and US. In the EU, UK, and US, only political, issue, housing, employment, and credit ads are publicly surfaced. Commercial brand ads are visible in regions like India, Brazil, and Southeast Asia.

Can I get ad spend data from the Facebook Ad Library?

Only for political, issue, housing, employment, and credit ads. Meta publishes spend ranges for those regulated categories. Standard commercial ads do not include spend data in the Ad Library.

How many ad creatives can I pull per brand?

Up to 200 per brand via the maxCreatives parameter. The default is 20. Set maxCreatives to 0 if you only need the active ad count without individual creative details.

How often should I re-scrape for competitive monitoring?

Weekly is sufficient for most competitive intel use cases. Brands typically rotate creatives on a 2-4 week cycle. For fast-moving categories like DTC or political campaigns, daily or every-other-day scraping catches new launches faster.

Related

Try it yourself

100 free credits, no credit card.

About 30 real searches. Add the MCP to Claude or Cursor in two minutes.