DEV Community

Esteban Ortega
Esteban Ortega

Posted on

How to Download Every Ad a Competitor Runs on Google (and Why Most Scrapers Return Empty)

Google publishes every ad an advertiser is currently running. Not leaked, not scraped from private data — published, on purpose, at adstransparency.google.com, as part of its ads-accountability program. Search any brand and you'll see their whole live creative library: every image ad, every HTML5 unit, when each first and last ran, and in which countries.

For anyone doing competitive ad research, that's the primary source. The catch is what's not there: an export button. You can look at ads one at a time in a web UI, and that's it.

What the Transparency Center actually gives you

Three ways to find an advertiser:

  • By name — resolved through a suggestion service (type "Nike", get candidate advertisers).
  • By advertiser ID — every advertiser has a stable AR… identifier, visible in the page URL. This is the deterministic option.
  • By domain — with a quirk: Google exposes match counts for a domain but not a clean domain→advertiser mapping, so some domains only resolve to candidates.

Per creative, the underlying data includes the format (image / HTML5), preview URLs, first-shown and last-shown timestamps, and — one level deeper — per-region last-shown dates and every render variant of the creative.

Why DIY scrapers (and several paid ones) silently return nothing

The site is a JavaScript app talking to internal RPC endpoints, and if you build against them yourself, four landmines are waiting:

  1. The payload shape drifts. Google periodically reshuffles the request format. A scraper built on last quarter's payload doesn't error — it receives an empty {} and happily reports "this advertiser runs zero ads." That's the worst possible failure mode for research data: it looks like an answer. It's the main reason the most-installed Transparency scraper on Apify sits at ~2.2★ — check its reviews and you'll see "returns empty" over and over.
  2. Pagination is a token chain. Results come in pages linked by continuation tokens. Stop after the first page — which many tools quietly do — and a 900-creative advertiser looks like a 100-creative advertiser. No error, just silently wrong.
  3. An empty response is genuinely ambiguous. Zero results can mean a dormant advertiser, a soft-block on your IP, or payload drift. Telling those apart requires cross-checking Google's own advertiser-level ad counts — most tools don't bother.
  4. The asset URLs expire. The simgad image links die quickly. A swipe file of URLs rots in weeks unless you persist the actual bytes at collection time.

None of this is hard to handle once — it's hard to keep handled, because the drift is ongoing.

The maintained option

I run enough of this research that I packaged the whole thing as an Apify actor: Google Ads Transparency Scraper. Design goals, in order:

  1. Complete captures or a loud error — never a silent empty. Payload drift, soft-blocks, and mid-pagination truncation all produce explicit error/notice records, and a truncated run is marked partial: true on the advertiser summary. A genuine zero (Google's own counts confirm no ads) is reported as a clean zero.
  2. Full token pagination. Every creative, not the first page. Each record carries the creative ID, format, preview/image URL, first/last shown, and a deep link back to the Transparency Center so anyone can verify.
  3. Optional depth. Per-region last-shown dates and render variants (one enrichment call per creative), and optional asset rehosting that stores the actual image bytes before the URLs expire.
  4. The advertiser summary tells you if you got everything. It carries both the count you scraped and Google's own reported totals, so a capped or truncated run is visible instead of invisible.
curl -X POST "https://api.apify.com/v2/acts/silentshadow55~google-ads-transparency-actor/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"advertiserName": "Nike", "region": "US", "maxCreativesPerAdvertiser": 300}'
Enter fullscreen mode Exit fullscreen mode

Pricing is per creative (about a tenth of a cent), which for context is a different shape than SerpApi's metered Transparency API (~$25/mo floor) or ad-spy dashboards like AdSpy/BigSpy ($9–459/mo seats): you pay for the advertisers you actually check, and the raw JSON is yours to pipe into Sheets, a dashboard, n8n, or an AI agent.

Is this okay to do?

The Ads Transparency Center is Google's own public accountability database — the same pages it shows any visitor, with no login, no gate, and no terms click-through. Reading it politely (rate-limited, no CAPTCHA or WAF circumvention — this actor does neither) is reading public data that exists specifically so ads can be scrutinized. Use it for competitive research, not for anything the transparency program wasn't built for.


I build data tools on Apify. If an advertiser, region, or format misbehaves, open an issue on the actor — loud errors are the product, so bugs get fixed fast.

Top comments (0)