Google Ads Transparency Center API & Scraper
Pricing
from $0.32 / 1,000 creatives
Google Ads Transparency Center API & Scraper
Google Ads Transparency scraper and API: every ad a competitor runs, by name, domain, AR id or pasted URL, no login or API key. Search, YouTube, Shopping, Maps and Play ads with decoded headline, description, image, YouTube id, dates, EU impression bands and political spend. Pay per creative.
Pricing
from $0.32 / 1,000 creatives
Rating
0.0
(0)
Developer
Automation Craft
Maintained by CommunityActor stats
0
Bookmarked
52
Total users
20
Monthly active users
1.1 hours
Issues response
10 days ago
Last modified
Categories
Security
Limited permissionsShare
Google Ads Transparency Scraper - Decoded Creatives
Scrape the Google Ads Transparency Center for any advertiser and get every creative back with the copy decoded: headline, description, call to action, display and landing URLs, image, YouTube video id, first and last shown dates, days served, served regions, EU impression bands and political spend. No login, no cookies, no API key. Pay per creative; creatives your memory already knows are free.
Google publishes the ads of every verified advertiser at adstransparency.google.com, but the site is built for browsing one advertiser at a time and hides the ad copy inside a rendered preview. This Actor calls the same endpoints the site uses, pages through an advertiser's creatives at 100 per request, decodes the preview payloads and returns flat rows you can filter, schedule and export.
Quick start
- In Advertisers, enter a website domain (
nike.com), an advertiser name, an AR id, or paste a Transparency Center URL. One line per advertiser. - Pick a Region (or leave Anywhere), and any Platforms, Formats or date window. Filter by platform (Google Search, YouTube, Shopping, Maps, Play) and format (text, image, video), or leave both empty for every creative.
- Set Max creatives per advertiser and Max creatives per run.
- Keep Decode creatives on to get the copy, media and EU data; turn it off for metadata and preview URLs only.
- Run. Rows land in the dataset (JSON, CSV, Excel, API). For a scheduled competitor watch, set a Memory name and every later run returns only new creatives.
What you get
One row per creative. The columns in the table view are the ones most people use; the JSON row carries everything.
Measured on 180 live creatives (2026-09-22); percentage of rows where the field is filled.
| field | text ads | image ads | video ads |
|---|---|---|---|
headline | 73% | 0% | 43% |
description | 73% | 0% | 38% |
callToAction | 0% | 5% | 43% |
displayUrl | 73% | 0% | 37% |
landingUrl | 0% | 27% | 0% |
businessName | 7% | 0% | 37% |
storeLocations | 62% | 0% | 0% |
productTitle | 0% | 27% | 0% |
merchantName | 0% | 27% | 0% |
imageUrl | 72% | 92% | 50% |
youtubeVideoId | 0% | 0% | 52% |
videoUrls | 0% | 0% | 18% |
appName | 0% | 0% | 7% |
firstShown | 100% | 100% | 100% |
lastShown | 100% | 100% | 100% |
daysServed | 100% | 100% | 100% |
regionStats | 100% | 100% | 100% |
payerName | 47% | 70% | 57% |
category | 0% | 23% | 0% |
| field | meaning |
|---|---|
advertiserName, advertiserId, advertiserRegion, advertiserVerified, payerName | the advertiser as Google verified it, its AR id, home region, verification flag and the legal payer name from the creative detail |
creativeId, format, transparencyUrl, previewUrl | Google's CR id, TEXT / IMAGE / VIDEO, the link to the creative in the Transparency Center, the raw preview URL |
headline, description, callToAction, displayUrl, businessName, businessCategory, storeLocations, phone | decoded search, local and companion copy; location extensions with store name, address and city |
ocrStatus, ocrConfidence, ocrText, ocrLanguage, sitelinks | with OCR on: how the render was read, the recognition confidence, the full recognised text, the language pack used, the sitelinks visible in the render |
productTitle, merchantName, offerId, landingUrl, cssPartner | Shopping creatives: product, merchant, GTIN or offer id, product landing URL, comparison shopping partner |
appName, appId, appIconUrl, developerName | App install creatives (Google Play) |
imageUrl, imageUrls, width, height | the creative image (Google's archived render for text ads, the display image otherwise) and its size |
youtubeVideoId, youtubeUrl, videoUrls | video creatives: YouTube id and watch URL where the rendering embeds YouTube; signed playback URLs (they expire within hours, fetch what you keep) |
firstShown, lastShown, daysServed, servedCountries, matchedDomain | dates as ISO timestamps, number of days served, ISO country codes the creative was shown in |
regionStats, eeaImpressions, usImpressions | EU transparency: per region impression bands with per surface breakdown (Search, YouTube, Shopping, Maps, Play) and dates; aggregate EEA and US bands |
impressionsLower, impressionsUpper, spendLower, spendUpper, spendCurrency, targeting, politicalRegions | political ads: impression and spend ranges, age, gender and location targeting, audience selection categories |
category, vertical, containsSyntheticMedia | topic provided by the advertiser, vertical, Google's synthetic media disclosure |
isNew, memoryStatus, decodeStatus, decodeSources, query, scrapedAt | provenance: memory result, how the row was decoded (detail, overlay, bundle), which input line produced it |
A run-summary row closes every dataset: per advertiser requested, found (Google's size band), delivered, known skipped, pages fetched and stop reason; decode statistics; request counts and proxy mode; charges attempted and confirmed; memory state.
Sample creative row:
{"type": "creative","advertiserName": "株式会社ナイキジャパン","advertiserId": "AR01437837420136497153","advertiserRegion": null,"advertiserVerified": true,"payerName": "株式会社ナイキジャパン","creativeId": "CR15429817122099822593","format": "TEXT","headline": "【ナイキ公式】オンラインストア","description": "季節のオススメやベストセラー、クリアランスが勢揃い。ジブンだけのカスタマイズも。","displayUrl": "nike.com","businessName": "ナイキジャパン","imageUrl": "https://tpc.googlesyndication.com/archive/simgad/13803053261096263349","imageUrls": ["https://tpc.googlesyndication.com/archive/simgad/13803053261096263349","https://tpc.googlesyndication.com/archive/simgad/1021467459010002479","https://tpc.googlesyndication.com/archive/simgad/3595071776370173829"],"storeLocations": [{"name": "Nike Factory Store","address": "土岐ヶ丘1丁目2, 土岐プレミアムアウトレット 210","city": "土岐市","region": "岐阜県","postalCode": "509-5127","country": "JP"}],"width": 380,"height": 400,"firstShown": "2025-08-04T07:03:47.000Z","lastShown": "2026-09-22T14:16:58.000Z","daysServed": 415,"matchedDomain": "nike.com","categoryId": 10021,"impressionsLower": null,"impressionsUpper": null,"spendLower": null,"spendUpper": null,"spendCurrency": null,"regionStats": [{"region": "KR","impressionsLower": null,"impressionsUpper": null,"firstShown": null,"lastShown": "2026-09-17","dataAvailableFrom": null,"surfaces": []},{"region": "JP","impressionsLower": null,"impressionsUpper": null,"firstShown": null,"lastShown": "2026-09-22","dataAvailableFrom": null,"surfaces": []}],"targeting": {"age": null,"gender": null,"geoCriteriaIds": null,"audienceSelection": {"demographics": {"included": true,"excluded": false},"geographicLocations": {"included": true,"excluded": false},"contextualSignals": {"included": true,"excluded": true}}},"politicalRegions": null,"reportedByUser": false,"previewUrl": "https://tpc.googlesyndication.com/archive/simgad/13803053261096263349","transparencyUrl": "https://adstransparency.google.com/advertiser/AR01437837420136497153/creative/CR15429817122099822593?region=anywhere","variantCount": 4,"creativeType": 102,"decodeStatus": "decoded","decodeSources": ["detail","bundle"],"isNew": true,"memoryStatus": "NO_MEMORY","query": {"input": "nike.com","kind": "domain","value": "nike.com","region": "ANYWHERE","format": "all"},"scrapedAt": "2026-09-22T14:52:07.041Z"}
How much does it cost to scrape the Google Ads Transparency Center?
Pay per event, nothing per month. The Store card shows the same prices per 1,000 events.
| event | price | when it is charged |
|---|---|---|
| Creative | $0.40 per 1,000 | one creative row delivered (Silver 10 percent off, Gold 20 percent off) |
| Creative decoded | $0.30 per 1,000 | the detail and rendering decoded on top of a creative row, only when the decode returned data (same tiers) |
| OCR read | $0.50 per 1,000 | with "Read image-only text ads (OCR)": the copy read out of a text ad Google publishes only as an image, only when a headline was recognised (same tiers) |
| Actor start | $2.50 per 1,000 runs (0.25 cents per run) | once per run, so a monitoring run that finds nothing new costs a fraction of a cent |
Worked example: 1,000 decoded creatives of one advertiser cost $0.70 plus one start fee. A weekly watch of five competitors that finds 40 new creatives costs 40 x ($0.40 + $0.30) / 1,000 plus the start fee, about 4 cents. Known creatives, filtered rows, run summaries and status rows are free; a failed run costs its start fee and whatever it charged before it failed.
Input
| field | notes |
|---|---|
advertisers | domains, names, AR ids or pasted adstransparency.google.com URLs (advertiser page, ?domain= search, or one creative). Names are resolved through Google's own suggestions; a domain is the most exact key. |
region | one of 244 regions or ANYWHERE |
platforms | search, youtube, shopping, maps, play (empty = all) |
formats | text, image, video (empty = all) |
lastShownAfter, lastShownBefore | YYYY-MM-DD, applied by Google |
topic | all or political |
sort | lastShown (default) or impressions |
maxCreativesPerAdvertiser, maxTotal | caps; the run summary says why each advertiser stopped |
decodeCreatives | on in the Console by default, off for API callers who do not send it |
ocrImageOnlyText | read image-only text ads with the built-in OCR engine (needs decodeCreatives and a run memory of 512 MB or more); off by default |
memoryName, emitKnown, resetMemory | cross-run memory |
concurrency | advertisers paged in parallel (1 to 8) |
proxyConfiguration | Apify datacenter by default with automatic residential fallback for the small RPC calls |
stopOnFirstRefusal, disableResidentialFallback, directCreativeLookup | Advanced switches, all off by default; read "Advanced options" below before turning one on |
API example:
curl -X POST "https://api.apify.com/v2/acts/automation_craft~google-ads-transparency-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"advertisers": ["nike.com"], "region": "US", "maxCreativesPerAdvertiser": 200, "decodeCreatives": true}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation_craft/google-ads-transparency-scraper').call({ advertisers: ['nike.com'], platforms: ['youtube'], formats: ['video'], maxCreativesPerAdvertiser: 100, decodeCreatives: true, memoryName: 'weekly-watch' });const { items } = await client.dataset(run.defaultDatasetId).listItems();
from apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("automation_craft/google-ads-transparency-scraper").call(run_input={"advertisers": ["nike.com"], "lastShownAfter": "2026-09-01", "decodeCreatives": True})items = client.dataset(run["defaultDatasetId"]).list_items().items
Advanced options (read before turning one on)
Three switches sit in the input's collapsed Advanced section. All are off by default, and an input that does not mention them runs exactly as before. They exist for callers who need a strict access policy; each one trades data for it.
How a normal run treats refusals. Google answers a burst of requests from one IP with HTTP 429, a redirect to its "unusual traffic" page, or a silent empty answer. A clean IP serves about 40 to 50 requests before that, and Apify's shared datacenter pool holds IPs other users already got refused. So by default every worker keeps one datacenter session for up to 30 requests, moves to a fresh session on any refusal (up to 12 tries per request), and when the datacenter pool keeps refusing, moves the small list and detail requests to Apify residential IPs. Rendering files (where YouTube ids and rendered copy come from) only ever go over datacenter.
| switch | what it does | what you lose |
|---|---|---|
stopOnFirstRefusal | The whole run uses one proxy session (one IP), never rotates and sends one request at a time (concurrency is 1), so no other request is in flight when a refusal arrives. The first HTTP 403 or 429, redirect of any kind, unusual traffic page, answer that is not Google's data, or silent block (an empty answer where Google promised more ads) stops the run: that request is not retried, no other IP is tried, no residential IP is ever used, and nothing more is requested. A platform restart of the run keeps the stop. A RESIDENTIAL group selected in the proxy settings is replaced by the Apify datacenter proxy for the run (a warning says so). A status row, the run summary (stoppedOnRefusal) and the run's status message name the refused request. Creatives of a page already read are still delivered and charged as creatives; their decode stops there (decodeStatus: stopped_on_refusal, not charged), except that a decode which had already added data before the stop (for example the detail's copy) keeps decoded and is charged as usual. Server errors and network timeouts are retried at most three times on the same IP. | Runs can stop early: it depends heavily on the hour: on 2026-10-22 in the morning 1 of 25 strict test runs on Apify datacenter stopped, and in the afternoon 21 of 23 stopped on their very first request (Google sent 12 of 12 fresh datacenter sessions to its unusual traffic page at that hour), while runs with the switch off still finished by moving to fresh sessions. One request at a time makes large runs slower. An empty answer cannot be asked again from another IP, so a filtered query that answers empty is reported as unverified. One IP serves about 40 to 50 requests, so this suits a few single creatives, not a full advertiser crawl. |
disableResidentialFallback | A datacenter run stays on datacenter IPs: it still moves to fresh datacenter sessions after a refusal but never to residential. No effect with the RESIDENTIAL group, custom proxy URLs or the proxy turned off. | When the datacenter pool keeps refusing, the advertiser stops with stopReason: refused instead of finishing over residential. |
directCreativeLookup | A pasted single creative link (/advertiser/AR.../creative/CR...) is read with one detail request instead of paging the advertiser's ad list until the creative turns up: about two or three requests per link in all (advertiser name, detail, and the rendering file when decoding). The row's query.lookup says direct. Applies without a region, platform, political topic or "shown before" filter; with one of those the link is paged as usual and the run summary says why. | firstShown, daysServed and advertiserVerified are empty (Google's detail does not carry them), previewUrl is the detail's preview link rather than the list's, and an HTML5 ad has no static imageUrl (the list shows a fallback image the detail does not carry). On the YouTube Ads listing the YouTube platform is preselected, so send "platforms": [] to look links up directly. Decoded fields (headline, description, images, YouTube id, EU data) come from the creative's own detail and first variation, which can differ from the variation the list shows: on 8 video ads probed both ways the YouTube id matched on 7, and the direct lookup found one where the list's variation had none. |
For a strict lookup of a few known ads, combine them: paste the creative links, turn on Decode creatives, Look up pasted creative links directly and Stop on the first refusal. With the proxy turned off as well ("proxyConfiguration": {"useApifyProxy": false}), requests leave from the run's own container IP; rendering files are only fetched over Apify datacenter, so video ads then come back without youtubeVideoId.
{"advertisers": ["https://adstransparency.google.com/advertiser/AR11154049584043393025/creative/CR04688698681874972673"],"decodeCreatives": true,"directCreativeLookup": true,"stopOnFirstRefusal": true}
What this Actor does NOT do
- Keyword search across commercial ads: the Transparency Center only searches ad text within political ads. Keywords are resolved to advertisers (what the website does).
- Read the copy out of image-only text ads unless you turn on "Read image-only text ads (OCR)": without it those rows carry the image URL and
decodeStatus: image_only. With it, about 8 percent of renders still come back without a headline (a product photo across the text, a truncated render, Google's placeholder templates) and are not billed. - Download media files: it returns image and video URLs; the signed video playback URLs expire within hours.
- Exact match counts for commercial searches: Google gives a size band (
foundLower,foundUpperin the run summary); political searches get exact counts. - Show impressions or spend for commercial ads outside the EU: Google publishes none. EU rows carry
regionStats; political rows carry spend and impression ranges. - Reach ads older than what Google keeps for an advertiser.
FAQ
Does the Google Ads Transparency Center have an API?
No public API exists. This Actor reads the same JSON endpoints the Transparency Center website calls, with no login, no cookies and no key, and bills per creative delivered. The BigQuery datasets Google publishes cover only political ads and, since 2025, EU ads.
How do I see all the ads a competitor is running on Google?
Put the competitor's website domain (the most exact match) or name in "Advertisers", leave the filters empty and set your caps. Every creative comes back with format, first and last shown dates, days served and, with "Decode creatives" on, the headline, description, image, YouTube id and EU impression bands.
Why do some text ads come back with an image but no headline?
Google publishes many text ads only as a rendered image (the "simgad" PNG you see in the Transparency Center). The Actor delivers that image URL and marks the row decodeStatus: image_only. Where Google also serves the rendering script, the copy is decoded and the row says decoded.
Can I filter by region, platform, format and date?
Yes, and every filter is applied by Google itself: region (244 regions), platforms (Search, YouTube, Shopping, Maps, Play), formats (text, image, video) and a shown-between date window. The run summary reports the size band Google gave for each query.
How do I monitor new Google ads automatically?
Set a "Memory name" and schedule the run. Creatives delivered under that name are remembered; every later run returns only the creatives you have not received yet, and known creatives are never charged again.
How does the OCR for image-only text ads work and how accurate is it?
Google publishes about a quarter of text ads only as a rendered PNG. With "Read image-only text ads (OCR)" on, the Actor runs the open source Tesseract engine inside the run (no key, no third party) on Google's own clean render, masks the logo and product photo, and recovers headline, description, display URL and sitelinks from the line layout. Measured on 66 live renders where Google also exposed the real copy: the headline was recovered on 92 percent of Latin-script renders; Japanese reads at about 90 percent per character. Every OCR row carries ocrConfidence, and a render with no real copy (Google's placeholder templates) is never billed.
Why does this Actor run with limited permissions?
Least privilege: it only needs its own dataset, its own key-value store and the Apify proxy. The cross-run memory is a named key-value store the Actor creates itself, so nothing outside its own storages is touched.
Can the Actor stop when Google refuses a request, without retries or residential proxies?
Yes, with the switches in the input's Advanced section, all off by default. "Stop on the first refusal" ends the run at the first HTTP 403 or 429, redirect to Google's unusual traffic page or silent block, on one IP for the whole run, with no retry, no rotation and no residential proxy. "Disable residential fallback" keeps a datacenter run on datacenter IPs. "Look up pasted creative links directly" reads a single creative link with one detail request instead of paging the advertiser. Each one trades data for a stricter behaviour; the README section "Advanced options" lists what you lose.
More data tools by Automation Craft
- Google Ads Library Scraper - Competitor Ads, No Login
- YouTube Ads Scraper - Video Ads by Advertiser
- Facebook Ads Library Scraper - Page Ads, No Login
- Meta Ad Library Scraper - All Placements, Filters
- Instagram Ads Library Scraper - Creatives, Video
- LinkedIn Ad Library Scraper
- Google Trends Scraper
- Google News Scraper
Changelog
- 0.3.0 (2026-10-23): Advanced input section with three opt-in switches (stop on the first refusal, disable residential fallback, direct lookup of creative links); the memory record is no longer written by the platform's periodic timer, so a late write can never land after another run took the memory.
- 0.2.0 (2026-09-23): OCR for image-only text ads (opt in, priced per read).
- 0.1.0 (2026-09-22): first release. Advertiser resolution by name, domain, id or URL; region, platform, format, date and topic filters applied by Google; decode of search, local, shopping, app and video creatives; EU impression bands; political spend; cross-run memory; per run ledger.