Google Ads Archive: Ads Transparency Export
Pricing
from $0.26 / 1,000 results
Google Ads Archive: Ads Transparency Export
Export every ad an advertiser runs on Google, from the official Ads Transparency Center: creative image, first and last shown dates, format, and a link to the ad on Google. Any country, no API key.
Google Ads Archive
Export an advertiser's ads from Google's own Ads Transparency Center — text, image and video creatives — as clean JSON, CSV or Excel. No API key, no browser, no scraping code.
Google publishes this archive but gives it no API and no export button. This Actor turns it into a table.
What you get
One row per ad creative: Google's own format for it, the image and its pixel size where the creative has one, the dates it first and last ran, and a link back to the ad on Google so anything can be checked at source.
By default a run collects up to 100 ads per advertiser — large brands run
thousands, so raise maxAdsPerAdvertiser (or set it to 0) when you want the
full history, and watch the cost.
How to scrape Google ads by advertiser
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.
{"advertisers": ["Nike, Inc."],"region": "US","maxAdsPerAdvertiser": 100}
To pin an exact advertiser, pass its Google id instead:
{"advertisers": ["AR16735076323512287233"],"region": "GB"}
Competitor ad research and creative tracking
Because every row carries firstShown and lastShown, a single run tells you
which creatives a competitor is still running, which they retired, and how long
each has been live. Re-run it on a schedule and the diff is a creative-rotation
timeline.
Ads differ by country: an advertiser with thousands of ads in the US may have none in Germany. Set Region per market.
Input
| Field | Type | Default | Description |
|---|---|---|---|
advertisers | array | — | Advertiser names (Nike, Inc.) or Google advertiser ids (AR16735076323512287233). Required — with none set the run stops and charges nothing. |
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. A large advertiser can run thousands — Google reports 9,000-10,000 for Nike in the US alone — so this is the main cost control. 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, before Google throttles it. 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; the output table's stopReason row lists the six partial reasons (maxAdsPerAdvertiser, maxItems, maxRunSeconds, duplicatePage, repeatedToken, emptyPage). 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; the output table's stopReason row lists the six partial reasons (maxAdsPerAdvertiser, maxItems, maxRunSeconds, duplicatePage, repeatedToken, emptyPage). |
Output
{"advertiserId": "AR16735076323512287233","advertiserName": "Nike, Inc.","creativeId": "CR05576182909712203777","format": "text","formatCode": 1,"imageUrl": "https://tpc.googlesyndication.com/archive/simgad/10891172661046192318","imageWidth": 348,"imageHeight": 174,"previewUrl": null,"firstShown": "2022-11-30","lastShown": "2026-07-27","firstShownTimestamp": 1669820166,"lastShownTimestamp": 1785116984,"region": "US","regionCode": 2840,"creativeUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR05576182909712203777?region=US","scrapedAt": "2026-07-27T01:10:00+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, 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 firstShownTimestamp or lastShownTimestamp. Those rows are excluded from the date arithmetic above. |
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).
Cost
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 only when every advertiser was actually unreadable, with the reason in the status message.
Set maxAdsPerAdvertiser to bound a run before you start it — that is the field
that decides what a large advertiser costs.
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. Google's archive has no "all advertisers" view, so there is no way to sweep a whole category in one call.
- Ad counts, spend and impression ranges shown for political ads in some regions are not included — this Actor returns creatives.