Google Ads Transparency Scraper - Ad Creatives · Apify
Google Ads Transparency Scraper avatar

Google Ads Transparency Scraper

Pricing

from $0.60 / 1,000 ads

Go to Apify Store
Google Ads Transparency Scraper

Google Ads Transparency Scraper

Google Ads Transparency Scraper extracts ad creatives from Google's Ad Transparency Center. Search by advertiser domain, advertiser ID, or name, filter by region and date range, and retrieve creative details including text, images, video previews, and show/hide dates.

Pricing

from $0.60 / 1,000 ads

Rating

0.0

(0)

Developer

Murat Uzun

Murat Uzun

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

18 hours ago

Last modified

Features

Limited permissions

Share

What does Google Ads Transparency Scraper do?

Google Ads Transparency Scraper lists the ads an advertiser runs on Google, straight from the public Google Ads Transparency Center. Give it a domain (nike.com), an advertiser ID (AR…) or an exact advertiser name. For each ad you get the creative ID, the advertiser, Google's format label (text, image or video), first and last shown day, the number of days shown, the rendered ad image, Google's preview link and a link to the ad in the Transparency Center.

Who it is for: marketers and agencies watching competitors' Google ads, sales teams checking whether a prospect advertises, and analysts tracking ad activity by country and period. Price: $1.00 per 1,000 ads on the Free plan ($0.80 Bronze, $0.70 Silver, $0.60 Gold and above), plus one $0.00005 Actor start event. Filtered-out, failed and empty results are never charged.

Filters are applied by Google, not after the fact. Country, date window and format are sent to Google with the search, so you get (and pay for) only matching ads, and the Actor pages through Google's results 100 at a time, up to 10,000 ads per advertiser.

Keep the creatives, not just links. With Save ad images every rendered ad image is downloaded into your run's storage under its creative ID, with size, SHA-256 and pixel dimensions on the row, at no extra charge. With a monitor store name, scheduled runs deliver and charge only ads you have not received before, so tracking a competitor costs only what is new. Turn on Also report ads that stopped running and each run also tells you which of the competitor's running ads went off air since the previous run (changeType: "stopped"), so you see what they launched and what they cut.

How to use it

  1. Open the Input tab and enter one or more advertisers separated by ; or new lines: domains (nike.com), Transparency Center IDs (AR16735076323512287233) or exact advertiser names (Nike, Inc.).
  2. Optionally pick a Region (2-letter country code), a date window and an Ad format.
  3. Set Max ads per advertiser and click Start. Each ad becomes one dataset row; a run summary is saved as OUTPUT.

Example input

{
"advertisers": "nike.com; AR16735076323512287233",
"region": "US",
"dateFrom": "2026-11-01",
"dateTo": "2026-11-13",
"format": "video",
"maxAds": 200
}

Input options

FieldDescription
advertisersDomains, AR… advertiser IDs or exact advertiser names, separated by ; or new lines. A URL such as https://www.Booking.com/ is reduced to booking.com. Empty input runs the demo advertiser nike.com.
region2-letter country code (US, GB, DE, TR, …; 250 codes). Empty = all regions.
dateFrom, dateToKeep ads shown at any time inside this window (YYYY-MM-DD).
formatall, text, image or video, as labelled by the Transparency Center.
maxAdsMost ads per advertiser, 1–10,000 (default 40).
downloadImagesSave each rendered ad image in the run's key-value store (default off).
monitorStoreNameName of a store that remembers delivered ads per advertiser and filter set; later runs deliver only new ads.
reportStoppedAdsWith a monitor store: also deliver ads that were running at the previous run and have stopped (default off). Not combinable with dateFrom/dateTo.
stoppedAfterDaysAn ad counts as stopped when Google has not shown it for this many days, today included (2–30, default 3).
proxyModeauto (default): direct first; when Google rate-limits the run's IP (HTTP 429/403) the rest of the run goes through Apify residential proxy at once. never: direct only. always: residential proxy from the first request. Proxy traffic is never charged to you.
domain, advertiserSingle-value aliases of advertisers.

Names are looked up in Google's own advertiser suggestions (the Transparency Center search box) and only advertisers whose name matches exactly, ignoring case and punctuation, are scraped. If none matches, the run lists Google's suggestions with their AR… IDs in OUTPUT and charges nothing. For brands, the domain is usually the best key.

Output

One row per ad:

{
"creativeId": "CR13013582080305528833",
"advertiserId": "AR06365026152670560257",
"advertiserName": "WPP MEDIA MANAGEMENT",
"domain": "nike.com",
"format": "video",
"firstShown": "2024-05-15",
"lastShown": "2026-09-28",
"daysShown": 854,
"regionCount": null,
"videoUrl": null,
"imageUrl": null,
"previewUrl": "https://displayads-formats.googleusercontent.com/ads/preview/content.js?client=ads-integrity-transparency&…",
"transparencyUrl": "https://adstransparency.google.com/advertiser/AR06365026152670560257/creative/CR13013582080305528833",
"searchedFor": "nike.com",
"scrapedAt": "2026-11-13T21:00:00.000Z"
}
  • format uses Google's own label. Text ads are archived by Google as a rendered image, so they usually have an imageUrl too.
  • regionCount and videoUrl are retained for backward compatibility and are always null: this response provides neither a verified region count nor a direct video URL. Field 13 remains daysShown; the preview script remains previewUrl.
  • daysShown is the number of days Google reports the ad was shown.
  • previewUrl is Google's preview script for the creative (mostly text and video ads); open transparencyUrl to view the ad.

With downloadImages the row also has imageKey, imageStoredUrl, imageBytes, imageSha256, imageWidth, imageHeight and imageError (NO_IMAGE when Google has no rendered image, e.g. most video ads; IMAGE_HTTP_ERROR, IMAGE_NOT_IMAGE, IMAGE_TOO_LARGE over 5 MB, IMAGE_NETWORK). A failed image never drops the ad row. With monitorStoreName, delivered rows carry newSinceLastRun: true and changeType: "new".

With reportStoppedAds, every run also reads all ads Google showed in the last stoppedAfterDays days (one complete pass, same region and format; not charged) and saves them as the running set in the monitor store. An ad that was running at the previous run and is missing now is delivered once as a row with changeType: "stopped", newSinceLastRun: false and its last known lastShown. The first run only saves the baseline. Stopped rows count toward maxAds after new ads; stopped ads that do not fit (or exceed the budget) stay in the store and come with the next run. Each advertiser in OUTPUT has stoppedCheck (BASELINE, DONE, INCOMPLETE, PAGE_LIMIT or TOO_MANY_ACTIVE), activeAds, stoppedAds and stoppedPending; the run totals are stoppedAds, stoppedPending, activeAds, stoppedBaselines and stoppedChecksIncomplete. An incomplete check keeps the previous running set, makes the run PARTIAL and is repeated by the next run.

In a live run on 13 Nov 2026 (nike.com, region US, 150 ads over 2 pages) every row had all then-reported fields except imageUrl (136 of 150) and previewUrl (14 of 150), which Google provides only for some creatives.

The OUTPUT record summarises the run: outcome (COMPLETE, PARTIAL, EMPTY or FAILED) with one reason code, ads delivered, advertisersRequested, advertisersWithAds, incompleteAdvertisers with incompleteByReason (for example {"BUDGET": 2} or {"RATE_LIMITED": 1}), failedAdvertisers (stopped by an error or the time limit, details in ERRORS) and notFoundAdvertisers, all counted per advertiser input line. connection says how Google was reached: mode, residential (true when requests went through the residential proxy), switchedAt, directRequests, proxiedRequests and proxySessions. The terminal status message repeats the same counts and reason, and says when Google rate-limited the direct connection and requests went through the proxy. It also lists the filters and, for every advertiser, the query type (domain, id, name), pages read, Google's approximate total, why it stopped and, for names, the resolved advertiser IDs or Google's suggestions.

Errors, empty results and run outcomes

Each advertiser's stoppedReason says why it stopped: MAX_ADS, LAST_PAGE (Google has no more ads), BUDGET (your maximum charge per run), DEADLINE (run time limit), NOT_FOUND (name without an exact match), ERROR or PAGE_LIMIT (Google repeated a page token or 500 pages were read). Problems are saved in the ERRORS record with an errorCode:

CodeWhereMeaningWhat to do
INVALID_INPUTrun failsUnknown country code, a date that is not YYYY-MM-DD, a reversed window, an unknown format, maxAds or stoppedAfterDays out of range, or reportStoppedAds without a monitor store or with a date windowFix the field named in the message; nothing was charged
TOO_MANY_ACTIVE_ADSadvertiser errorCode (stage STOPPED_CHECK)More than 5,000 ads ran in the last stoppedAfterDays days, too many to remember; new ads are still delivered, stopped ads are not checkedNarrow the region or format, or lower stoppedAfterDays
NO_ADS_FOUNDzeroResultReasonGoogle lists no ads for this advertiser with these filtersWiden the filters or check the domain
NO_NEW_ADSzeroResultReasonMonitor run: every ad Google listed was delivered in an earlier run (alreadySeenAds)Nothing; schedule the next run
MONITOR_SAVE_FAILEDadvertiser errorCode, OUTPUT reason for this failureThe monitor store could not be updated; the advertiser is incomplete. With delivered ads, OUTPUT is PARTIAL and the terminal explicitly reports the failureAds already delivered remain charged and may be delivered and charged again on the next run because the monitor history was not saved. Check the store failure before retrying
ADVERTISER_NOT_FOUNDzeroResultReasonNo advertiser has exactly this nameUse an AR… ID from the suggestions in OUTPUT, or the domain
RATE_LIMITEDadvertiser errorCodeGoogle answered HTTP 429/403 and three more tries failed (5 s, 15 s, 30 s apart): with proxyMode auto or always these tries go through the residential proxy, each on a new proxy IP; with never they come from the same IPRun again later or with fewer advertisers per run; keep proxyMode on auto
HTTP_ERRORadvertiser errorCodeGoogle rejected the request or failed (HTTP 4xx/5xx)Run again later; open an Issue if it repeats
BAD_RESPONSEadvertiser errorCodeGoogle answered with something that is not search dataRun again later
NETWORKadvertiser errorCodeThe request did not completeRun again later
DEADLINEzeroResultReason / advertiserThe run time limit came first; delivered ads are keptRaise the timeout or lower maxAds

When no advertiser delivered an ad because every one failed, the run is marked Failed with the error code; a run where Google simply has no matching ads succeeds and says NO_ADS_FOUND.

Pricing and cost example

You pay per ad delivered: $1.00 per 1,000 on Free, $0.80 Bronze, $0.70 Silver, $0.60 Gold and above, plus one $0.00005 start event per run. Example: 3 competitors × 200 ads = 600 ads = $0.60 on Free ($0.36 on Gold). A stopped-ad row is charged like any ad; the pass over running ads that finds them is free. Residential proxy traffic after a rate limit is paid by us, not added to your bill. Set Maximum cost per run in the run options; the Actor stops before it and reports BUDGET.

How it compares

Rival cells are what each Actor documents on its public Store page, price list and input schema, read on 12–14 Nov 2026 (scrapesage, solidcode, s-r); we did not run them. "Not documented" means we found no mention, not that the feature is missing. The free alternative is Google's own Transparency Center website.

Per 1,000 ads, same unit (one ad = one result)This Actorscrapesagesolidcodes-rTransparency Center website (free)
Price, Free plan$1.00$2.00$1.50$2.00$0, manual browsing only
Price, Gold plan$0.60$2.00$0.80$2.00$0
Country filterYes, sent to GoogleYes (region)Yes (region)Yes (region)Yes
Date windowYes, sent to GoogleYes (startDate)Yes (dateFrom)Yes (start_date, last shown)Yes
Format filterYes, sent to GoogleYes (adFormat)Not documentedYes (format)Yes
Platform filter (Search, YouTube, …)Not yetYes (platforms)Yes (platform)Yes (platform)Yes
More than 100 ads per advertiserYes, up to 10,000maxAdsPerSearch; paging not documentedYes, "up to 50,000"Yes, up to 1,000 (ads_count)Scroll in the browser
Ad image files saved in your storage (size, SHA-256, width, height)Yes (downloadImages)Not documented; image URL (imageUrl)Not documented; image URLs (imageUrl, previewUrl)Not documented; image URL (image_url)Save each image by hand
Deliver and charge only ads not received in earlier runsYes (monitorStoreName)Yes (onlyNewAds)Not documentedNot documentedNo
Report ads that stopped running since the last runYes (reportStoppedAds, changeType: "stopped")Not documented; onlyNewAds returns new ads only (checked 14 Nov 2026)Not documentedNot documentedCompare last-shown dates by hand
Ad text (headline, description)No; rendered image + preview linkYes (includeAdText)Not documentedYes (ad_text)Visible on screen
Export / APIDataset JSON, CSV, Excel, APIYesYesYesNo export

Run it from code

JavaScript (npm i apify-client):

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('webdatatools/google-ads-transparency-scraper').call({
advertisers: 'nike.com; adidas.com',
region: 'US',
maxAds: 200,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, items[0]);

Python (pip install apify-client):

from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("webdatatools/google-ads-transparency-scraper").call(
run_input={"advertisers": "nike.com", "region": "GB", "format": "image", "maxAds": 100}
)
for ad in client.dataset(run["defaultDatasetId"]).iterate_items():
print(ad["format"], ad["lastShown"], ad["transparencyUrl"])

CLI:

$apify call webdatatools/google-ads-transparency-scraper --input '{"advertisers": "nike.com", "region": "US", "maxAds": 50}'

Using it with AI agents and MCP

Add the Actor to the Apify MCP server (https://mcp.apify.com/?actors=webdatatools/google-ads-transparency-scraper) and ask your agent things like "List Nike's video ads shown in the US this month" or "Does example.com advertise on Google in Germany?". The agent receives the same rows and the OUTPUT summary, including the stop reason for every advertiser.

FAQ

Does it need a Google account or API key? No. It reads the public Transparency Center.

Why did a name return nothing? Names must match an advertiser exactly. Check the suggestions in OUTPUT and rerun with the AR… ID, or use the domain.

Why do text ads have an image? Google archives text ads as a rendered image; format still says text.

How do I track a competitor every week? Schedule the Actor with the same monitorStoreName and filters. The first run delivers up to maxAds ads and remembers them (use a high maxAds for a full baseline); each later run returns only ads not delivered before and says NO_NEW_ADS when there are none. Changing the region, dates or format starts a separate baseline.

How do I see which ads a competitor stopped? Add reportStoppedAds: true to the same scheduled monitor run. The first run saves which ads are running; every later run delivers the ones Google has not shown for stoppedAfterDays days (default 3, because Google updates the last-shown day with up to a day's delay). With a daily schedule and the default, an ad last shown on 10 Nov is reported by the 13 Nov run.

Where are the saved images? In the run's key-value store, one record per creative ID; imageStoredUrl on each row points to the file. Identical creatives share the same imageSha256.

Can I get ads from years ago? Google decides what the date filter returns. In our 13 Nov 2026 check, a January 2024 window returned no ads for nike.com in the US while recent windows did.

What changed in this version? New: reportStoppedAds reports ads that stopped running since the previous monitor run, and monitor rows carry changeType. When Google rate-limits the run's IP, the run moves to Apify residential proxy instead of failing (proxyMode, connection in OUTPUT). Earlier: format labels now match the Transparency Center (earlier versions mislabelled text, image and video), the region and date filters are applied by Google (before, the region was ignored and a date made Google reject the search), results page past 100. regionCount (field 13 is days shown, not regions) is now always null and kept only for compatibility — read daysShown; videoUrl (it held Google's preview script) is always null — read previewUrl.

Data and reliability limits

  • Google rate-limits bursts of requests from one IP address (HTTP 429/403) and can keep blocking that IP for hours: on 14 Nov 2026 a server IP still got Google's block page more than two hours after its first 429, and one run on Apify failed on its first request. That is why proxyMode auto moves the run to Apify residential proxy at the first 429/403 instead of waiting on the blocked IP. With never, the Actor waits 5, 15 and 30 seconds before giving up on an advertiser with RATE_LIMITED.
  • Domains are matched by Google exactly; the Actor lower-cases them because Google returned nothing for Booking.com but results for booking.com (13 Nov 2026).
  • Google reports only an approximate, rounded total per search (approxTotal, e.g. 50,000 for nike.com worldwide and 8,000 for the US on 13 Nov 2026).
  • Field meanings come from Google's internal Transparency Center API and were checked against the Transparency Center pages on 13 Nov 2026; Google can change them without notice.

Support and feedback

Found a wrong field or a missing ad? Open an Issue on this Actor's page with the run ID; we read every one. If the Actor saves you time, a short review on the Store helps other buyers find it.