Google Ads Transparency Scraper — Advertiser Ad Library Export
Pricing
Pay per event
Google Ads Transparency Scraper — Advertiser Ad Library Export
Scrape ad creatives from the Google Ads Transparency Center by advertiser domain or advertiser ID — creative, format, regions, first/last shown, landing URL — export to JSON or CSV. A Google Ads Transparency API alternative and data exporter. You pay only for ads that land. Google ads spy tool.
Pricing
Pay per event
Rating
0.0
(0)
Developer
DevilScrapes
Maintained by CommunityActor stats
0
Bookmarked
80
Total users
28
Monthly active users
a day ago
Last modified
Categories
Share
Quick answer: The Google Ads Transparency Scraper pulls every public ad creative Google logs for a brand or advertiser — creative ID, format, landing domain, impression counts, first/last-seen dates, and preview URLs — straight from the Google Ads Transparency Center (the closest thing Google has to Meta's "Ad Library") into JSON, CSV, or Excel. Google ships no official API for this data; we replay its internal RPC ourselves and absorb the browser fingerprinting so you don't have to. Pricing is pay-per-result — $3.20 per 1 000 ads landed, no subscription, no card required to try it.
🎯 What this scrapes
The Google Ads Transparency Center is Google's public registry of every ad campaign running on Search, YouTube, Display, Shopping, Maps, and Play. This Google Ads Transparency Scraper talks directly to Google's internal SearchService/SearchCreatives RPC — so it pulls fast, stable structured data without the overhead of a full browser session.
Google publishes no official API for this data. We reverse-engineered the RPC, replay it with a real-browser TLS fingerprint, and absorb all the reliability work so you get clean rows.
Two output shapes, same underlying scrape: the default per-creative mode below, or domain ad-screening mode (screeningMode: true) — flip it on to bulk-check a list of domains for Google Ads activity, one row per domain instead of one per creative (see Output and Pricing).
Per creative you get:
| Field | Type | Notes |
|---|---|---|
advertiser_id | string | Google's stable advertiser identifier (e.g. AR0123…) |
advertiser_name | string | Public-facing brand name |
creative_id | string | Stable per-creative ID (e.g. CR0123…) |
creative_url | string | Deep link into Transparency Center |
landing_domain | string | Click-through domain |
format_type | integer | Numeric format code (1=text, 2=image, 3=video — inferred) |
first_shown_ts | integer | Unix seconds, first observed impression |
last_shown_ts | integer | Unix seconds, last observed impression |
impressions | integer | Google-reported impression count |
preview_image_url | string | null | Static thumbnail (image creatives) |
preview_content_js_url | string | null | JS bundle URL (video/rich creatives) |
region | string | Locale label you passed (display only) |
scraped_at | string | ISO-8601 UTC timestamp |
Why we replay the RPC instead of automating a browser
Most listings in this niche point a headless browser at the public Transparency Center UI and re-parse the rendered DOM on every run — one slow page load per handful of creatives, and a broken selector every time Google reshuffles its frontend. We skip the browser: our client speaks the internal SearchCreatives RPC directly, replaying the exact TLS handshake a real Chrome tab would send. One round-trip returns roughly 40 structured creatives, and because it's a backend contract rather than rendered HTML, a Google frontend redesign doesn't break us the way it breaks DOM scrapers overnight.
We're also upfront about what the RPC can't do: Google's SearchCreatives endpoint ignores the region parameter server-side — we tested every plausible request shape to confirm it, and we'd rather publish that finding than ship a region filter that quietly does nothing (see Limitations).
🔥 What we handle for you
- 🛡️ Browser fingerprint rotation — every RPC call replays a real Firefox TLS+H2 handshake via
curl-cffi, so Google's edge sees a browser, not a Python script. - 🌐 Apify Proxy support — sticky-session proxying keeps cookie continuity across a target's pagination run.
- 🧱 Paced request cadence — a fixed gap between RPC pages keeps us under the SPA's own request rate.
- 🧊 Clean, typed dataset rows — golden-file tested against four real creative shapes (static image, rich video, minimal, malformed) before every release.
- 💰 Pay-per-result pricing — a small per-run fee, then you're charged only for ad rows that actually land in your dataset. No data, no charge.
- 🧪 Batch input, deduplicated — scrape dozens of domains and advertiser IDs in a single run; overlapping creatives across targets are merged, not double-billed.
- 🔍 Bulk domain ad-screening mode — check a list of brand domains for Google Ads activity in one run without paying per creative; a domain with zero ads still finishes as a clean, successful result.
💡 Use cases
- Competitor ad spend tracker — pull every Nike ad once a week and diff the creative set to see what launched; track competitor Google Ads spend without manually clicking through the Transparency Center UI.
- Trademark enforcement — monitor advertisers running ads against your brand keyword; combine with your own takedown workflow.
- Affiliate-fraud detection — flag advertisers whose landing domain doesn't match the advertiser name.
- Political-ad monitoring — track which advertisers are active in an election cycle.
- Brand-safety audits — for agencies, prove the ads currently live for a client before the QBR.
- Market research — observe how saturated a vertical (crypto, sports betting, supplements) is with active creatives.
- AI / RAG ingestion — feed creative metadata and image URLs into a vector store for image-grounded competitive analysis.
- Bulk domain ad screening — feed in a prospect list or a portfolio of brand domains and get back a yes/no "is this domain running Google Ads" flag per domain, with a rough ad count — a lead-qualification or compliance-sweep pass before you invest in per-creative pulls.
⚙️ How to use it
- Click "Try for free" at the top of the page.
- Paste one or more brand domains into the
Brand domainsfield (e.g.nike.com,adidas.com). One per line. Each domain spawns its own scrape. - (Optional) Drop in advertiser IDs if you already know them — they look like
AR0123456789and live in the Transparency Center URL when you click into an advertiser. - (Optional) Set a date window to narrow ad activity. Defaults to the last 365 days.
- (Optional) Flip on Domain ad-screening mode if you want one summary row per domain (has ads? how many? first/last seen?) instead of every individual creative.
- Run. Each ad is one row in the dataset by default (one row per domain in screening mode); export to JSON, CSV, or Excel from the Storage tab.
The first run on a new account uses $5 of free Apify credit — that's roughly 1 600 ads at our pricing.
📥 Input
The schema lives in .actor/input_schema.json. The fields:
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
searchDomains | array of string | one of | ["nike.com"] | Brand landing domains, one per line |
advertiserIds | array of string | one of | [] | Google advertiser IDs (AR…) |
region | enum string | no | anywhere | Display-only — Google's RPC does not filter by region (see Limitations) |
dateFrom | string (YYYY-MM-DD) | no | 365 days back | Lower bound of ad-activity window |
dateTo | string (YYYY-MM-DD) | no | today (UTC) | Upper bound |
maxResults | integer | no | 1000 | Total dataset items across all targets. 0 = unlimited |
maxPages | integer | no | 25 | RPC budget per target (40 ads × 25 pages = 1 000 / target) |
proxyConfiguration | proxy config | no | Apify Proxy enabled | Sticky session recommended |
screeningMode | boolean | no | false | true = one row per domain/advertiser instead of one per creative (see Output) |
At least one of searchDomains or advertiserIds must contain at least one entry.
Example input
{"searchDomains": ["nike.com", "adidas.com"],"advertiserIds": ["AR03012025048987521025"],"region": "US","dateFrom": "2025-11-15","dateTo": "2026-05-15","maxResults": 5000,"maxPages": 25,"proxyConfiguration": { "useApifyProxy": true }}
📤 Output
Every row is one creative. Example:
{"advertiser_id": "AR18378488041124659201","advertiser_name": "Nike Retail BV","creative_id": "CR15771942603307614209","creative_url": "https://adstransparency.google.com/advertiser/AR18378488041124659201/creative/CR15771942603307614209?region=anywhere","landing_domain": "nike.com","format_type": 1,"first_shown_ts": 1761145807,"last_shown_ts": 1778871417,"impressions": 205,"preview_image_url": "https://tpc.googlesyndication.com/archive/simgad/12774179880874022668","preview_content_js_url": null,"region": "anywhere","scraped_at": "2026-05-15T19:17:59+00:00"}
Domain ad-screening mode output
With screeningMode: true, each dataset row is one input target instead of one creative — aggregated over the same SearchCreatives pull, no extra request:
{"domain": "nike.com","has_ads_detected": true,"ad_count": 40,"first_seen_ts": 1761145807,"last_seen_ts": 1778871417,"sample_creative_url": "https://adstransparency.google.com/advertiser/AR18378488041124659201/creative/CR15771942603307614209?region=anywhere"}
A domain with no ads in the window still finishes as a normal, successful row — not a failure:
{"domain": "example.com","has_ads_detected": false,"ad_count": 0,"first_seen_ts": null,"last_seen_ts": null,"sample_creative_url": null}
ad_count is capped by maxResults (and by the pagination budget in maxPages) the same way per-creative mode is — see Limitations.
Export options once the run finishes:
- JSON — full payload, ideal for AI/RAG pipelines
- CSV / Excel — for analyst spreadsheets; sort by
impressionsto find big-spender ads - JSONL — line-delimited, easy to stream into a warehouse
- API — fetch programmatically via
GET /v2/datasets/{id}/items; webhook onACTOR.RUN.SUCCEEDEDfor live pipelines
💰 Pricing
Pay-per-event. You pay for what you get, nothing for what you ask for:
| Event | Price | When charged |
|---|---|---|
actor-start | $0.20 | Base fee, once per run (warm-up, cookie handshake, proxy resolution) |
ad-result | $0.003 | Per ad creative written to the dataset (default mode) |
The base fee moves from $0.005 to $0.20 on 2026-09-04; the per-ad rate is unchanged. The figures on this page are the post-change prices.
Domain ad-screening mode bills differently. With screeningMode: true, the
ad-result event charges once per domain/advertiser screening row, not
per creative — screening 50 domains costs the same $0.20 start fee plus
50 × $0.003 ≈ $0.35 total, regardless of how many ads any one domain
actually runs.
Examples:
| Pull | Cost |
|---|---|
| 100 ads | $0.50 |
| 1 000 ads | $3.20 |
| 10 000 ads | $30.20 |
| 100 000 ads (monthly competitor sweep) | $300.20 |
Compare to: building this in-house is roughly two engineer-weeks plus the ongoing cost of maintaining a proxy pool and the TLS-fingerprint replay loop. We've already done it, and we keep it running as Google's RPC shifts underneath us.
🚧 Limitations
- Region is metadata, not a filter. Google's
SearchCreativesRPC ignores the geo target — we confirmed this empirically (seescripts/recon/FINDINGS.md). The Transparency Center browser UI shows a region selector, but the server returns the same creative set regardless. We exposeregionso you can tag exports by intended locale, nothing more. - No region-only browsing. You must supply a
searchDomainoradvertiserId. There is no "all ads in country X" mode on the public RPC. If Google adds one we'll wire it in. - Video / rich creatives return a
content.jsURL, not an MP4. Rendering the actual video frame requires executing Google's JS bundle — out of scope for v1. - Date range is enforced by Google, not us. They retain roughly 12 months of history. Requesting older dates clips to that window.
- Large advertisers hit pagination caps. Google's infrastructure stops responding past roughly 1 000 ads per query. Nike's library claims ~300 000 ads; the default
maxPages=25is intentionally conservative. Raise it for full-history pulls knowing you may hit the server-side ceiling. - Screening mode's
ad_countis a floor, not an exact total. It counts creatives actually pulled withinmaxPages/maxResults, same ceiling as per-creative mode above — a domain flaggedhas_ads_detected: truewithad_count: 40may run more than 40 ads; raisemaxPagesif you need a tighter count.
❓ FAQ
Is this legal?
Yes. The Google Ads Transparency Center is a public registry Google operates under EU DSA and US regulatory pressure. We scrape only what the public UI exposes at a polite cadence, and we do not bypass authentication. We also do not collect personal data — only advertiser-level metadata.
Does Google have an official API for Ads Transparency data?
No. As of 2026, Google publishes no official API for the Transparency Center. We reverse-engineered the internal SearchCreatives RPC, replay it with a real-browser fingerprint, and keep the implementation current as the endpoint evolves. The "google ads transparency api" you may have searched for is exactly what this Actor provides.
Is this the same thing as a "Google Ads Library" scraper?
Effectively yes. Google doesn't officially brand it "Ads Library" the way Meta does — the product is the Google Ads Transparency Center — but that's the phrase people search for when they mean the same target. Same registry, same data, this Actor covers it either way.
Why replay an RPC instead of automating a browser against the UI?
Speed and stability. A browser-automation approach re-renders the Transparency Center page for every batch of creatives and re-parses whatever DOM structure Google shipped that week. Talking to the internal RPC directly returns ~40 structured creatives per round-trip and doesn't break when Google reshuffles frontend markup — see Why we replay the RPC above.
How do I scrape Google Ads Transparency Center data, step by step?
Paste a brand domain or advertiser ID into the input, run the Actor, and export. Under the hood we replay Google's internal SearchCreatives RPC instead of automating a browser against the public UI — see How to use it below for the exact steps.
Can I export Google Ads Transparency data to a spreadsheet or database?
Yes — this is a Google Ads Transparency data export tool at heart. Every run's dataset exports to JSON, CSV, Excel, or JSONL from the Storage tab, or pull it programmatically via the API (see Output above).
Why is the region selector marked "display only"?
Because we empirically confirmed the RPC ignores it. Other scrapers on the Store claim region filtering; we tested every plausible RPC body shape and none returned a region-narrowed result set. We would rather under-promise than ship broken filtering. If Google adds a server-side region filter, we will wire it in immediately.
Why isn't there a search-by-keyword mode?
Google's RPC does not expose one. You search by advertiser. For brand-keyword monitoring, give us the domain (e.g. nike.com) and the scraper returns every ad pointing at that domain — including those bought by competitors bidding on your name.
Can I scrape political ads specifically?
Not yet — political ads live in a separate Google library with its own endpoints. Open an issue on the Apify Store listing if you want this; we will prioritize based on demand.
How do I export to Google Sheets or a database?
Three options:
- Console → Storage → Export for one-off CSV downloads.
- Webhook the dataset URL to a Make / Zapier flow that appends to Sheets.
- Apify integration nodes in Airbyte, n8n, or your warehouse loader.
Some preview URLs are null. Why?
Rich, video, and animated creatives expose only a content.js URL — Google renders the preview via JavaScript. Static image creatives give you a direct preview_image_url. If you need actual video frames, post-process the content.js URL with a headless browser downstream.
The number of returned ads is less than Google's reported total. Why?
Google paginates and stops responding past an internal limit we have observed at roughly 1 000 ads per query. For very large advertisers, raise maxPages beyond the default of 25 if you need fuller coverage.
Can I bulk-check a list of domains for Google Ads activity without pulling every creative?
Yes — turn on screeningMode. Instead of one row per ad creative, you get one row per input domain (or advertiser ID) with has_ads_detected, an ad_count, first/last-seen timestamps, and a sample creative link. It's the same underlying search, just aggregated differently, so it's billed once per screening row instead of once per creative — see Pricing.
How do I scrape google ads transparency center data automatically on a schedule?
Go to Apify Console → Schedules, attach this Actor, and set your cron. Weekly is the right cadence — Google updates the Transparency Center daily at most. More frequent polling wastes credit without new signal.
What integrations does this Actor support?
- Schedule — Apify Console → Schedules tab → run weekly for monitoring.
- Webhooks — register
ACTOR.RUN.SUCCEEDEDto fire your downstream pipeline as soon as the dataset is final. - API —
POST /v2/acts/DevilScrapes~google-ads-transparency/run-sync-get-dataset-itemsreturns the full result set in one synchronous call (good for up to a few thousand ads). - Make / Zapier — every Apify Actor surfaces as a node out of the box.
- n8n — use the Apify community node; a workflow template is available on n8n.io/workflows.
💬 Your feedback
Spotted a bug, missing field, or want a new feature? Open an issue on the Apify Store listing — we read every one.
Built by Devil Scrapes — Apify Actors with attitude. PPE, transparent pricing, no junk fields.