Google Ads Transparency Scraper & Archive
Pricing
from $0.26 / 1,000 results
Google Ads Transparency Scraper & Archive
Export Google Ads Transparency Center creatives by advertiser and region, with formats, source links and shown dates. Optional rotation summaries and change feeds.
Pricing
from $0.26 / 1,000 results
Rating
0.0
(0)
Developer
Eli J
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
8 days ago
Last modified
Categories
Share
What you can export
Use this Google Ads Transparency Center scraper for advertiser research and creative archives. Supply advertiser names or IDs and a region to export ad creatives, available images, first/last shown dates and source links.
Keep full exports for comparison, or enable the optional creative-rotation summary. Shown dates describe Google's recorded observations; they do not independently prove that an ad is currently serving or has stopped.
How to export Google Ads Transparency data
- Put one or more advertiser names, or Google advertiser ids starting with
AR, inadvertisers. - Choose the
region. - Bound the run with
maxAdsPerAdvertiser,maxItemsandmaxRunSeconds, and leaveproxyConfigurationon. - Optionally turn on
includeRotationSummaryand setactiveWithinDays. - Start the run and export the dataset as JSON, CSV or Excel.
- Check the
ERRORSrecord, theROTATION_SUMMARYrecord when the add-on is on, and the log for other advertiser matches.
Two published tasks show this with Nike, Inc.:
- Export Nike's ads from the Google Ads Transparency Center runs Google Ads Archive for Nike, Inc. in the United States and returns up to 50 of its ads. It runs the saved input shown under Input.
- Summarize Nike Google ad creative rotation
exports up to 20 Nike ads in the US plus an opt-in
ROTATION_SUMMARYrecord. It runs the saved input shown under Input.
Pricing
How much does it cost to export Google Ads Transparency data?
This Actor charges three events. Result is one ad creative written to the
dataset. Creative rotation summary (add-on) is charged only when
includeRotationSummary is on, subject to the charge, write, skip and error
rules below. Actor Start is charged when the Actor starts running: one
event per GB of Actor memory, minimum one. The unit prices you pay depend on
your subscription plan; see the rates on the
current Pricing tab.
Result rows and an automatic, memory-scaled Actor Start event are charged
separately. No result charge without result rows. The automatic Actor Start
event still applies; an empty or failed run is not promised to be free. Failed
requests are never written to the dataset, so you are not charged a result row
for this Actor's errors. The creative-rotation summary lives in the run's
key-value store, not the dataset, and is charged once per summarized advertiser
only when includeRotationSummary is on and at least one collected row for that
advertiser carries both firstShownTimestamp and lastShownTimestamp. If the
record write fails after the charge, ERRORS says so under rotationSummaryWrite.
A spending-limit skip is recorded there under rotationSummarySkipped. A skip is
recorded under rotationSummaryUnknown when charged_count was unavailable and
event_charge_limit_reached was true, or was zero without
event_charge_limit_reached.
Passing the same advertiser twice — by name and by id, say — collects it once, so a duplicated list does not become a duplicated invoice.
A run whose advertisers exist but have no ads in that region finishes successfully with an empty dataset and an explanation in the log. So does a run where a name matches nothing: that is an answer, not a failure. A run fails when an input is invalid, or when every advertiser was actually unreadable, with the reason in the status message.
maxAdsPerAdvertiser caps each advertiser's result rows and so their result
charges; maxItems caps the whole run's rows. The Actor Start event and, when
includeRotationSummary is on, the per-advertiser summary event are charged
separately.
Input
| Field | Type | Default | Description |
|---|---|---|---|
advertisers | array | — | Advertiser names (Nike, Inc.) or Google advertiser ids (AR16735076323512287233). Required: an input without at least one advertiser, an empty list included, fails input validation, so the run does not start. |
region | string | US | US, GB, DE, IN, CA, AU or JP. For any other country pass Google's numeric region code (2000 + the ISO-3166-1 numeric country code). |
maxAdsPerAdvertiser | integer | 100 | Stop after this many ads per advertiser. This caps each advertiser's result rows and so their result charges. 0 means no limit. |
maxItems | integer | 0 | Stop the whole run after this many rows. 0 means no limit. |
maxRunSeconds | integer | 900 | Stop starting new pages after this many seconds. 0 disables the budget. |
maxRetriesPerRequest | integer | 8 | Retries when Google rate-limits a request; each one backs off and rotates the proxy IP. |
rotateAfterRequests | integer | 24 | Retire a proxy identity after this many requests. 0 disables proactive rotation. |
proxyConfiguration | object | Apify Proxy | Google rate-limits a single address with 429 during sustained reading, so leaving the proxy on is strongly recommended. |
includeRotationSummary | boolean | false | Opt-in add-on. When on, the run writes one per-advertiser creative-rotation summary to the ROTATION_SUMMARY key-value record (never the dataset) and charges the custom event advertiser-rotation-summary once per summarized advertiser that has at least one collected row carrying both firstShownTimestamp and lastShownTimestamp, then writes the record; a write that fails after the charge is reported under rotationSummaryWrite in ERRORS, a spending-limit skip under rotationSummarySkipped, and a skip under rotationSummaryUnknown when charged_count was unavailable and event_charge_limit_reached was true, or was zero without event_charge_limit_reached. coverage is complete only when Google returned no further page; see the Output table's stopReason row for every partial reason. Off: no summary and no add-on charge. |
activeWithinDays | integer | 7 | Look-back window in whole days from the instant this run started collecting (scrapedAt, shared by every advertiser so summaries are comparable). shownWithinWindow counts collected creatives whose lastShownTimestamp falls in that window, inclusive of the exact boundary. Minimum 1. coverage is complete only when Google returned no further page; see the Output table's stopReason row for every partial reason. |
changeFeed | boolean | false | Return only new, changed or ended creatives relative to baselineDatasetId. Off by default: existing rows and billing apply. |
baselineDatasetId | string | — | Read-only dataset resource selected by the caller, required when changeFeed is on. Use a previous export's default dataset id containing full ad rows for the same advertiser and region. No baseline is filled in automatically. |
Track changes since a previous export
Turn on changeFeed and select baselineDatasetId. The Actor reads that
dataset with READ permission under LIMITED_PERMISSIONS; it creates no
named storage. An empty dataset is valid and makes every observed creative
new. A missing reference, unreadable dataset, malformed row or duplicate
advertiser/region/creative identity fails before reading Google or billing
result rows. Supply full prior ad rows, rather than creative ids alone. Keep
the baseline dataset unchanged while the run reads it. A change-feed dataset
contains only differences, so use a full export as your next baseline.
The comparison key is (advertiserId, regionCode, creativeId); rows for
other advertisers or regions do not participate. Observable fields are
advertiserName, format, formatCode, imageUrl, imageWidth,
imageHeight, previewUrl, firstShown, lastShown,
firstShownTimestamp, lastShownTimestamp, region and creativeUrl.
scrapedAt is excluded so the new scrape time alone does not create a change.
For previewUrl, comparison ignores Google's responseCallback and htmlParentId rendering query values, which vary between otherwise identical creatives; emitted URLs retain their raw values.
Each emitted row is the existing ad row plus changeStatus and
baselineDatasetId. new means its key was absent from the baseline.
changed means at least one observable field differs; changedFields lists
those field names in the order above. Unchanged rows are omitted and carry
no result charge. ended preserves the baseline's last known ad fields,
including its old scrapedAt, and carries coverage: "complete" and
seenInCompleteScan: false: it was absent from a complete scan of Google's
archive, which does not prove the ad stopped serving.
Any stopReason or failed request suppresses ended for that advertiser;
baseline rows for another advertiser id or region never produce ended here.
If a scan returns zero creatives but that advertiser and region have baseline rows, the Actor suppresses all ended rows, logs their count and warns you to rerun.
Complete coverage requires successful natural pagination exhaustion;
an empty page with a next token or a duplicate/repeated page is partial.
Coverage and the stop reason are reported per advertiser in the log.
In change mode, maxAdsPerAdvertiser bounds current creatives scanned as
well as emitted rows; unchanged pages still advance pagination. maxItems
caps emitted rows across the run. Both limits apply to ended rows too;
the log counts ended rows withheld by a result cap and names the cap.
Use maxAdsPerAdvertiser: 0 for a complete scan, subject to the other stops.
Zero changes finish successfully with guidance in the log. Each emitted
change is an ordinary result row billed at the existing per-row price;
Actor Start and maximum-cost stopping still apply. includeRotationSummary
continues to summarize current creatives scanned, including unchanged ones,
with its existing add-on charge; ended rows never enter that summary.
Baseline access is grounded in Apify's
Actor permissions
contract: "they can access storages that users explicitly provide via the
Actor input" and "the run token is expanded to allow only the requested
operations on the selected storages". The
input-schema resource contract
defines a string dataset resource with resourcePicker and ["READ"].
Advertiser names and ids
Put one or more advertiser names in Advertisers and run it. A name is
resolved against Google's own advertiser directory and the closest match is
used; when a brand has several registered entities the alternatives are listed
in the log so you can switch to an exact id. To pin an exact advertiser, pass
its Google id, such as AR16735076323512287233, instead of a name.
Saved inputs of the published tasks
Export Nike's ads from the Google Ads Transparency Center
{"advertisers": ["Nike, Inc."],"region": "US","maxAdsPerAdvertiser": 50,"maxItems": 0,"maxRunSeconds": 900,"maxRetriesPerRequest": 8,"rotateAfterRequests": 24,"proxyConfiguration": {"useApifyProxy": true}}
Summarize Nike Google ad creative rotation
{"advertisers": ["Nike, Inc."],"region": "US","maxAdsPerAdvertiser": 20,"includeRotationSummary": true,"activeWithinDays": 30,"maxItems": 0,"maxRunSeconds": 900,"maxRetriesPerRequest": 8,"rotateAfterRequests": 24,"proxyConfiguration": {"useApifyProxy": true}}
Output
{"advertiserId": "AR16735076323512287233","advertiserName": "Nike, Inc.","creativeId": "CR01416500074149576705","format": "text","formatCode": 1,"imageUrl": "https://tpc.googlesyndication.com/archive/simgad/16848047578975485832","imageWidth": 380,"imageHeight": 219,"previewUrl": null,"firstShown": "2022-11-30","lastShown": "2026-10-06","firstShownTimestamp": 1669819797,"lastShownTimestamp": 1791309134,"region": "US","regionCode": 2840,"creativeUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR01416500074149576705?region=US","scrapedAt": "2026-10-06T18:11:33+00:00"}
That row is a real one, taken verbatim from a live run. Note it: a text ad
that carries an image. That is normal, and it is why you should filter on
format rather than on whether imageUrl is set.
format is Google's own classification, read from the format code it
returns, not inferred from what the creative happens to contain:
formatCode | format |
|---|---|
1 | text |
2 | image |
3 | video |
Anything else is reported as other with the raw formatCode kept, so a new
Google format arrives visible rather than silently mislabelled. Do not infer the
format from whether a row has an image: text ads carry images too, so
filtering on imageUrl returns search ads alongside display ones.
Dates. firstShown and lastShown are the UTC date of the instants Google
returns. Those instants are not midnight boundaries, so a reader in another
timezone may want a different calendar date — firstShownTimestamp and
lastShownTimestamp carry the raw epoch seconds for exactly that.
previewUrl is Google's own preview endpoint for the creative. It is a
script payload meant to be embedded by Google's viewer rather than a standalone
page, so treat it as an identifier for the creative rather than a link to hand
to a browser. imageUrl and creativeUrl are ordinary URLs.
Key-value store. Failed requests are recorded on the ERRORS key, never as
dataset rows. When includeRotationSummary is on, ROTATION_SUMMARY is a JSON
list with one object per summarized advertiser. Those objects are not dataset
rows and are not billed as results. Each object carries:
| Field | Definition |
|---|---|
advertiserId | Resolved Google advertiser id for this object. |
advertiserName | Display name Google returned for that id. |
creativesCollected | Count of creative rows collected for this advertiser in this run. |
byFormat | Count of those rows per Google format (text / image / video / other). |
earliestFirstShown | UTC date of the smallest firstShownTimestamp among rows that have one. |
latestLastShown | UTC date of the largest lastShownTimestamp among rows that have one. |
medianRunDays | Median of (lastShownTimestamp - firstShownTimestamp) / 86400 over rows that have both timestamps. An even count uses the average of the two middle values. |
longestRunningCreative | {id, days} for the row with the largest (lastShownTimestamp - firstShownTimestamp) / 86400; a tie goes to the lexicographically smaller creativeId. |
shownWithinWindow | Count of rows whose lastShownTimestamp is within activeWithinDays days of this run's scrapedAt, inclusive of the exact boundary (lastShownTimestamp >= scrapedAt minus windowDays). Not a count of "active ads" except under that window. |
windowDays | The activeWithinDays value used for shownWithinWindow. |
scrapedAt | The instant this run started collecting, as UTC ISO-8601 with seconds, shared by every advertiser in the run so summaries are comparable. The window cutoff is measured from that instant. |
coverage | complete only when this advertiser's walk ended because Google returned no further page; otherwise partial (including a duplicatePage, repeatedToken, or emptyPage stop). |
stopReason | Present when coverage is partial: maxAdsPerAdvertiser, maxItems, maxRunSeconds, chargeLimit (the maximum cost you set for the run was reached), duplicatePage (a page held only already-collected creatives), repeatedToken (Google repeated a pagination token), or emptyPage (an empty page that still carried a next token). |
rowsWithoutDates | Count of collected rows missing a usable firstShownTimestamp or lastShownTimestamp. These rows are excluded from medianRunDays and longestRunningCreative; an available first or last timestamp still contributes to earliestFirstShown or latestLastShown, respectively, and an available last timestamp can count toward shownWithinWindow. |
ERRORS is a JSON list of handled failures. Each object names the input
advertiser and one of notFound, error, rotationSummaryCharge (the
add-on charge raised; base rows for that advertiser were still delivered),
rotationSummarySkipped (the spending limit was reached before this summary
could be charged; base rows were still delivered), rotationSummaryUnknown
(charged_count was unavailable and event_charge_limit_reached was true,
or charged_count was 0 and event_charge_limit_reached was not reported;
the summary was not written and base rows were still delivered) or
rotationSummaryWrite (the summary was charged but its record write failed;
base rows were still delivered).
Related Actors
| Actor | Research fit | What it exports |
|---|---|---|
| Kalshi Weather Markets | Price History API | Weather-market price history | Hourly or daily candles for named Kalshi weather markets: prices, bids, asks, volume and open interest as exact decimal strings |
| UFCStats Scraper | Fight & Round Statistics | UFC fight statistics | UFCStats fight and round statistics as flat rows with fighter IDs, event dates and locations |
| Tennis Abstract Scraper | Match History API | Tennis match statistics | ATP and WTA player match histories from Tennis Abstract: scores, opponents, surfaces and available serve and return statistics |
| Google Trends Scraper | Keyword Data API | Search-interest research | Google Trends interest over time, interest by region and related or rising queries, plus the Trending Now board by country |
| Clutch Agency Scraper | B2B Directory Export | Agency research and lead generation | B2B agency listings from Clutch.co directories: company names, websites, locations, headcounts and service mix |
FAQ and support
How do I export an advertiser's ads from the Google Ads Transparency Center?
Put the advertiser's name or Google id in advertisers, choose the region,
and set maxAdsPerAdvertiser (see Input). Then export the run's dataset as
JSON, CSV or Excel. The
Export Nike's ads from the Google Ads Transparency Center
task shows one such input.
How do I summarize an advertiser's Google ad creative rotation?
Turn on includeRotationSummary. The summary is a ROTATION_SUMMARY
key-value record, not dataset rows, and it is charged once per summarized
advertiser under the rules in Pricing. Each summary covers only the rows
collected for that advertiser in that run, so a walk stopped by
maxAdsPerAdvertiser has coverage partial with that stopReason (see
Output). The
Summarize Nike Google ad creative rotation
task shows the add-on turned on.
Do first and last shown dates show that an ad is still running?
No. firstShown and lastShown are the UTC dates of the first and last shown
instants Google returned when the run read the creative, so they give each
collected creative's shown span, not its serving status. A recent lastShown
does not prove the ad is still shown, and an older one does not prove it
stopped. With the add-on, shownWithinWindow counts rows last shown within
activeWithinDays days of the summary's scrapedAt. This Actor cannot show
ads Google has removed.
How do I pick the exact advertiser?
A name is resolved to the closest match, and up to three other matches are
listed in the log. To pick precisely, pass the advertiser's Google id instead.
A name or id Google does not list is recorded as notFound in ERRORS, not as
a failed run. One advertiser reached by both name and id is collected once.
Do I need a Google API key?
No. This Actor takes no Google API key. Calls to the Actor through the Apify API use your Apify API token.
Why did I get fewer ads than expected?
- With
changeFeedon, unchanged creatives are omitted; see Track changes since a previous export. maxAdsPerAdvertiserstops each advertiser at 100 ads by default.maxItemsstops the whole run after that many rows.maxRunSecondsstops new pages and new advertisers once the budget is spent.- A maximum cost you set for the run does the same once it is reached: the run stores no further rows, reads no further pages or advertisers, ends normally, and the log says how many ads were delivered.
- A walk can stop early on
duplicatePage,repeatedTokenoremptyPage(see Output). - Ads differ by region, so an advertiser may have fewer or no ads in the
regionyou chose. - A name or id Google does not list is recorded as
notFoundinERRORS. - An advertiser whose ads could not be read is recorded under
errorinERRORS. - Only ads Google still retains are listed.
- When every advertiser was unreadable, the run fails with the reason in the status message.
Notes and limits
- Only advertisers Google has verified appear in the Transparency Center, and only ads Google still retains are listed. This Actor reports what that archive contains; it cannot show ads Google has removed.
- An advertiser must be specified. This Actor has no all-advertisers or category mode, so it cannot sweep a whole category in one run.
- Ad counts, spend and impression ranges shown for political ads in some regions are not included — this Actor returns creatives.
Support
For bugs or questions, open an issue on the Issues tab of this Actor's page.