Google Ads Library Scraper
Pricing
from $2.00 / 1,000 results
Google Ads Library Scraper
Scrapes ads from the Google Ads Transparency Center. Returns creative content, advertiser info, ad format, dates, and asset URLs.
Pricing
from $2.00 / 1,000 results
Rating
2.4
(4)
Developer
Practical Tools
Maintained by CommunityActor stats
0
Bookmarked
25
Total users
5
Monthly active users
14 days ago
Last modified
Categories
Share
Google Ads Transparency Center Scraper
Scrapes ads from the Google Ads. Returns creative content, advertiser info, ad format, dates, and asset URLs.
Features
- No login required — Google's Transparency Center is publicly accessible
- Search by website or advertiser —
nike.comsearches a website,Nikeresolves to matching advertisers automatically - Filter by region — 65+ countries supported
- Filter by platform — Search, YouTube, Play, Maps, Shopping
- Filter by format — text, image, video ads
- Date range filtering — custom date range or preset timeframes
- No browser needed — pure HTTP API calls with
undici, fast and lightweight
How It Works
The actor reverse-engineers Google's internal "anji" RPC API that powers the Transparency Center frontend. It:
- Establishes session cookies via a simple HTTP GET (no Playwright/browser required)
- Resolves an advertiser-name query to advertiser IDs via
SearchService/SearchSuggestions(skipped when the query is a domain) - Searches for creatives using
SearchService/SearchCreatives - Optionally fetches per-ad detail via
LookupService/GetCreativeById - Normalizes the proto-JSON response into clean JSON output
Search scopes
Google's Transparency Center supports exactly two scopes, and there is no browse-everything mode — a query is always required:
| Query | Scope | How it works |
|---|---|---|
nike.com | Website | Sent as a domain filter |
Nike | Advertiser | Resolved to advertiser IDs, ranked by exact match → Google's verified flag → ad volume |
With queryType: "auto" (the default), a domain-shaped query is tried as a website and
anything else as an advertiser name; if the first scope finds nothing, the other is tried
automatically.
Input
| Field | Type | Description | Default |
|---|---|---|---|
query | string | Required. Website (nike.com) or advertiser name (Nike) to look up ads for. | — |
queryType | select | How to read the query: auto, domain, or advertiser. | auto |
maxAdvertisers | integer | For advertiser-name queries, how many matching advertisers to pull ads from. | 10 |
region | select | Country to filter ads by. | anywhere |
platform | select | Platform filter: all, search, youtube, play, maps, shopping. | all |
creativeFormat | select | Ad format: all, text, image, video. | all |
dateStart | string | Start date in YYYY-MM-DD format (optional). | (empty) |
dateEnd | string | End date in YYYY-MM-DD format (optional). | (empty) |
timeframe | select | Preset date range (used when dateStart/dateEnd not set). | 365d |
limit | integer | Maximum number of ads to collect (up to 100 per page). | 20 |
scrapeAdDetails | boolean | Fetch full ad detail for each result (format, assets, dates). | true |
proxyConfiguration | object | Standard Apify proxy configuration. | { useApifyProxy: true } |
Output
Each ad in the dataset has this structure:
{"id": "CR14652493479645544449","advertiserId": "AR18378488041124659201","advertiserName": "Nike Retail BV","domain": "nike.com","adFormat": "image","firstShownDate": 1677628800,"lastShownDate": 1787567197,"totalDaysShown": 1256,"category": "Apparel & Accessories","categoryId": 166,"impressions": { "min": 3000000, "max": 3500000 },"platforms": [{ "platform": "search", "impressionsMin": 2500000, "impressionsMax": 3000000 },{ "platform": "shopping", "impressionsMin": 60000, "impressionsMax": 70000 }],"regions": [{"code": "CZ","regionId": 2203,"impressionsMin": 3000000,"impressionsMax": 3500000,"firstShown": "2023-03-01","lastShown": "2026-08-24","platforms": [{ "platform": "search", "impressionsMin": 2500000, "impressionsMax": 3000000 }]}],"assets": {"images": [{ "url": "https://tpc.googlesyndication.com/archive/simgad/104202098", "width": 380, "height": 503 }],"videos": [],"previews": [{"url": "https://displayads-formats.googleusercontent.com/ads/preview/content.js?...","width": null,"height": null}]},"detail": null}
assets is split by what each URL actually is:
images/videos— directly downloadable media filespreviews—content.jsad-preview endpoints. These are JavaScript, not media: load them in an iframe, don't fetch them as files.
scrapeAdDetails is on by default. The search response alone carries only a sparse
subset of a creative's assets; the detail endpoint returns roughly 2.5x as many
downloadable images. The cost is one extra request per ad, so a 20-ad run makes 21
requests instead of 1 — turn it off for fast, cheap listings, or when Google is rate
limiting you.
Reach data
category, impressions, platforms and regions come from the detail endpoint and
require scrapeAdDetails: true (the default). Google reports impressions as a range,
never an exact number, and omits the lower bound for low-volume regions — so min can be
null while max is set.
category is localized by Google to the IP the run executes from — the same ad returns
"Apparel & Accessories" from a US proxy and "לבוש ואביזרים" from an Israeli one. Key off
categoryId (stable numeric) if you need to group or filter reliably.
Not available: the detail response contains no landing-page URL, so there is no
landingPage field. For image/display creatives Google also returns no downloadable
image — only a previews embed — so assets.images is legitimately empty for many ads.
Example Inputs
Search for Tesla ads in the US:
{"query": "tesla.com","region": "US","limit": 50,"scrapeAdDetails": true}
Search by advertiser name rather than domain:
{"query": "Nike","queryType": "advertiser","maxAdvertisers": 1,"limit": 50}
All video ads a brand ran on YouTube:
{"query": "Coca-Cola","creativeFormat": "video","platform": "youtube","timeframe": "90d","limit": 20,"scrapeAdDetails": false}
Search with custom date range:
{"query": "amazon.com","region": "anywhere","dateStart": "2024-01-01","dateEnd": "2024-06-30","limit": 100}
Proxy and rate limiting
On the Apify platform, the actor uses Apify Proxy automatically. Configure
proxyConfiguration to use residential proxies or custom proxy URLs.
Google rate limits the Transparency Center per IP and answers with HTTP 429. The actor
retries with exponential backoff and fails loudly if the limit does not clear — it
will not report a throttled run as "no ads found". If you hit 429s repeatedly, switch
proxyConfiguration to residential proxy groups.