Google Ads Transparency Scraper — Ads, Creatives & Contacts
Pricing
from $2.00 / 1,000 per ad creative returneds
Google Ads Transparency Scraper — Ads, Creatives & Contacts
Scrape the Google Ads Transparency Center: get every ad an advertiser runs on Google by domain, advertiser ID or brand name — creative ID, format, image/preview URL, first and last shown, days active, regions — plus the advertiser's website email, phone and socials. No login.
Pricing
from $2.00 / 1,000 per ad creative returneds
Rating
0.0
(0)
Developer
Scrapers Delight
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Turn the Google Ads Transparency Center into a clean table of every ad an advertiser runs on Google — Search, YouTube, Display, Shopping, Maps and Play. One row per ad creative: creativeId, advertiserId, advertiserName, domain, format, imageUrl / previewUrl, videoUrl, firstShown, lastShown, daysShown, googleCreativeId, googleCustomerId, adGroupId, regionsShown, variations, adUrl — and, on the same row, the advertiser's own website contact: advertiserEmail, advertiserPhone, advertiserSocials, advertiserWebsite. Look up by domain, advertiser ID, brand name or a pasted Transparency Center URL. No login. No cookies. No CAPTCHA solving. Runs at 256 MB with no browser.
Measured 2026-08-22: 600 ads across three domains in 44 seconds, 600 unique creatives, 0 duplicates, 15 of 15 pages served — through the Apify datacenter proxy, not a home IP. The same sustained test passed 15 of 15 on RESIDENTIAL too.
{"domains": ["hellofresh.com"],"region": "US","maxAdsPerTarget": 40,"maxItems": 200,"enrichAdvertiserContacts": true}
Click Try for free and hit Start — that block is literally the input the Actor ships
with. A run on those shipped defaults returned 40 ads in 16 seconds with creative ID,
advertiser, format, dates and days-active at 100% fill, and the advertiser contact found
(hello@hellofresh.com, Facebook, Instagram, X). Cost: $0.11 ($0.08 for the ads + $0.03
for the one contact).
The wedge: "who is advertising" becomes "who to write to"
More than a dozen Actors on the Store already read the Transparency Center, and several of them do it well. What none of their input schemas has is the step after the ad list. An advertiser that is spending on Google right now is a live buyer of marketing, analytics, creative and agency services — the ad row tells you they spend, but nothing in the Transparency Center tells you how to reach them.
This Actor opens the advertiser's own website (the landing domain the Transparency Center
publishes on every domain-route row), reads the public business contact off the homepage and
its contact / about / imprint pages, and puts it on the row: the best on-domain email
(sales@, hello@, info@ ranked above careers@ and privacy@), the phone number from
the site's tel: links, and the LinkedIn / Facebook / Instagram / X / YouTube / TikTok
profiles. Business contact data only — no people lookups, no name inference, nothing
behind a login.
It is success-billed: one advertiser-contact-found event per advertiser domain,
charged only when an email or phone was actually read off the site. A site with nothing
public, a dead domain or a bot-walled homepage costs nothing and the columns stay null.
Measured on a deliberately hard list of twelve big-brand domains (the ones most likely to
hide contact details behind forms): 9 of 12 returned an email or phone; the three misses
were two bot-walled homepages and one HTTP 400, all free.
Two more things that set the row apart:
videoUrl— for YouTube video ads, with Fetch per-region reach and variations on, the Actor resolves the actualyoutube.com/watch?v=link from the preview bundle. Measured on 12 Nike video ads: 7 resolved (58%); the other 5 are non-YouTube preview types and staynull.- Monitor mode (
onlyNewAds) — a named key-value store remembers every creative the Actor has delivered; a scheduled run returns only creatives launched since, and is billed only for those. Verified: the second run on the same domain returned 0 rows, stopped after one page, and said so in the status message.
Read this before you buy rows
Five things that would otherwise turn into a refund request.
- Contact enrichment needs a domain, and only the domain route guarantees one. Rows
found by domain carry
domainon 100% of rows (Google publishes it). Rows found by advertiser ID or brand name carry no landing domain, soadvertiserEmail/advertiserPhonestaynullon those routes and you are never charged a contact event for them. If you want the contact, search by domain. - Brand-name search is Google's fuzzy autocomplete, not a brand lookup.
"Nike"returns ten fuzzy matches — Nikena, Nikesh, a Kenyan Nike — alongside Nike, Inc.. The Actor ranks them by name match, verified badge and account size (on a log scale, so HelloFresh's 10,000-ad main account outranks its 2-ad verified stub), which puts the 10,000-ad Nike, Inc. account first, but the candidate list is Google's and a brand with no clean match can be missed. When you know the domain, use it. - Region changes the result set, not just a filter flag.
hellofresh.comreturned 40 ads for US, 10 for GB and a different 40 for DE in the same minute.ANYWHEREreturns ads shown in any country. Pick deliberately — the default is US. - Text ads come back as images. Google renders Search text ads as a static image
(
imageUrl,tpc.googlesyndication.com/archive/simgad/…), so there is no headline or description text to extract — for any scraper, not just this one. Image and video ads come back as a Google-hosted preview (previewUrl) that renders the live creative. daysShownis Google's own "days shown" figure, not a span you can recompute — it usually differs fromlastShown − firstShown(in our sample by 2 days on most rows and by 142 on one). Treat it as a Google-reported reach signal, not as continuous days live.
What you get
One row per unique ad creative. Dates are ISO-8601 UTC; lastShown is the most recent
impression Google recorded in the searched region.
| Group | Fields | Example |
|---|---|---|
| Identity | creativeId, advertiserId, advertiserName, advertiserVerified, advertiserCountry, domain | CR08275988769178386433 · Grocery Delivery E-Services USA Inc. · hellofresh.com |
| Creative | format, formatCode, previewType, imageUrl, imageWidth, imageHeight, previewUrl, videoUrl, youtubeVideoId | IMAGE · iframe · a content.js preview URL |
| Google IDs | googleCreativeId, googleCustomerId, adGroupId, versionId | 662879873968 · 5588076203 · 150785776295 |
| Timing | firstShown, lastShown, daysShown | 2023-06-22T22:08:17Z · 2026-08-22T16:08:31Z · 1010 |
| Reach (detail on) | regionsShown[] (region, criteriaId, lastShown), regionCount, variations[], variationCount | [{US, 2840, 2026-08-22}, {DE, …}] · 3 |
| Contact (domain route) | advertiserWebsite, advertiserEmail, advertiserEmails[], advertiserPhone, advertiserPhones[], advertiserSocials{}, contactSource, contactFound | hello@hellofresh.com · {facebook, instagram, twitter} |
| Links | adUrl, advertiserUrl | the Transparency Center pages for the ad and the advertiser |
| Provenance | region, searchType, searchTarget, isNew, scrapedAt | US · domain · hellofresh.com |
The dataset ships with a saved table view (advertiser, domain, format, dates, days active, image, preview, contact email, phone, website, regions, IDs) so you do not have to configure columns.
Field fill — measured on 600 ads
Three domains (hellofresh.com, hubspot.com, casper.com), region ANYWHERE, 200 ads each,
2026-08-22. Sorted by fill, so the sparse fields are impossible to miss. Format mix on this
sample: 463 TEXT, 108 IMAGE, 29 VIDEO.
| Field | Fill | Notes |
|---|---|---|
creativeId / advertiserId / advertiserName | 100% | |
domain | 100% | domain route; null on advertiser-ID and name routes |
format / formatCode | 100% | TEXT / IMAGE / VIDEO |
firstShown / lastShown / daysShown | 100% | |
adUrl / advertiserUrl | 100% | |
advertiserWebsite | 100% | the homepage that answered (domain route) |
advertiserSocials | 100% | at least one profile on all 3 domains |
contactSource | 100% | the page the contact was read from |
imageUrl / imageWidth / imageHeight | 73.5% | almost every TEXT ad (Google renders Search ads as a static snapshot); IMAGE and VIDEO ads normally carry previewUrl instead |
advertiserEmail | 66.7% | 2 of the 3 domains published one (hello@hellofresh.com, support@casper.com); HubSpot publishes phone only |
advertiserPhone | 66.7% | HubSpot and Casper; HelloFresh's site has no tel: link |
previewUrl / googleCreativeId / googleCustomerId / adGroupId | 26.5% | wherever Google serves a live preview bundle — nearly all IMAGE and VIDEO ads and a small share of TEXT ads. These IDs are parsed out of the preview URL, so they are absent whenever previewUrl is null. |
versionId | 5.7% | only on versioned rich-media previews |
regionsShown / variations | 0% here, 100% with detail on | measured 12/12 on a separate detail run; off by default |
videoUrl / youtubeVideoId | 58% of VIDEO ads with detail on | 7 of 12 Nike video ads resolved to a YouTube watch URL |
The headline that could mislead you: imageUrl + previewUrl together are 100%. Every
ad has exactly one of them — imageUrl when Google rendered a static snapshot (nearly always
a TEXT ad), previewUrl when it serves a live preview (nearly all IMAGE and VIDEO ads, and
some TEXT ads). Do not filter on one of them alone.
How to run it
1. By domain (the usual choice, and the one that brings the contact)
{"domains": ["hellofresh.com", "casper.com"],"region": "US","maxAdsPerTarget": 200,"maxItems": 1000}
Google matches ads whose landing page is on that domain, so one domain can return several
advertiser accounts (nike.com returns Nike, Inc., Nike Retail BV and NIKE GLOBAL
TRADING B.V. SINGAPORE BRANCH). Paste a full URL and the Actor strips it to the hostname.
2. By advertiser ID
{ "advertiserIds": ["AR00930880903813529601"], "region": "ANYWHERE", "maxAdsPerTarget": 500 }
The AR… token from an advertiser page URL. Exact, but carries no landing domain (see gotcha 1).
3. By brand name
{ "queries": ["HelloFresh"], "maxAdvertisersPerQuery": 3, "region": "DE" }
Resolved through the Transparency Center's own autocomplete into up to maxAdvertisersPerQuery
accounts, each walked separately. The log prints exactly which accounts were chosen and why
(HelloFresh SE (AR1741…, DE) vs HelloFresh SE (AR1171…, DE, verified)).
4. Pasted Transparency Center URLs
{"startUrls": [{ "url": "https://adstransparency.google.com/advertiser/AR00930880903813529601?region=US" },{ "url": "https://adstransparency.google.com/?domain=casper.com®ion=GB" },{ "url": "https://adstransparency.google.com/advertiser/AR00930880903813529601/creative/CR12924188684000952321?region=US" }]}
Advertiser pages, domain searches and single creatives are all parsed; a region= in the URL
overrides the Region field for that URL. A single-creative URL returns that one ad with its
regions and variations.
Filters
region— the Transparency Center's country dropdown (49 countries + ANYWHERE). Applied by Google inside the search.adFormat— ALL / TEXT / IMAGE / VIDEO. Applied by Google inside the search, so an unwanted format is never fetched or billed. Verified:VIDEOonnike.comreturned 40 of 40 video ads.lastShownAfter— keep ads still live on or after a date. Results come back newest-last-shown first, so the Actor stops paging a target as soon as it passes this date: a 7-day window on a 10,000-ad brand costs one or two pages, not 250.firstShownAfter— keep ads launched on or after a date (new creatives). Per-row only.
Per-region reach, variations and video URLs
{ "domains": ["nike.com"], "adFormat": "VIDEO", "includeRegionDetail": true, "maxAdsPerTarget": 50 }
One extra request per ad adds regionsShown (every country the ad ran in, each with its own
last-shown date — a Nike video ad listed DE, ID, PH, NL, PL, FR and US), variations (every
A/B variant with its own preview) and, for YouTube ads, videoUrl. Same price per ad —
it costs time, not money. Measured: 12 ads with detail in 13 RPC calls, ~10 seconds.
Monitor mode — only what launched since last time
{ "domains": ["casper.com"], "onlyNewAds": true, "monitorStoreName": "monitor-casper", "region": "US" }
The first run seeds the memory and returns everything up to your limits. Every later run
returns only creatives not delivered before — and stops paging at the first already-seen
creative, because results are ordered newest-last-shown first and everything launched since
sits above it. Use one monitorStoreName per watch. Attach an Apify Schedule (0 7 * * *)
and a webhook and you have a standing new-ad alert on a competitor for a few cents a day.
Scheduling and integrations
Save the input as a Task, attach a Schedule, read the dataset over the REST API or through the standard integrations (Zapier, Make, n8n, webhooks, MCP). From the API:
curl -X POST "https://api.apify.com/v2/acts/scrapersdelight~google-ads-transparency-scraper/runs?token=YOUR_TOKEN" \-H 'Content-Type: application/json' \-d '{"domains":["casper.com"],"region":"US","maxAdsPerTarget":100}'
Sample row
A real row from the shipped-default run, captured 2026-08-22 17:34 UTC.
{"creativeId": "CR08275988769178386433","advertiserId": "AR00930880903813529601","advertiserName": "Grocery Delivery E-Services USA Inc.","advertiserVerified": null,"advertiserCountry": null,"domain": "hellofresh.com","format": "IMAGE","formatCode": 2,"previewType": "iframe","imageUrl": null,"imageWidth": null,"imageHeight": null,"previewUrl": "https://displayads-formats.googleusercontent.com/ads/preview/content.js?client=ads-integrity-transparency&obfuscatedCustomerId=5588076203&creativeId=662879873968&uiFeatures=12,54&adGroupId=150785776295&itemIds=12663816311744455808&…","googleCreativeId": "662879873968","googleCustomerId": "5588076203","adGroupId": "150785776295","versionId": null,"videoUrl": null,"youtubeVideoId": null,"firstShown": "2023-06-22T22:08:17.000Z","lastShown": "2026-08-22T16:08:31.000Z","daysShown": 1010,"regionsShown": null,"regionCount": null,"variationCount": null,"variations": null,"adUrl": "https://adstransparency.google.com/advertiser/AR00930880903813529601/creative/CR08275988769178386433?region=US","advertiserUrl": "https://adstransparency.google.com/advertiser/AR00930880903813529601?region=US","region": "US","advertiserWebsite": "https://www.hellofresh.com/","advertiserEmail": "hello@hellofresh.com","advertiserEmails": ["hello@hellofresh.com", "support@hellofresh.com"],"advertiserPhone": null,"advertiserPhones": [],"advertiserSocials": {"facebook": "https://www.facebook.com/HelloFreshus","instagram": "https://instagram.com/hellofresh","twitter": "https://twitter.com/HelloFresh"},"contactSource": "https://www.hellofresh.com/","contactFound": true,"searchType": "domain","searchTarget": "hellofresh.com","isNew": null,"scrapedAt": "2026-08-22T17:34:52.246Z"}
Fields people misread:
advertiserNameis the legal entity Google verified, not the brand — HelloFresh's US ads run under Grocery Delivery E-Services USA Inc. The brand is indomain.advertiserVerified/advertiserCountryare only known on the brand-name route (they come from the autocomplete);nullelsewhere is "not available", not "unverified".googleCustomerIdgroups ads from the same Google Ads account;adGroupIdclusters ads from the same campaign. Both exist only where there is apreviewUrl.contactFound: falsewithadvertiserWebsiteset means either the site answered and published no email and notel:link, or a contact was found after your spend cap and therefore not attached. Either way you were not charged.isNewistrueon every delivered row in monitor mode (by definition) andnullotherwise.
Input
Fields in the order the Console shows them.
| Field | Type | Default | What it does |
|---|---|---|---|
| 🎯 Who to look up | |||
domains | string list | ["hellofresh.com"] | Advertiser landing domains. The route that carries domain and therefore the contact. |
advertiserIds | string list | [] | AR… IDs. Exact, no domain. |
queries | string list | [] | Brand names, resolved via Google's autocomplete. |
maxAdvertisersPerQuery | integer | 3 | Accounts a name may expand into (1–10). |
startUrls | URLs | [] | Advertiser / domain-search / creative URLs from the site. |
| 🌍 Filters | |||
region | select | US | Country dropdown or ANYWHERE. Applied by Google. |
adFormat | select | ALL | TEXT / IMAGE / VIDEO. Applied by Google. |
lastShownAfter | date | — | Still live on or after this date; shortens paging. |
firstShownAfter | date | — | Launched on or after this date; per row. |
| 📦 Output shape | |||
includeRegionDetail | boolean | false | +1 request per ad: regionsShown, variations, videoUrl. Same price. |
enrichAdvertiserContacts | boolean | true | Open the advertiser's site for email / phone / socials. Success-billed. |
onlyNewAds | boolean | false | Monitor mode — only creatives never delivered before. |
monitorStoreName | string | google-ads-transparency-monitor | One memory per watch. |
| 💷 Limits & cost | |||
maxAdsPerTarget | integer | 40 | Per domain / advertiser / name. 40 = one request. |
maxItems | integer | 200 | Your hard cost ceiling. You are never charged for more than this many rows — a run may stop short of it. |
| ⚙️ Advanced | |||
proxyConfiguration | proxy | Apify proxy (datacenter) | Not walled; datacenter by design, one capped RESIDENTIAL retry as the safety net. |
Pricing
$0.002 per ad returned — $2 per 1,000 — plus $0.03 per advertiser contact found. No start fee, no monthly fee from this Actor.
| Run | Ads | Contacts | Cost |
|---|---|---|---|
| The shipped default (HelloFresh, US) | 40 | 1 | $0.11 |
| One competitor, full US creative set | 1,000 | 1 | $2.03 |
| Ten competitors × 200 ads, all with a site contact | 2,000 | 10 | $4.30 |
| Daily monitor, quiet day | 0 | 0 | $0.00 |
ad-scrapedis charged per unique creative delivered. An ad reached through two targets is billed once — duplicates are dropped oncreativeIdbefore billing. Rows removed by the date filters, the format filter or monitor memory are never pushed and never billed.advertiser-contact-foundis charged once per advertiser domain, only on success. A domain with nothing public is free, and a domain that appears under 500 ads is billed one contact, not 500.- Rows are charged as they are pushed (
Actor.pushData(rows, 'ad-scraped')), so at a spend cap you get whole rows and stop, never a half-billed dataset. A contact found after the cap is not attached and not billed. - Per-region detail and video resolution cost no extra money — only time.
Honest limits
- No ad copy for text ads. Google renders Search text ads as images; nothing on the
Transparency Center exposes the headline or description as text.
imageUrlis the snapshot. - No spend, no impressions, no landing-page URL. The public Transparency Center publishes
none of these for commercial ads (political ads are a separate, region-specific surface this
Actor does not target).
daysShownandregionsShownare the reach signals that exist. - Contact enrichment is domain-route only and measured 9 of 12 on big brands; small and mid-size advertisers publish contact details more readily, big brands hide them behind forms. A bot-walled homepage (Zillow, Lululemon on the datacenter rung) is a free miss.
- Brand-name search is only as good as Google's autocomplete. Use the domain when you have it.
videoUrlresolves for YouTube-hosted video ads only — 58% of a Nike sample; the rest are other preview formats and staynull.- Creative assets are linked, not downloaded.
imageUrlandpreviewUrlare Google-hosted URLs; this Actor does not re-host or store any creative. - No login, no cookies, no CAPTCHA solving. Everything read here is the public, logged-out Transparency Center and the advertiser's public website.
How it works, and what it cost to make reliable
The Transparency Center web app calls an un-authenticated RPC
(/anji/_/rpc/SearchService/SearchCreatives) with a form-encoded JSON body; this Actor calls
the same endpoint, 40 creatives per page, token-paginated, with the region and format filters
applied server-side. Per-region reach comes from LookupService/GetCreativeById; brand names
go through SearchService/SearchSuggestions. No browser, no rendering, no cookie jar — which is
why it runs in 256 MB.
Transport ladder, measured 2026-08-22 through Apify, fresh proxy session per call:
| Rung | Result |
|---|---|
| Direct, home IP | 200 with 40 creatives on the first probes — then HTTP 429 after the day's shared probing. Google rate-limits per IP. |
| Apify proxy, datacenter | 15 / 15 token-paginated pages, 40 creatives each, 600 unique / 0 duplicates, 0.4–1.3 s per page |
| Apify RESIDENTIAL + country US | 15 / 15, 600 unique / 0 duplicates, 0.8–6.5 s per page |
Because the per-IP limit is real, every call uses a fresh datacenter session, a 429 or an interstitial is retried on a new one, and a request that fails all three datacenter attempts gets one retry through RESIDENTIAL (capped at 30 per run so the worst case stays bounded). A page that fails every rung stops that target with a warning — nothing is invented and nothing unfetched is billed.
robots.txt on adstransparency.google.com returns 404 (no Disallow). The advertiser-website
crawl reads at most four pages per domain (homepage + up to three contact/about/imprint
pages), same-site links only, and stops at the first email found.
Duplicates — measured in both directions
| Walk | Creatives returned | Unique | Duplicates |
|---|---|---|---|
hellofresh.com, 15 contiguous pages, datacenter | 600 | 600 | 0.0% |
hellofresh.com, 15 contiguous pages, RESIDENTIAL | 600 | 600 | 0.0% |
| 3 domains × 200 ads, ANYWHERE | 600 | 600 | 0.0% |
Google's page token is stable, so a single walk repeats nothing. Duplicates do arise when
two targets overlap — a creative URL pasted alongside its own domain search, or a brand name
that resolves to an account already covered by a domain — and the Actor drops them on
creativeId before billing. Across runs, use monitor mode.
When a run stops early
This Actor never ends FAILED on a data condition; it stops cleanly and tells you why in the status message:
- Run time limit → the run stops early to stay inside it and the status message says so. Every request is clamped to the time remaining and none starts with under 8 s left.
- Your spend cap → the run stops cleanly and the status message says why.
- 0 rows → the message names the cause: nothing in that region / format / date window, nothing new since the last monitor run, or the RPC unreachable on every rung.
- Unknown brand name → a warning naming the query, with the advice to use the domain.
- Bad advertiser ID or URL → skipped with a warning; the rest of the run continues.
Who buys this
- Agencies and marketing SaaS prospecting advertisers — the row is an active Google
advertiser with a contact on it;
daysShownsorts the serious spenders from the testers. - Competitive-intelligence and creative teams — every creative a rival runs, by format and region, with A/B variations and the YouTube link, diffed week over week in monitor mode.
- Ad-tech, analytics and attribution vendors —
googleCustomerIdandadGroupIdlet you cluster a brand's accounts and campaigns without the brand's permission. - Market researchers sizing a vertical — run the domains of a category and count live creatives, regions and launch cadence per player.
- Brand and compliance teams — watch your own domain (and your resellers') for ads you did
not authorise;
regionsShownshows where they run.
FAQ
Does this need a Google account, a login or cookies? No. The Transparency Center is a public, logged-out surface; so is the advertiser's website.
Why is the advertiser name a company I have never heard of?
Google verifies the legal entity, not the brand. domain carries the brand.
Can I get the ad text? Not for Search text ads — Google serves them as images. Image and video ads come with a Google-hosted preview URL that renders the live creative.
How does the contact enrichment work, and what does it cost?
The Actor opens the advertiser's own site and reads the public email, tel: phone and social
links; role inboxes (sales@, info@) count, addresses on unrelated corporate domains are
discarded (free-mail boxes such as gmail.com are kept — for a small advertiser that often IS
the office inbox). $0.03 per domain, only when something was found.
Do I need a residential proxy? No. Datacenter held 15 / 15 on the sustained test and is the default; RESIDENTIAL is the automatic, capped fallback.
Will a run ever fail with zero rows? No. Zero rows ends SUCCEEDED with a status message naming the cause.
Legal & fair use
This Actor reads the public, logged-out Google Ads Transparency Center and the public websites of advertisers. It does not log in, does not solve or bypass any challenge, does not download or re-host creative assets, and collects business contact details only (no people lookups). You are responsible for complying with Google's terms and with how you use the data, including GDPR, PECR/CAN-SPAM and the rules on unsolicited B2B outreach in your jurisdiction.
Google and the Google Ads Transparency Center are trademarks of Google LLC. This Actor is not affiliated with, endorsed by, or connected to Google.
Feedback
Found a missing field or want a new filter? Open an issue on the Issues tab, and if the Actor earns it, a review on the Reviews tab helps other buyers find it.