Ad Library Search & Get Ad
curl --request GET \
--url https://scrapebadger.com/v1/facebook/ads/search \
--header 'X-API-Key: <x-api-key>'import requests
url = "https://scrapebadger.com/v1/facebook/ads/search"
headers = {"X-API-Key": "<x-api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<x-api-key>'}};
fetch('https://scrapebadger.com/v1/facebook/ads/search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://scrapebadger.com/v1/facebook/ads/search",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://scrapebadger.com/v1/facebook/ads/search"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<x-api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://scrapebadger.com/v1/facebook/ads/search")
.header("X-API-Key", "<x-api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://scrapebadger.com/v1/facebook/ads/search")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<x-api-key>'
response = http.request(request)
puts response.read_body{
"ads": [
{}
],
"ads[].transparency": {},
"count": 123,
"end_cursor": "<string>",
"has_next_page": true,
"query": "<string>"
}Endpoints
Ad Library Search & Get Ad
Search Facebook’s public Ad Library by advertiser or keyword — creative copy, snapshot URL, flight dates, platforms, media and CTA.
GET
/
v1
/
facebook
/
ads
/
search
Ad Library Search & Get Ad
curl --request GET \
--url https://scrapebadger.com/v1/facebook/ads/search \
--header 'X-API-Key: <x-api-key>'import requests
url = "https://scrapebadger.com/v1/facebook/ads/search"
headers = {"X-API-Key": "<x-api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<x-api-key>'}};
fetch('https://scrapebadger.com/v1/facebook/ads/search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://scrapebadger.com/v1/facebook/ads/search",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://scrapebadger.com/v1/facebook/ads/search"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<x-api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://scrapebadger.com/v1/facebook/ads/search")
.header("X-API-Key", "<x-api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://scrapebadger.com/v1/facebook/ads/search")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<x-api-key>'
response = http.request(request)
puts response.read_body{
"ads": [
{}
],
"ads[].transparency": {},
"count": 123,
"end_cursor": "<string>",
"has_next_page": true,
"query": "<string>"
}Search Facebook’s public Ad Library, the transparency archive of ads
running across Facebook, Instagram, Messenger and the Audience Network — or
look one up directly by its archive id.
Credits: 5 (each)
Query Parameters —
Path Parameters —
| Endpoint | Returns |
|---|---|
GET /v1/facebook/ads/search | keyword / advertiser search, cursor-paginated |
GET /v1/facebook/ads/{ad_archive_id} | one ad by its archive id |
Authorization
string
required
Your ScrapeBadger API key.
Query Parameters — /ads/search
string
required
Advertiser name or keyword.
string
default:"US"
ISO 3166-1 alpha-2 country code. The Ad Library is partitioned by country —
the same advertiser returns different ads per market.
string
default:"all"
One of
all, political_and_issue_ads. Political and issue ads carry extra
disclaimers in the archive.string
default:"active"
One of
active, inactive, all.string
Pagination cursor — the
end_cursor from a previous response.Path Parameters — /ads/{ad_archive_id}
string
required
The Ad Library archive id, as returned in
ad_archive_id on any search
result.string
default:"US"
ISO 3166-1 alpha-2 country code for the lookup. Pass an EU/UK code (e.g.
DE, FR, GB) to get the transparency object with EU DSA reach and
demographic data.Response
AdLibraryAd[]
Each
AdLibraryAd includes ad_archive_id, page_id, page_name,
ad_creative_body, ad_creative_link_title, ad_creative_link_caption,
ad_creative_link_description, ad_snapshot_url (Facebook-hosted rendered
preview), start_date_utc, start_date, end_date_utc, end_date (null
while the ad is still running), is_active, publisher_platforms[]
(FACEBOOK, INSTAGRAM, MESSENGER, AUDIENCE_NETWORK), images[],
videos[], cta_text (button label) and cta_type (Facebook’s CTA enum,
e.g. SHOP_NOW, LEARN_MORE, SIGN_UP).AdTransparency
Lookup endpoint only, when
country is an EU/UK market or the ad targets
the EU. Carries payer_beneficiary[] ({payer, beneficiary} pairs),
targets_eu, has_violating_payer_beneficiary, is_ad_taken_down,
is_violating_eu_siep and eu_transparency — the DSA disclosure:
eu_total_reach, gender_audience, age_audience_min /
age_audience_max, location_audience[] ({name, type, excluded, num_obfuscated}) and age_country_gender_reach_breakdown[] (per-country
age_gender_breakdowns[] with age_range, male, female, unknown
reach).integer
Number of ads in this page.
string
Pass as
after for the next page. Search only.boolean
Whether more ads are reachable. Search only.
string
Echoes the query (or the archive id on the lookup endpoint).
Example
curl "https://scrapebadger.com/v1/facebook/ads/search?query=Nike&country=US&active_status=active" \
-H "X-API-Key: YOUR_API_KEY"
const res = await fetch(
"https://scrapebadger.com/v1/facebook/ads/search?" +
new URLSearchParams({
query: "Nike",
country: "US",
active_status: "active",
}),
{ headers: { "X-API-Key": process.env.SCRAPEBADGER_API_KEY } },
);
const data = await res.json();
import requests
res = requests.get(
"https://scrapebadger.com/v1/facebook/ads/search",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"query": "Nike", "country": "US", "active_status": "active"},
)
data = res.json()
Response
{
"ads": [
{
"ad_archive_id": "1284772093418206",
"page_id": "15087023444",
"page_name": "Nike",
"ad_creative_body": "Built for the long run. The new Pegasus 42 lands today.",
"ad_creative_link_title": "Pegasus 42",
"ad_creative_link_caption": "nike.com",
"ad_creative_link_description": "Free shipping for members.",
"ad_snapshot_url": "https://www.facebook.com/ads/library/?id=1284772093418206",
"start_date_utc": 1785225600.0,
"start_date": "2026-07-26T14:40:00Z",
"end_date_utc": null,
"end_date": null,
"is_active": true,
"publisher_platforms": ["FACEBOOK", "INSTAGRAM"],
"images": [
"https://scontent.xx.fbcdn.net/v/t39.35426-6/449120_n.jpg"
],
"videos": [],
"cta_text": "Shop Now",
"cta_type": "SHOP_NOW"
}
],
"count": 1,
"end_cursor": "AQHZHZHNfbGlicmFyeV9jdXJzb3JfMDAx",
"has_next_page": true,
"query": "Nike"
}
Example — EU transparency
Look an ad up with an EUcountry to get the DSA transparency block:
cURL
curl "https://scrapebadger.com/v1/facebook/ads/1284772093418206?country=DE" \
-H "X-API-Key: YOUR_API_KEY"
Response (transparency excerpt)
{
"ads": [
{
"ad_archive_id": "1284772093418206",
"page_name": "Nike",
"transparency": {
"payer_beneficiary": [
{ "payer": "Nike Retail B.V.", "beneficiary": "Nike Retail B.V." }
],
"targets_eu": true,
"has_violating_payer_beneficiary": false,
"is_ad_taken_down": false,
"is_violating_eu_siep": false,
"eu_transparency": {
"targets_eu": true,
"eu_total_reach": 1834920,
"gender_audience": "All",
"age_audience_min": 18,
"age_audience_max": 65,
"location_audience": [
{ "name": "Germany", "type": "country", "excluded": false, "num_obfuscated": 0 }
],
"age_country_gender_reach_breakdown": [
{
"country": "DE",
"age_gender_breakdowns": [
{ "age_range": "18-24", "male": 141203, "female": 152884, "unknown": 4102 },
{ "age_range": "25-34", "male": 289441, "female": 301276, "unknown": 8817 }
]
}
]
}
}
}
],
"count": 1,
"query": "1284772093418206"
}
The Ad Library is country-partitioned. To size a competitor’s full spend
footprint, sweep
country across the markets you care about rather than
paginating a single one deeper. On the lookup endpoint, an EU country
additionally unlocks the DSA transparency block — reach, demographics and
payer/beneficiary — even for ads you first found via a US search.
