Facebook Ads & Ad Library Scraper API
Our Facebook ads scraper reads the public Meta Ad Library and returns an advertiser's ads as structured JSON: the creative body, the ad snapshot URL, the start and end dates, the platforms each ad ran on, and the spend and impression ranges Meta discloses for political and issue ads. Pass a page id, a page name, a keyword, or a full Ad Library URL.
Quickstart
curl "https://api.facebookscraperapi.com/api/v1/facebook/ads?page_id=15087023444&country=US&api_key=$API_KEY" import requests
BASE = "https://api.facebookscraperapi.com"
API_KEY = "YOUR_API_KEY"
# Pass a numeric page_id, a page vanity, a keyword (q), or a full ads/library URL.
data = requests.get(
f"{BASE}/api/v1/facebook/ads",
params={
"page_id": "15087023444", # Nike
"country": "US",
"active_status": "all",
"limit": 30,
"api_key": API_KEY,
},
timeout=30,
).json()
print(data["results_count"], "ads for", data["query"])
for ad in data["ads"]:
print(ad["ad_archive_id"], ad["is_active"], ad["cta_text"])
print(" ", ad["ad_creative_body"])
print(" ", ad["ad_snapshot_url"])
print(" ran:", ad["start_date_iso"], "->", ad["end_date_iso"]) Response
{
"query": "15087023444",
"page_id": "15087023444",
"country": "US",
"active_status": "all",
"results_count": 30,
"total_results": 30,
"source": "embedded",
"ads": [
{
"ad_archive_id": "1520310666349109",
"page_id": "15087023444",
"page_name": "Nike",
"ad_creative_body": "Add a retro touch to any fit.",
"ad_creative_link_title": "Find Nike Near You",
"ad_creative_link_url": "https://www.nike.com/w/womens-summer-essentials-lifestyle-13jrmz5e1x6z6pei9",
"ad_snapshot_url": "https://www.facebook.com/ads/library/?id=1520310666349109",
"start_date": 1777446000,
"start_date_iso": "2026-04-29T07:00:00.000Z",
"end_date": 1779692400,
"end_date_iso": "2026-05-25T07:00:00.000Z",
"is_active": false,
"platforms": ["FACEBOOK", "INSTAGRAM"],
"impressions": { "impressions_text": null, "impressions_index": -1 },
"spend": null,
"currency": null,
"cta_text": "Shop now",
"cta_type": "SHOP_NOW",
"display_format": "IMAGE",
"page_profile_uri": "https://www.facebook.com/nike/",
"page_like_count": 39600590,
"collation_count": 3,
"images": [
"https://scontent-tpe1-1.xx.fbcdn.net/v/t39.35426-6/680632406_1648649816184681_5171813441674285678_n.jpg"
]
},
{
"ad_archive_id": "1181819485586009",
"page_id": "15087023444",
"page_name": "Nike",
"ad_creative_body": "Black women are rarely recognized for the hard work they put in. Join us in celebrating their hard work and help level the playing field. #WePlayReal",
"ad_creative_link_title": null,
"ad_creative_link_url": "https://www.nike.com/",
"ad_snapshot_url": "https://www.facebook.com/ads/library/?id=1181819485586009",
"start_date": 1615190400,
"start_date_iso": "2021-03-08T08:00:00.000Z",
"end_date": 1619766000,
"end_date_iso": "2021-04-30T07:00:00.000Z",
"is_active": false,
"platforms": ["INSTAGRAM"],
"impressions": { "impressions_text": ">1M", "impressions_index": 39 },
"spend": "$40K - $45K",
"currency": "USD",
"cta_text": "Learn more",
"cta_type": "LEARN_MORE",
"display_format": "VIDEO",
"page_profile_uri": "https://www.facebook.com/nike/",
"page_like_count": 39600590,
"collation_count": 28,
"images": null
}
]
} | Field | Type | Description |
|---|---|---|
query | string | The keyword or page id the search was run for. |
page_id | string | The numeric advertiser Page id resolved for the search, or null for a keyword search. |
source | string | Where the ads came from: graphql when the paginated call succeeded, embedded when parsed from the first page render. |
results_count | integer | Number of ads returned in the ads array. |
ads | array | The ads. Each item carries the fields below. |
ad_archive_id | string | The Ad Library archive id, the stable identifier for the ad. |
page_name | string | The advertiser Page name, e.g. Nike. |
ad_creative_body | string | The ad's primary text or caption. |
Why it is hard
The Meta Ad Library is public, but the page is a React app that loads its ad rows from an internal GraphQL call guarded by a per-load lsd token, so a plain request returns an empty shell. The official Ad Library API only covers ads about social issues, elections, or politics and needs an approved access token, so commercial ads from a brand like Nike are not returned there at all.
Use it for
Competitor ad monitoring
Creative and hook research
Ad longevity signals
Political and issue ad transparency
How it compares
| Our API | DIY (requests / headless) | Official Ad Library API | |
|---|---|---|---|
| Commercial (non-political) ads | Yes, any advertiser | Possible but you fight the token and GraphQL | No, issue, election, and political ads only |
| Access | One API key | You mint the lsd token per load | Approved access token plus identity confirmation |
| Setup | API key only | Residential proxies, headless browser, parsers | Meta developer app and Ad Library API access |
| Anti-bot and proxies | Built in, US residential | You build and maintain it | Not applicable |
| Output | Flat, validated JSON | Whatever you parse from GraphQL | JSON you map yourself, limited fields |
| Spend and impressions | Returned where Meta discloses them | You parse them yourself | Returned for political and issue ads |
Pricing
| Plan | Price | Best for |
|---|---|---|
| Free | 1,000 requests | Testing and small jobs |
| Pro | $0.60 / 1k | Production workloads |
| Pay-as-you-go | $0.90 / 1k | Spiky or one-off volume |
Median response 2.6s. You only pay for successful requests.
FAQ
What is a Facebook ads scraper?
A Facebook ads scraper is a tool that reads the public Meta Ad Library and returns an advertiser's ads as structured data. Our Facebook ads scraper API takes a page id, page vanity, keyword, or Ad Library URL and returns each ad's creative body, headline, snapshot URL, run dates, platforms, call-to-action, display format, and the spend and impression ranges Meta discloses for political and issue ads, all as JSON from one request.
Can I scrape ads for any advertiser, or only political ones?
Any advertiser. The Meta Ad Library shows every active and recent ad for any Page, which is why our sample returns 30 commercial ads for Nike. The distinction only affects the disclosure fields: Meta publishes spend and impression ranges for ads about social issues, elections, or politics, so those come back populated, while commercial ads return null spend and impressions because Meta does not disclose them.
Do I need the official Facebook Ad Library API or an access token?
No. You authenticate with a single facebookscraperapi key. The official Ad Library API only covers issue, election, and political ads and requires an approved access token plus identity confirmation, so it cannot return a brand's commercial product ads. Our endpoint reads the public Ad Library that anyone can view in a browser and returns the ads as JSON.
How do I find a page's numeric page_id?
You do not have to. Pass the Page vanity as the page parameter, or a keyword as q, and we resolve the numeric advertiser id for you before searching. If you already have a full ads/library URL with a view_all_page_id, pass it as the url parameter and we parse the id out of it.
Does the API return ad spend and impressions?
For political and issue ads, yes: Meta discloses a spend range like $40K to $45K and an impression range like greater than 1M, and we return them in the spend and impressions fields. For ordinary commercial ads Meta does not publish those figures, so both come back null rather than estimated. This keeps the data honest to what the Ad Library actually shows.
How many ads come back per request?
One Ad Library page is roughly 30 ads, and the limit parameter accepts 1 to 100. We read the ads embedded in the first render and, when the internal pagination call succeeds, follow it for the full set, then de-duplicate by ad_archive_id. The response includes a source field so you can see whether the ads came from the GraphQL pagination or the embedded first page.