Google Ads Transparency Center & Competitor Ad Scraper
Every ad an advertiser is running, from Google's Ads Transparency Center — with first and last shown dates, the creative image and the rich-media preview URL.
Verification
Output fields
Authoritative field set from the dataset schema.
| Field | Type |
|---|---|
advertiser_id | string|null |
advertiser_name | string|null |
advertiser_domain | string|null |
creative_id | string|null |
format_code | integer|null |
creative_type | string|null |
creative_image_url | string|null |
creative_preview_url | string|null |
display_width | integer|null |
display_height | integer|null |
first_shown | string|null |
last_shown | string|null |
days_running | integer|null |
region | string|null |
advertiser_creatives_low | integer|null |
advertiser_creatives_high | integer|null |
matched_by | string|null |
advertiser_url | string|null |
notice | string|null |
notice_type | string|null |
source_url | string|null |
scraped_at | string|null |
Sample row
{
"source_url": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR10365997061744099329?region=US",
"advertiser_id": "AR16735076323512287233",
"advertiser_name": "Nike, Inc.",
"advertiser_domain": "nike.com",
"creative_id": "CR10365997061744099329",
"format_code": 1,
"creative_type": "image",
"creative_image_url": "https://tpc.googlesyndication.com/archive/simgad/2588413232821661199",
"creative_preview_url": null,
"display_width": 348,
"display_height": 180,
"first_shown": "2023-11-16T22:59:37Z",
"last_shown": "2026-09-07T05:25:23Z",
"days_running": 1025,
"region": "US",
"advertiser_creatives_low": 8000,
"advertiser_creatives_high": 9000,
"matched_by": "domain",
"advertiser_url": "https://adstransparency.google.com/advertiser/AR16735076323512287233?region=US"
} Inputs
| Field | Type | Req | Default | Description |
|---|---|---|---|---|
query | string | no | "nike.com" | An advertiser domain (nike.com), a Google advertiser id (AR16735076323512287233), or a company name to search for. Which of the three you gave is recorded on every row in 'matched_by'. Kept forever alongside 'Advertisers' — saved tasks and API callers send it. |
queries | array | no | ["nike.com","geico.com"] | Look up many advertisers in ONE run instead of starting a run per advertiser. Takes the same values as 'Advertiser'. Combined with it if you fill both, and duplicates are removed. The result cap applies PER advertiser, so one large advertiser cannot use up the run and leave the others looking like they run no ads. |
region | string | no | "US" | The country whose ad library to read, as an ISO country code — US, GB, DE, FR, JP, BR and so on. This is not cosmetic: Google keeps a separate library per country and the same advertiser has very different volumes in each. An unrecognised code is refused up front, because Google answers one with an empty list rather than an error, which would read as 'this advertiser runs no ads here'. |
maxResults | integer | no | 200 | Cap on creatives returned PER advertiser, not per run. Large advertisers run enormous libraries — Google stated 8,000-9,000 creatives for one of them in the US alone on 2026-09-07 — so this is your spend control. Every row carries Google's own stated range for that advertiser and region, so a cap can never read as completeness. |
proxyConfiguration | object | no | {"useApifyProxy":true} | ON by default, and it should stay on. Google throttles the Transparency Center per IP and answers a spent one with a redirect to its /sorry/ page rather than an error — measured from an ordinary connection during development. A shared cloud IP is often already spent, so running without a proxy is the most likely reason for a run that returns nothing. |
Pricing
Pay per result (creative) — no charge for empty runs.
Example: 1000 ad creatives at $0.0015/result ≈ $1.50.
FAQ
Does this give me impressions, spend or reach?
No, and neither can anything else reading this source: Google publishes no impression count, no spend figure and no audience reach anywhere in the Ads Transparency Center for a normal commercial ad. What it does publish is which creatives ran, in which country, and the dates each was first and last shown — and the gap between those two dates is the most useful signal available here, because an advertiser who keeps a creative live for months is telling you it works. The creative row does carry one undocumented integer that this Actor deliberately does not return; it is between 5 and 1,737 across the ads sampled, it matches neither the image area nor its dimensions, and shipping it labelled 'impressions' would be inventing a number.
Why is the proxy on by default when other Actors here have it off?
Because Google throttles this endpoint per IP, and it does so invisibly. A spent IP does not get an error or a 429 — the request is redirected to google.com/sorry/, so a scraper that only checks the response body sees a perfectly valid page and reports an empty result. That happened during development from an ordinary connection and persisted for several minutes. Shared cloud IPs are frequently already spent by someone else, so an unproxied run is the likeliest reason for a run that comes back with nothing. This Actor also checks where each response landed rather than only what it contains, so when it is throttled it says so in a free row instead of pretending the advertiser has no ads.
Why does a row say 8,000 to 9,000 instead of a number?
Because that is what Google says. It publishes an advertiser's library size as a bucketed range and never as an exact count, so both bounds are carried on every row rather than one of them being presented as a total. It is the only honest way to answer 'did I get all of them?': compare your row count against the range. It also varies enormously by country — on 2026-09-07 the same advertiser was stated at 8,000-9,000 creatives in the US, 20,000-30,000 in Germany and 400-500 in Japan.
Which countries can I search?
48 were verified one by one against the live service on 2026-09-07 and every one returned creatives: the US, Canada, Mexico, Brazil, Argentina, Chile, Colombia, the UK, Ireland, Germany, France, Italy, Spain, Portugal, the Netherlands, Belgium, Switzerland, Austria, Sweden, Norway, Denmark, Finland, Poland, Czechia, Greece, Hungary, Romania, Ukraine, Turkey, Israel, the UAE, Saudi Arabia, Egypt, South Africa, Nigeria, India, Japan, South Korea, Singapore, Malaysia, Thailand, Indonesia, the Philippines, Vietnam, Taiwan, Hong Kong, Australia and New Zealand. Give a standard two-letter country code. Anything unrecognised is refused with a free row naming the valid ones, rather than being sent to Google and coming back as a misleading empty list.
Can I search by company name instead of by domain?
Yes. A value that is not a domain and not an advertiser id is put through Google's own advertiser search, and the best match is used — the row then says matched_by: name_search so you know a resolution step happened. Names are ambiguous, though: searching 'Nike' returns NIKE SRL in Italy and several unrelated advertisers alongside Nike, Inc., and the run log lists how many candidates were considered. Where you know the domain or the advertiser id, use it — those are exact.
Why can't I fetch the creative image with curl?
Google serves those images to browsers and refuses plain command-line clients — a request with default headers hangs rather than returning an error. The URL is real and is taken verbatim from Google's own response, not assembled by this Actor; one checked on 2026-09-07 rendered as a 696×458 image in a browser. Use browser-style headers if you are downloading them programmatically, or just open one in a tab. Note also that display_width and display_height are the size the ad is shown at, not the asset's own resolution — that same creative is served as 348×489 in the ad slot.
What happens if Google changes the RPC?
You get a free, unbilled row with notice_type 'source_changed'. This matters more here than for a normal scraper: the endpoint identifies its fields by NUMBER rather than by name, so if Google renumbers them the response is still valid JSON of the right shape and every value silently lands in the wrong column. The Actor checks that the rows it got still carry a creative id where one belongs, and stops rather than emitting a dataset that looks fine and is wrong.
How many ads can one run return?
As many as the advertiser has, in pages of 40, with the cap applied per advertiser rather than per run — so a batch of ten cannot be used up by the first large one. Libraries get big: Google stated 8,000-9,000 creatives for a single advertiser in the US alone. Set the cap to control spend, and read it against the advertiser_creatives range on the rows to see what fraction you covered.
Is this the same data as the Transparency Center website?
Yes — it is the same service, read through the same internal endpoint the website's own front end calls, so what you get is what the site would show for that advertiser and country. Nothing here is inferred, modelled or enriched from anywhere else, and the source page for every single row is on the row so you can open it and check.
Do I need a Google account or an Ads account?
No. The Transparency Center is public and this Actor sends no credentials of any kind. It reads only what Google publishes about ads that ran; there is no account data, no audience data and no personal information involved.
Guides & use cases
Related actors