Google Ads Transparency Center Scraper: Ads by Advertiser
Pricing
from $0.60 / 1,000 ads
Google Ads Transparency Center Scraper: Ads by Advertiser
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
Alexis Morain
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
3
Monthly active users
4 days ago
Last modified
Categories
Features
Share
Google Ads Transparency Scraper
This Actor turns the Google Ads Transparency Center into structured data. Give it website domains, advertiser IDs, advertiser names or Transparency Center URLs, and it returns every ad Google lists for them: the verified advertiser, the format (text, image, video), the first and last shown dates, the 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, down to $0.60 per 1,000 ads on the Gold plan; $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.
If you were looking for a Google Ads Transparency Center API, this is the closest thing that exists. Google does not publish one. This Actor is a domain or an advertiser in, JSON out.
What this Google ads scraper does
It searches in four 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, or raise Advertisers per name to take several at once. A name that looks like a domain (temu.com) is searched as a domain.
By Transparency Center URL. Paste an advertiser page, a domain search (?domain=nike.com®ion=US), or a single ad page (/advertiser/AR.../creative/CR...). The region in the URL is kept for that URL. A single ad URL returns that ad with its details.
On top of any search you get filters (country, dates, ad format, platform), an optional details lookup per ad, a Check mode that answers "does this company advertise on Google" in one line per domain, a New ads only mode for scheduled monitoring, and an optional webhook at the end of the run.
Check mode: does this company advertise on Google?
Switch Mode to Check and the Actor returns one line per domain or advertiser (and per country) 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 ($0.001 on Gold), whether the company has 10 ads or 100,000, so a list of 1,000 domains costs about $2.
{"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"}
Typical uses: filter a prospect list down to companies that spend on Google Ads, rank accounts by ad volume before an audit, or check weekly whether a competitor has stopped advertising (latestAdLastShown going stale).
Why scrape the Google Ads Transparency Center?
- Scrape competitor ads. What a competitor runs on Google Search, YouTube, Shopping, Play and Maps, in which formats, since when.
- Find who advertises on Google, for lead generation. Check mode qualifies a list of domains by whether they pay for Google ads and how many ads they have.
- Ad creative research. Pull the image, video and Search ad previews of a market for a swipe file.
- Agency pitches and audits. Show a prospect their own ads and their competitors' in the first meeting.
- Brand protection. Search for your brand name or domain and see which advertiser accounts, including resellers and lookalikes, run ads pointing to you.
- European ad transparency research. For ads served in the EU, details include impressions ranges per country and per platform, published under the Digital Services Act.
- Alerts. Schedule the Actor daily in New ads only mode and get a webhook when a competitor launches something.
How to scrape Google ads
From the Apify console
- Open the Actor and type one or more domains in Website domains, for example
nike.com. - Optional: pick countries, a date window, ad formats or platforms.
- Set Max ads per target (default 100), or 0 for everything.
- Press Start, then download the results as JSON, CSV, Excel or HTML, or read them through the API.
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}'
Full Python, JavaScript and cURL examples are further down, in "Using the Google Ads Transparency API from your code".
Which fields should I fill?
| You want | Fill | Notes |
|---|---|---|
| All the ads pointing to a website | domains | nike.com or a full URL, only the domain is kept. |
| The ads of one exact advertiser account | advertiserIds | AR... IDs, or the advertiser page URL. |
| The ads of a company when you only know its name | searchTerms | Matched to the verified advertiser with the most ads. |
| Reproduce a search from the website | startUrls | Advertiser page, domain search or single ad URL. |
| Ads shown in one or several countries | countries | Codes like US, GB, FR, or English names. |
| Ads shown in a period | startDate, endDate | Shown inside the window. |
| Only Search ads, only videos... | adFormats | TEXT, IMAGE, VIDEO. |
| Only YouTube, only Shopping... | platforms | GOOGLE_SEARCH, YOUTUBE, GOOGLE_SHOPPING, GOOGLE_PLAY, GOOGLE_MAPS. |
| Variants, served countries, EU impressions | includeDetails | One extra lookup per ad, priced as a detailed ad. |
| Whether 1,000 companies advertise | mode = check | One line per domain, no ads. |
| A daily competitor alert | mode = new-only and webhookUrl | See the monitoring section. |
Input examples
Every ad pointing to a domain, in the United States, capped at 500:
{"domains": ["nike.com"],"countries": ["US"],"maxAdsPerTarget": 500}
Image ads shown on Google Shopping for a French retailer:
{"domains": ["decathlon.fr"],"countries": ["FR"],"adFormats": ["IMAGE"],"platforms": ["GOOGLE_SHOPPING"],"maxAdsPerTarget": 500}
One advertiser account, ads shown in 2026, with details:
{"advertiserIds": ["AR16735076323512287233"],"startDate": "2026-01-01","includeDetails": true,"maxAdsPerTarget": 100}
A prospect list qualified in check mode:
{"domains": ["puma.com", "adidas.com", "newbalance.com", "asics.com"],"mode": "check"}
A daily competitor watch:
{"domains": ["zalando.de", "aboutyou.de"],"countries": ["DE"],"mode": "new-only","maxAdsPerTarget": 0,"webhookUrl": "https://hooks.slack.com/services/..."}
Filters
countries: two-letter codes (US,GB,FR) or names in English. Each country is searched on its own, because Google ignores a second country in the same filter, and an ad found in several comes out once, tagged with the first country. Leave empty for all countries.startDate/endDate: only ads shown inside the window.adFormats:TEXT,IMAGE,VIDEO. Text ads are Google Search ads.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.
What data can it extract? Every output field
One item per ad. A field Google does not publish for an ad is null.
Every ad
| Field | Type | Description |
|---|---|---|
adUrl | string | Public page of the ad in the Transparency Center |
creativeId | string | Google ID of the ad (CR...) |
advertiserId | string | Google verified advertiser ID (AR...) |
advertiserName | string | Verified advertiser name as published by Google |
format | string | TEXT, IMAGE or VIDEO |
firstShown | string | When Google first showed the ad, UTC |
lastShown | string | When Google last showed the ad, UTC |
daysShown | integer | Number of days Google reports the ad as shown |
domain | string | Domain the ad points to (searches by domain only) |
previewImageUrl | string | Image of the ad. For text ads, a picture of the Search ad with its headline and description |
previewUrl | string | Google's HTML preview of the ad (a script that renders it), for image, video and Shopping ads |
input | string | The domain, advertiser ID, name or URL this item came from |
inputType | string | domain, advertiser, searchTerm or url |
country | string | Country searched (two-letter code), null for all countries |
hasDetails | boolean | true when the details lookup was made for this ad |
scrapedAt | string | When the item was collected, UTC |
With Include details
| Field | Type | Description |
|---|---|---|
variantCount | integer | Number of variants of the ad |
variants | array | Each variant with previewUrl and previewImageUrl |
servedCountries | array | Each country where the ad ran: code, name, last shown date; in the EU also first shown date and impressions per platform |
impressionsMin | integer | EU only: lower bound of Google's impressions range, all EU countries |
impressionsMax | integer | EU only: upper bound of the range, null when open-ended (10M+) |
platforms | array | EU only: impressions range per platform (GOOGLE_SEARCH, YOUTUBE, GOOGLE_SHOPPING, GOOGLE_PLAY, GOOGLE_MAPS) |
productCategory | string | EU only: category of a Shopping ad, for example Apparel & Accessories |
In Check mode
| Field | Type | Description |
|---|---|---|
hasAds | boolean | true when Google lists at least one ad |
adCountMin, adCountMax | integer | Google's range for the ad count (Google gives a range, not an exact number) |
latestAdLastShown | string | Last shown date of the most recently shown ad |
latestAdvertiserId | string | Advertiser of the most recently shown ad |
latestAdvertiserName | string | Name of that advertiser |
latestAdUrl | string | Transparency Center page of that ad |
transparencyUrl | string | Transparency Center page of the domain or advertiser |
The Output tab has three ready views: Ads, Ads with details and Check mode.
Example output
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}
You can download the dataset in JSON, CSV, Excel, XML or HTML.
Monitor competitor Google ads: New ads only mode
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.
By default the registry is tied to the exact targets, countries and filters, so changing any of them starts a fresh one. Set your own Registry key to keep one registry while you edit the list.
Webhook at the end of the run
Add a webhookUrl and you get a POST with a small JSON summary only when there is something to report, meaning at least one item was returned:
{"actor": "google-ads-transparency-scraper","runId": "<run id>","mode": "new-only","items": 4,"searches": 2}
Slack and Discord incoming webhooks work as they are. The URL is stored encrypted and never logged. Use the final URL: a redirect is not followed, except 307 and 308, which get the same POST once. An unreachable webhook is logged as a warning and never fails the run.
Using the Google Ads Transparency API from your code
Every run is an API call. Your token is in the Apify console under Settings, Integrations.
Python
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"])
Check a list of domains and keep those that advertise:
run = client.actor("alexmorain/google-ads-transparency-scraper").call(run_input={"domains": ["puma.com", "adidas.com", "example.org"],"mode": "check",})advertisers = [row["input"]for row in client.dataset(run["defaultDatasetId"]).iterate_items()if row["hasAds"]]
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_TOKEN>' });const run = await client.actor('alexmorain/google-ads-transparency-scraper').call({domains: ['nike.com'],countries: ['US'],includeDetails: true,maxAdsPerTarget: 50,});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const ad of items) console.log(ad.advertiserName, ad.format, ad.variantCount);
cURL
Run and wait for the items in one call:
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}'
For runs that take more than a few minutes, start the run and poll it, since the synchronous endpoint times out after 300 seconds:
curl -X POST "https://api.apify.com/v2/acts/alexmorain~google-ads-transparency-scraper/runs?token=<YOUR_TOKEN>&maxTotalChargeUsd=5" \-H "Content-Type: application/json" \-d '{"domains": ["nike.com"], "maxAdsPerTarget": 0}'
Then read https://api.apify.com/v2/datasets/<defaultDatasetId>/items?format=csv when the run has finished. maxTotalChargeUsd is a hard ceiling: the Actor stops cleanly when it is reached and you are never charged beyond it.
What people use it for
Competitor ad analysis on Google
List the domains of your competitors, set the country you sell in, and run once. Sort by daysShown: long-running ads are the ones the advertiser kept paying for. Group by format and by advertiserName to see which accounts carry the budget. Add platforms to see where the money goes: Search, YouTube, Shopping.
Qualifying a prospect list
Run Check mode over the domains of a list and keep the rows with hasAds: true. The ad count range (adCountMin, adCountMax) and latestAdLastShown tell you how big and how current the spend is. A company with 30,000 to 40,000 ads whose latest ad was shown yesterday is an active Google advertiser.
Brand protection and reseller monitoring
Search your own domain. Ads pointing to your website from advertiser accounts that are not yours show who resells or promotes your products on Google. Add the New ads only mode and a webhook to hear about a new account the day its first ad appears.
European impressions research
For ads served in the EU, Include details returns the impressions range of the ad and per platform, plus first and last shown dates per country. That is the only public volume signal Google gives for ads, and it exists in the EU only.
Creative research
Filter by format and platform and export previewImageUrl. For text ads, the preview is a picture of the Search ad itself.
Finding a competitor entering a market
Run the same domain with countries set to a market you do not expect it in. Ads in that country with a recent firstShown are the signal.
Google Ads Transparency scraper pricing
Pay per event, in US dollars, with no monthly fee. Platform usage (compute, proxies) is included. The price goes down with your Apify subscription plan, which is why the Store shows "from $0.60 / 1,000 ads".
| Event | When it fires | Free | Bronze | Silver | Gold and above |
|---|---|---|---|---|---|
| Ad | Per ad pushed to the dataset | $0.0012 | $0.0010 | $0.0008 | $0.0006 |
| Detailed ad | Per ad with its details lookup, instead of Ad, not on top | $0.0020 | $0.0017 | $0.0014 | $0.0010 |
| Advertiser lookup | Per line in Check mode | $0.0020 | $0.0017 | $0.0014 | $0.0010 |
| Actor start | Once when the run starts, per GB of memory (the default is 1 GB, so one event) | $0.002 | $0.002 | $0.002 | $0.002 |
Per 1,000 ads, that is $1.20 on the Free plan, $1.00 on Bronze, $0.80 on Silver and $0.60 from Gold. With details: $2.00, $1.70, $1.40 and $1.00.
Worked examples at Free plan prices:
- The default run, 100 ads from one domain: 100 x $0.0012 + $0.002 = $0.122.
- 1,000 ads with details: 1,000 x $0.002 + $0.002 = $2.00.
- 20,000 ads across 20 domains, no details: 20,000 x $0.0012 + $0.002 = $24.00, or $12.00 on Gold.
- 1,000 domains in Check mode: 1,000 x $0.002 + $0.002 = $2.00.
- A daily watch of five competitors in New ads only mode: $0.002 on a quiet day, plus $0.0012 for each new ad.
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.
How this compares to other Google ads scrapers
Prices as listed on the Apify Store on 21 October 2026. Check each page for its current terms.
| Actor | Price per 1,000 ads |
|---|---|
| This Actor | $1.20 on Free, $0.60 on Gold |
| silva95gustavo/google-ads-scraper | $1.90 |
| solidcode/ads-transparency-scraper | about $1.50 |
At the entry price this Actor is about a third cheaper than the first and a fifth cheaper than the second. On Gold it is less than half. Check mode is priced per domain, so qualifying a list of companies costs $2 per 1,000 domains instead of the cost of reading their ads.
Why this Google ads scraper
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. A search cut short by an empty page from Google is reported as such in the status message.
One ad, one charge
An ad found by two searches in the same run comes out once. Ads skipped by a format filter or by New ads only mode are never charged.
Limits and what this scraper does not do
- Ad counts are ranges. Google gives the ad count of a domain or an 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. Impressions are ranges.
- Speed. 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. The default timeout is one hour.
- Details cost an extra lookup per ad and are priced as a detailed ad.
GOOGLE_MAPSis the platform code Google uses for Maps placements as far as we could verify: those ads are text ads in small numbers.- Scope. The Actor reads the public Transparency Center and nothing else. It does not touch Google accounts, Google Ads campaigns, keywords, bids or budgets: Google does not publish those.
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 do I scrape the Google Ads Transparency Center?
Type a domain in Website domains and press Start. For one exact advertiser, use its AR... ID. For a name, use Advertiser names.
How do I see a competitor's Google ads?
Search their domain. Every ad pointing to it comes back, with the advertiser account that runs it, the format, and when it was first and last shown. Add Include details for the countries where each ad ran.
Can I find out whether a company advertises on Google?
Yes, with Check mode: one request per domain tells you whether Google lists any ad, in what range, and when the latest was shown.
Can I see Google Ads keywords, bids or budgets?
No. The Transparency Center does not publish them, and neither does this Actor. For EU ads, details give impressions ranges.
Can I see the text of Google Search ads?
Not as a field. Google shows Search ads in the Transparency Center as an image, and the Actor returns the link to that image in previewImageUrl.
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.
Which countries are supported?
Use two-letter codes (US, GB, FR) or English country names, one search per country. Leave the field empty for all countries.
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.
Can I run it every day and be told about new ads?
Yes. Use Mode New ads only on a daily schedule, with a Webhook URL. See the monitoring section.
Is it legal to scrape the Google Ads Transparency Center?
Our Actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our Actors, when used for ethical purposes by Apify users, are safe. However, you should be aware that your results could contain personal data. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.
Integrations, exports and agents
Runs can be scheduled from the Apify console, hourly through monthly, which is all a standing competitive watch needs. Combine a schedule with New ads only and a webhook and you get a call only when new ads appear. For every run, whatever its result, attach an Apify webhook on the ACTOR.RUN.SUCCEEDED event: Apify POSTs the run and dataset IDs to your endpoint, so a pipeline can pull the ads into your own store without polling.
The dataset is readable over the Apify API in JSON, CSV, XML, Excel, RSS and HTML. Apify's integrations push it to Google Sheets, Slack, Airtable, Zapier, Make and the usual storage targets without code. The Actor is also callable from an agent: anything that speaks the Apify API can start a run and read the dataset, and the Apify MCP server exposes Actors as tools to MCP-capable clients.
Support
Something wrong or missing? Open an issue in the Issues tab and it gets fixed; a reproducible input gets a fix faster than a description. If the Actor saved you time, a short review helps others find it.
More ad libraries from the same author: LinkedIn Ad Library Scraper and Facebook Ads Library Scraper.