Competitor Ads Spy - Google Ads Transparency Center, Creatives avatar

Competitor Ads Spy - Google Ads Transparency Center, Creatives

Pricing

$1.45 / 1,000 ad creatives

Go to Apify Store
Competitor Ads Spy - Google Ads Transparency Center, 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

Snow Leo Data

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

6 days ago

Last modified

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 nike resolves 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 to maxAdvertisersPerName.
  • domains - landing page domains such as nike.com. Covers every advertiser that sends traffic there.
  • advertiserIds - exact ids like AR16735076323512287233.
  • 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 or anywhere. 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, both or disapproved.
  • 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 servedDateLowerBound and servedDateUpperBound, 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. So shownAfter and shownBefore are 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.