Competitor Ads Spy - Google Ads Transparency Center, Creatives
Pricing
$1.45 / 1,000 ad creatives
Competitor Ads Spy - Google Ads Transparency Center, Creatives
19,782 ads for one advertiser in one region in 31.5 seconds, 244 regions, 63 columns where the most used rivals show 13. Google Ads library scraper for competitor ad creatives: format, surface and policy codes translated, removed ads with the policy that removed them.
Pricing
$1.45 / 1,000 ad creatives
Rating
0.0
(0)
Developer
Snow Leo Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
Google Ads Transparency Center Scraper - competitor ad library, ad creatives, advertiser accounts
Scrape the Google Ads Transparency Center without a login, an API key, a proxy or a browser. Point the actor at a brand name, a landing page domain, an advertiser ID or a link you copied from the report, and get back the ad creatives Google publishes for that advertiser: text, image and video ads, the first and last day each one ran, how many days it has been running, the image URL, the Google surface it was shown on, the countries it reached, the targeting categories the advertiser used, and the legal entity behind the account.
This is competitor ad intelligence and creative research: see what ads your competitors run on Google Search, YouTube, Shopping, Maps and Play, which creatives they keep alive for months, which they killed after a day, and which markets they push in. It is also an ad library for compliance work: the actor can return the political advertiser register and the ads Google removed for policy violations, with the policy that was broken and whether a human or an automated system made the decision.
What you get in one run
- Ad creatives - id, advertiser, domain, format, first shown, last shown, days shown, image and preview URLs, and a link straight back to the ad in Google's own report.
- Advertiser accounts - one brand runs many of them. The measured example
is in this README: the word
nikeresolves to 9 advertiser accounts in the report, and the biggest of them holds between 9,000 and 10,000 ads while the smallest holds one. - Removed ads - creatives Google took down, with the policy category, the enforcement means (automated or human) and the decision type (a notice or Google's own investigation).
- Per-country reach - impression ranges and first/last served dates per country, plus the separate EEA and US breakdowns Google publishes.
- Monitor mode - a named memory of everything already delivered, so a daily watch pays for the new creatives only.
Why this one and not a naive scraper
Everything below was measured, and the commands that measure it ship in
tools/measure.py. The numbers live in tools/measurements.json.
The report lies by silence, and the page size is the cheapest trap. Ask for 100 ads per request and you get 100. Ask for 101, 120, 150 or 200 and you get an empty list and HTTP 200 - not an error, not a warning. A scraper that raises its page size to go faster reads that as "this advertiser has no ads". This actor requests exactly 100 and pages with the report's own cursor.
Region is not cosmetic, and it is not a country code. The report is
region-scoped, and the same domain has a different library in every market. For
nike.com the report's own totals are 100,000-200,000 ads worldwide,
8,000-9,000 in the United States, 10,000-20,000 in France and
400-500 in Japan. The region has to travel inside the query as a numeric
Google geo criterion id and as a list; the two-letter code is refused and the
region field in the request context is accepted and then ignored. This actor
ships the full table of 244 regions and takes country codes, country names
or ids in regions, several at once.
Pagination goes all the way, but only if you pace it. A full walk of
monzo.com returned 1,398 ads over 14 pages in 2.1 seconds. A full walk of
nike.com restricted to France returned 19,782 ads over 198 pages in 31.5
seconds. There is no hidden ceiling at 1,000 or 10,000 rows - the cursor simply
runs out. There is, however, a rate limit: a burst of 200 pages
(20,000 ads) went through in 33.9 seconds, and at 438 pages the
report answered 429. From a home connection the block held for at least 5424
seconds - the measurement ran out before the report relented. This actor throttles itself, backs off, keeps every row it already
collected, and says so in the run report instead of dying.
A brand is not an advertiser. Buying ads under one brand usually means
several advertiser accounts in different countries, plus resellers and
affiliates pointing at the same domain. Searching by domains catches all of
them; searching by advertiserNames resolves the brand to its accounts and
takes the biggest ones first, with the ad count of each printed in the log.
Named values instead of raw numbers. The report speaks in enum numbers:
format 2, surface 9, policy 15. This actor translates them - image,
youtube, gambling_and_games - using the tables Google ships in the report's
own application, so the rows read like data and not like a protocol dump. The dataset has 63 columns. The three most used actors in this niche expose
13, 10 and 8 columns in their dataset views.
Inputs
Targets, any mix of them:
advertiserNames- brand names. Each is resolved to advertiser accounts, biggest first, up tomaxAdvertisersPerName.domains- landing page domains such asnike.com. Covers every advertiser that sends traffic there.advertiserIds- exact ids likeAR16735076323512287233.startUrls- links copied from adstransparency.google.com. Advertiser, creative, domain and region are read out of the link; a link to a single creative is fetched directly instead of being searched for.
Scope and filters:
regions- country codes, country names oranywhere. Several are allowed; each is a separate pass and an ad found in two regions is delivered once with both listed.adFormats-text,image,video.surfaces-search,youtube,shopping,maps,play.shownAfter,shownBefore- date bounds,YYYY-MM-DD.minDaysShown- keep long runners only.onlyWithImage- keep creatives that carry a direct image URL.politicalReport- ask the political section instead of the general one.
Depth, volume and output:
resultType-ads,advertisers,bothordisapproved.includeDetails- one extra request per ad for the full creative card.detailConcurrency- how many detail requests run at once.maxItems- a limit on delivered rows, not on rows walked.maxAdsPerTarget- a cap per advertiser, domain and region pass.maxAdvertisersPerName- accounts taken per brand name.onlyNewAds,emitUnchanged,monitorStoreName- monitor mode and its memory.includeHtml,includeRawData,compactOutput- how heavy each row is.
Output columns
Ads: creative_id, advertiser_id, advertiser_name, advertiser_legal_name,
advertiser_disclosed_name, advertiser_trademark_name, domain, format,
format_id, first_shown, last_shown, days_shown, region, regions,
ad_url, advertiser_url, image_url, preview_url, html, variations,
variations_count, targeting, category, category_id, vertical,
countries, countries_count, served_countries, eea, us,
impressions_low, impressions_high, spend_low, spend_high,
contains_synthetic_media, google_grants_account, served_consecutively,
advertiser_unverified, reported_by_user, political_region,
reported_time, change_type, raw.
Advertisers: billing_country, disclosure_country, creatives_total,
creatives_low, creatives_high, impressions, matched_name, country,
unverified, political_report_url, political_creatives, regulatory_ids,
candidate_name, candidate_office, promoter_name, promoter_address.
Removed ads: disapproved, disapproved_at, policies, violations.
targeting names the categories the advertiser used and whether each was
included or excluded - demographics, geography, contextual, topic of interest,
advertiser list - plus the age brackets and genders where Google publishes
them. countries carries one row per country with the impression range, the
first and last served dates and, when Google splits it, the impressions per
surface: search_desktop, search_mobile, youtube, gmail, news and
thirteen more names.
Honest limits
This section exists because the alternative is a buyer discovering these on their own run.
- Date filters are applied by this actor, not by the report. The query has
its own
servedDateLowerBoundandservedDateUpperBound, and measurement says they do nothing: 40 rows unfiltered, 40 rows with a lower bound in 2027, 40 rows with an upper bound in 2020; a third encoding returns zero rows for every input. SoshownAfterandshownBeforeare honest filters over collected rows - which means a narrow window on a large advertiser still costs the walk. - You cannot search the ad text. The report has a field for it and answers
an empty list for every word tried -
insurance,sale,vote. Nobody can offer real ad-copy search here; if you see it offered, it is filtering after the fact, the same as any date filter in this niche. - Impressions and spend are mostly empty for commercial ads. Google publishes those numbers for political advertising and for the EEA breakdowns. Regular product ads carry dates, formats and countries, not volume.
- No proxy support. The actor runs on Apify's own egress, which measured 200 pages in 34 seconds without a block. A competitor actor in this niche does offer a proxy input; if your workload needs tens of thousands of ads per hour, that is a real difference and this actor will instead stop politely and report partial results.
- No file import for URLs. Paste them into
startUrls. - Advertiser-level spend statistics are not offered. The report's statistics endpoint answered empty for every request shape tried, and an empty answer is not a feature.
How the run reports itself
Every run writes a REPORT record next to the dataset: targets walked, region
by region, how many ads each pass saw, how many requests were spent, the
report's own estimate of the library size, how many duplicate rows were dropped
before you were charged, and what every filter removed. When the dataset ends up
empty the report names the reason - nothing-changed, filtered-out,
source-returned-nothing, source-refused or charge-limit-reached - and the
log says the same thing in words. An empty dataset is normal in monitor mode
and it should never look like a failure.
Monitor mode
Turn on onlyNewAds and schedule the run. The actor keeps a named key-value
store with a fingerprint of everything it has already delivered; the
fingerprint is built only from fields that arrive in every mode, so switching
includeDetails on and off does not make every ad look changed. New and
changed creatives are delivered and charged, unchanged ones are skipped, and
change_type says which is which. Give each watch its own monitorStoreName
when you follow several competitors.
The memory holds 40,000 keys and drops the oldest beyond that, which is about 3 MB against the platform's 9 MB per-record limit.
FAQ
Is this affiliated with Google? No. It reads a public transparency report that Google publishes, the same pages a person sees at adstransparency.google.com.
Do I need an API key, a login or a proxy? No. The actor uses the standard library only and runs in 1024 MB.
How many ads can I get? As many as the report has: the cursor exhausts naturally. Measured walks: 1,398 ads for a small advertiser, 19,782 for one market of a big one. Very large libraries - the 100,000-200,000 range - will hit the report's rate limit before they finish; the actor delivers what it collected and says why it stopped.
Why does my advertiser have fewer ads than I expected? Two usual reasons. The region narrows the library, and a brand runs several advertiser accounts - check the log, it prints every account found for a brand name with its ad count.
Why is image_url empty on some rows? Text ads and video ads have no
static image. Use preview_url, or turn on includeDetails to get every
rendering variation.
Can I get the YouTube video of a video ad? You get the creative's rendering variations and the preview URLs Google serves. The underlying video id is not part of the public payload for every ad.
What does contains_synthetic_media mean? Google flags creatives that
contain AI-generated content. The flag is carried through as it comes.
How do I watch a competitor daily without paying twice? onlyNewAds: true,
a schedule, and a monitorStoreName per competitor.
What happens if the report blocks the run? The actor stops that target,
keeps everything already collected, writes source-refused into the report and
exits successfully. Retry later: on Apify's egress the block cleared within a
minute, while a home connection that had hammered the report stayed blocked for
the full 5424 seconds of the measurement.