Google Ads Transparency Scraper | from $0.60/1K Ads
Pricing
from $0.60 / 1,000 ads
Google Ads Transparency Scraper | from $0.60/1K Ads
Scrape the Google Ads Transparency Center by domain, advertiser ID or name: every ad with format, first and last shown dates, preview, and for EU-served ads impressions per country and platform. Plain HTTP, residential proxies, check 1,000 domains in one run.
Pricing
from $0.60 / 1,000 ads
Rating
0.0
(0)
Developer
Alex Morain
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Google Ads Transparency Scraper
This Actor turns the Google Ads Transparency Center into structured data. Give it website domains, advertiser IDs or advertiser names, and it returns every ad Google lists for them: verified advertiser, format (text, image, video), first and last shown dates, number of days shown, and a preview. With details on, each ad also comes with its variants, the countries where it ran, and for ads served in the European Union the impressions per country and per platform (Search, YouTube, Shopping, Play, Maps).
It runs over plain HTTP against the same endpoints the Transparency Center website calls. No browser, no login, no cookies. A run of 20,000 ads across 20 domains takes about a minute. Pricing is pay per event: $1.20 per 1,000 ads at the entry price, from $0.60 / 1,000 ads on Gold; $2.00 per 1,000 ads with details ($1.00 on Gold); $2.00 per 1,000 domains in check mode ($1.00 on Gold); and $0.002 per run.
Google does not publish an API for the Ads Transparency Center. This Actor is the closest thing to one: a domain or an advertiser in, JSON out.
What this Google ads scraper does
It searches in three ways, and they can be combined in one run.
By website domain. nike.com returns every ad pointing to that domain, across every
advertiser account that runs them. Big brands often advertise through several verified
accounts (a retail entity per country, agencies, resellers): a domain search catches them
all, and each ad carries the advertiserName so you can tell them apart.
By advertiser ID. AR16735076323512287233 (or its Transparency Center URL) returns the ads
of that one verified account and nothing else.
By advertiser name. Supercell is matched to the verified advertiser with the most ads
whose name contains it. The log lists the other matches with their IDs, so you can pin the
right one in Advertiser IDs on the next run.
You can also paste Transparency Center URLs: an advertiser page, a domain search, or a
single ad page (/advertiser/AR…/creative/CR…), which returns that ad with its details.
Check mode: does this company advertise on Google?
Switch Mode to Check and the Actor returns one line per domain or advertiser instead of its ads, from a single request each: does it advertise on Google, Google's range for its ad count, when its most recent ad was last shown, and which advertiser account ran it.
That is the cheap way to qualify a long list of companies. 100 domains took 18 seconds in our tests. You pay $0.002 per line on the Free plan, whether the company has 10 ads or 100,000.
{"input": "puma.com","inputType": "domain","country": null,"hasAds": true,"adCountMin": 30000,"adCountMax": 40000,"latestAdLastShown": "2026-10-16T14:52:07Z","latestAdvertiserId": "AR11620109060996595713","latestAdvertiserName": "PUMA SPORTS PHILIPPINES INC.","latestAdUrl": "https://adstransparency.google.com/advertiser/AR11620109060996595713/creative/CR15288039521514422273?region=anywhere","transparencyUrl": "https://adstransparency.google.com/?region=anywhere&domain=puma.com","scrapedAt": "2026-10-16T15:14:22Z"}
How to use it
From the console: type one or more domains in Website domains, press Start. Everything else can stay as it is for a first run.
From the API:
curl -X POST "https://api.apify.com/v2/acts/alexmorain~google-ads-transparency-scraper/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-H "Content-Type: application/json" \-d '{"domains": ["nike.com"], "countries": ["US"], "maxAdsPerTarget": 200}'
from apify_client import ApifyClientclient = ApifyClient("<YOUR_TOKEN>")run = client.actor("alexmorain/google-ads-transparency-scraper").call(run_input={"domains": ["decathlon.fr"],"countries": ["FR"],"adFormats": ["IMAGE"],"platforms": ["GOOGLE_SHOPPING"],"maxAdsPerTarget": 500,})for ad in client.dataset(run["defaultDatasetId"]).iterate_items():print(ad["advertiserName"], ad["format"], ad["lastShown"], ad["adUrl"])
Filters
countries: two-letter codes (US,GB,FR) or names. Each country is searched on its own and an ad found in several comes out once, tagged with the first country.startDate/endDate: only ads shown inside the window.adFormats:TEXT,IMAGE,VIDEO.platforms:GOOGLE_SEARCH,YOUTUBE,GOOGLE_SHOPPING,GOOGLE_PLAY,GOOGLE_MAPS.maxAdsPerTarget: cap per domain, advertiser or name (per country when you list several). Default 100,0for no cap. Google lists the most recently shown ads first, so a cap keeps the freshest ones.
Filters are applied by Google itself, so a filtered run reads only what it returns. The one exception is asking for exactly two formats, which Google cannot do in one search: the third format is then skipped after reading, and never charged.
Only new ads, for scheduled monitoring
Set Mode to New ads only and schedule the Actor daily. It keeps a registry of every ad it returned before (a named key-value store in your account) and returns only ads it has never returned. Skipped ads are not charged.
Once a run has read a search to its end, later runs stop that search as soon as they reach ads last shown before that run (with three days of margin for Google's indexing delay). A quiet day costs little more than the start fee. In our test, a second run on a 700-ad search returned nothing new and stopped after 7 requests.
Add a webhookUrl and you get a POST with a small JSON summary only when there is something
new: actor, runId, mode, items, searches. The URL is stored encrypted and never
logged.
Output fields
Every ad:
| Field | What it holds |
|---|---|
adUrl | The ad's page in the Transparency Center |
advertiserId, advertiserName | Verified advertiser account |
creativeId | Google's ID for the ad |
format | TEXT, IMAGE or VIDEO |
firstShown, lastShown | First and last time Google showed the ad, UTC |
daysShown | Number of days Google reports the ad as shown |
domain | Domain the ad points to (domain searches) |
previewImageUrl | Image of the ad. For text ads, a picture of the Search ad itself |
previewUrl | Google's HTML preview for image, video and Shopping ads |
input, inputType, country | Which search produced the item |
With Include details:
| Field | What it holds |
|---|---|
variantCount, variants | Every variant Google keeps for the ad, with previews |
servedCountries | Each country where the ad ran: code, name, last shown date; in the EU also first shown date and impressions per platform |
impressionsMin, impressionsMax | EU only: Google's impressions range, all EU countries. impressionsMax is null when open-ended (10M+) |
platforms | EU only: impressions range on Search, YouTube, Shopping, Play, Maps |
productCategory | EU only: category of a Shopping ad |
Example, a text ad with details:
{"adUrl": "https://adstransparency.google.com/advertiser/AR15589870916631265281/creative/CR03027411911672070145?region=DE","advertiserId": "AR15589870916631265281","advertiserName": "Zalando SE","creativeId": "CR03027411911672070145","format": "TEXT","firstShown": "2024-02-08T10:41:13Z","lastShown": "2026-10-16T14:50:15Z","daysShown": 710,"domain": "zalando.de","previewUrl": null,"previewImageUrl": "https://tpc.googlesyndication.com/archive/simgad/1109224665132657429","input": "zalando.de","inputType": "domain","country": "DE","hasDetails": true,"variantCount": 3,"impressionsMin": 10000,"impressionsMax": 15000,"platforms": [{"platform": "GOOGLE_SEARCH", "impressionsMin": 10000, "impressionsMax": 15000},{"platform": "GOOGLE_SHOPPING", "impressionsMin": 0, "impressionsMax": 1000},{"platform": "YOUTUBE", "impressionsMin": 0, "impressionsMax": 1000}],"servedCountries": [{"countryCode": "DE", "countryName": "Germany", "geoId": 2276, "firstShown": "2024-02-08","lastShown": "2026-10-16", "impressionsMin": 10000, "impressionsMax": 15000, "platforms": ["…"]}],"productCategory": null}
Why this one
It does not get stuck on Google's rate limit. Google lets one IP make about a hundred requests to the Transparency Center, then answers with a captcha for a quarter of an hour or more. We measured it from Apify's own servers: a single IP is cut off after 80 to 100 requests, and a shared datacenter pool of 27 IPs was exhausted after 1,700 requests. This Actor spreads its requests over many residential IPs, changes IP at the first refusal, and retires each IP before Google flags it. In our tests, 99.5% of requests went through on the first try, and every refused one went through on a fresh IP.
It reads Google's data, not a rendering of it. No browser, which is why it is fast and why it fits in 1 GB. The first and last shown dates are Google's own timestamps, not the day the Actor happened to see the ad.
It tells you what happened. Each search logs the total Google announces for it, the status message says how many items came back and why a search stopped, and a run that returns nothing because every search failed ends as FAILED, with the reason, rather than as an empty success.
Pricing
| Event | Free | Bronze | Silver | Gold and above |
|---|---|---|---|---|
| Ad | $0.0012 | $0.0010 | $0.0008 | $0.0006 |
| Detailed ad (instead of Ad, not on top) | $0.0020 | $0.0017 | $0.0014 | $0.0010 |
| Advertiser lookup (check mode) | $0.0020 | $0.0017 | $0.0014 | $0.0010 |
| Actor start | $0.002 |
The run log opens with the maximum cost of the run at Free plan prices. Set a maximum charge on the run and the Actor stops cleanly when it is reached: you are never charged beyond it.
Limits
- Google gives the ad count of a domain or advertiser as a range (
90000–100000), not an exact number. So does this Actor. - The text of text ads is in their preview image, not in a field: Google renders Search ads as images in the Transparency Center. Headlines and descriptions are not extracted.
- Video ads come with Google's HTML preview, not a YouTube video ID.
- Impressions, first shown date per country and product category exist only for ads served in the European Union (Digital Services Act data). Outside the EU, Google publishes the countries and the last shown date per country only.
- One domain is read at about 3,000 ads a minute, since Google hands out pages one after another. Several domains run in parallel. A brand with 100,000 ads needs a run timeout of about 40 minutes, or a country or date filter.
GOOGLE_MAPSis the platform code Google uses for Maps placements as far as we could verify: those ads are text ads in small numbers.
FAQ
Is there a Google Ads Transparency Center API?
Not a public one. The Transparency Center website calls internal endpoints that return JSON; this Actor calls the same ones and hands you a clean dataset.
How much does it cost to scrape 1,000 Google ads?
$1.20 on the Free plan, $0.60 on Gold, plus $0.002 per run. With details, $2.00 and $1.00.
Why does a domain return ads from several advertisers?
Because Google files ads by verified advertiser account, and one website is often advertised by several accounts. Use Advertiser IDs to keep a single one.
A domain returns zero ads. What now?
Check mode tells you in one request whether Google lists any ad for it. If it says no, the domain does not advertise on Google, or not under that exact domain: try the domain without a subdomain, or the advertiser name.
How do I export the ads to CSV or Excel?
From the run's Storage tab, or through the dataset API with format=csv or format=xlsx.
Support
Something wrong or missing? Open an issue on the Actor page and it gets fixed. If the Actor saved you time, a short review helps others find it.