Google Ads Scraper - Ad Creatives, Images & Audience Targeting avatar

Google Ads Scraper - Ad Creatives, Images & Audience Targeting

Pricing

$1.20 / 1,000 creative delivereds

Go to Apify Store
Google Ads Scraper - Ad Creatives, Images & Audience Targeting

Google Ads Scraper - Ad Creatives, Images & Audience Targeting

Scrape every ad an advertiser runs from Google's Ads Transparency Center: one row per creative with its archived image, format, serving dates, countries, ad wording where Google keeps it readable, and EU audience targeting. Creatives Google holds no content for are never returned.

Pricing

$1.20 / 1,000 creative delivereds

Rating

0.0

(0)

Developer

My Smart Digital

My Smart Digital

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

Google Ads Scraper — every ad an advertiser runs, from the Ads Transparency Center

Reads the public Google Ads Transparency Center and returns one row per ad creative an advertiser has run, with the content Google actually holds for it: the archived image, the ad wording where Google keeps it readable, the serving period, the countries it ran in, and the audience targeting the advertiser had to disclose in Europe.

The one rule this actor follows

It never returns a row it cannot fill, and never writes a value it does not have.

Google's registry hands back a share of creatives it holds no image and no preview for. Returning them produces a dataset of identifiers and dates that cannot be used for anything — and you pay for them all the same. Here they are counted in the run summary and dropped.

Three measurements behind that sentence, all reproducible on your own runs:

Measured
Creatives returned with no image and no preview0 out of 140 delivered, across two advertisers
adText filled with a placeholder, a template or a fragment of markup0 — the field is either real ad wording or null
audienceTargeting returned as an empty object where Google published nothing0 — it is null, which does not mean "targeted nobody"

Same rule everywhere else: a column the registry never fills is not shipped at all rather than shipped empty. The exact placement (STATIC_GOOGLE_SEARCH, DYNAMIC_MAPS_PROMOTED_PIN and 68 others) is declared by the registry but never filled on the public endpoint — checked on 60 search results and 4 detail lookups — so this actor does not offer a placement column.

What you get

One dataset item per creative:

FieldWhat it is
advertiserId, advertiserNameThe advertiser as the registry names it
creativeIdGoogle's identifier for this creative
domainThe domain the ad points to
formatTEXT, IMAGE or VIDEO
imageUrl, imageWidth, imageHeightDirect URL of the archived image, when the creative has one — a downloadable visual, not a page to render
previewScriptUrlHow to render the creative, when it is served as a rendered preview instead of a still image
adTextThe wording of the ad, when Google keeps it as text rather than as a picture. null otherwise, never a placeholder
displayUrlThe URL shown in the ad, when the creative renders one
advertiserDisplayNameThe name shown in the ad, often more specific than advertiserName
adTextPartsEvery string the creative renders, in order, so nothing is lost by the mapping above
firstShown, lastShown, daysServedServing period, as YYYY-MM-DD
politicalRegionsRegions where the ad is registered as political, when applicable
advertiserUnverified, reportedByUserFlags the registry sets on the creative
creativeUrlLink back to the creative's page in the registry

Sample output

A real row, shortened (a text ad Booking.com ran across 11 countries):

{
"advertiserId": "AR02934798844673654785",
"advertiserName": "Booking.com",
"creativeId": "CR04485766038394241025",
"domain": "booking.com",
"format": "TEXT",
"imageUrl": null,
"previewScriptUrl": "https://displayads-formats.googleusercontent.com/ads/preview/content.js?...",
"adText": "Išsirinkite ir užsisakykite – geriausi kaimo turizmo sodybų pasiūlymai Lietuvoje...",
"displayUrl": "www.booking.com/",
"advertiserDisplayName": "Booking.com",
"firstShown": "2026-08-19",
"lastShown": "2026-09-06",
"daysServed": 18,
"advertiserUnverified": false,
"creativeUrl": "https://adstransparency.google.com/advertiser/AR02934798844673654785/creative/CR04485766038394241025",
"legalName": "Booking.com B.V.",
"countriesServed": 11,
"countries": ["IT", "ES", "HR", "LT", "PL", "CZ", "IE", "NO", "DE", "GR", "LV"],
"countryDetails": [
{ "country": "BE", "geoCriteriaId": 2056, "firstServed": "2023-10-03", "lastServed": "2026-09-05",
"impressionsLowerBound": 5000, "impressionsUpperBound": 6000, "dataAvailableFrom": null,
"bySurface": [
{ "surface": "SEARCH", "impressionsLowerBound": 5000, "impressionsUpperBound": 6000 },
{ "surface": "YOUTUBE", "impressionsLowerBound": null, "impressionsUpperBound": 1000 }
] }
],
"eeaImpressions": {
"impressionsLowerBound": 1250000, "impressionsUpperBound": 1500000,
"firstServed": "2023-10-02", "lastServed": "2026-09-05", "dataAvailableFrom": null,
"bySurface": [
{ "surface": "SEARCH", "impressionsLowerBound": 1250000, "impressionsUpperBound": 1500000 },
{ "surface": "YOUTUBE", "impressionsLowerBound": 25000, "impressionsUpperBound": 30000 }
]
}
}

With per-country details switched on

includeDetails adds one lookup per creative and fills six more fields:

FieldWhat it is
legalNameThe legal entity behind the advertiser — Booking.com B.V. where the search only says Booking.com
countriesServed, countriesNumber of countries and their two-letter codes
countryDetailsPer country: Google's geo criteria ID, first and last served dates, the impression bracket where Google publishes one, and its split across Google properties. Sparse by nature — measured on 152 country rows, a first-served date on 59 and an impression bracket on 30
eeaImpressionsHow many times the ad was shown across the EEA, as a bracket, split by Google property. See below
variantCount, variantUrlsEvery rendering of the creative, where the search returns only one (3 to 4 on the videos tested)
audienceTargeting, audienceTargetingSignalsSee below

Audience targeting, and what it really is

Google publishes this because the EU Digital Services Act requires it, which is what decides its coverage: creatives served in the European Economic Area carry it, the others do not. Measured on 32 creatives — 8 of 8 for a French advertiser, 7 of 12 for booking.com, 2 of 12 for salesforce.com. Where Google publishes nothing, the field is null.

Five signals, each with what the advertiser included and what it excluded: demographics, geography, contextual, topicOfInterest, advertiserList.

"audienceTargeting": {
"demographics": { "included": true, "excluded": false },
"geography": { "included": true, "excluded": false },
"contextual": { "included": true, "excluded": true },
"advertiserList": { "included": true, "excluded": false }
},
"audienceTargetingSignals": ["demographics", "geography", "contextual", "advertiserList"]

The registry also declares age, gender and geographic conditions next to these signals. They are never filled on the public endpoint, so nothing is shipped for them.

How many times the ad was shown

eeaImpressions is the volume the ad reached across the European Economic Area, plus its split between the Google properties it ran on: SEARCH, YOUTUBE, MAPS, PLAY, SHOPPING. Same disclosure duty as the targeting above, so it lands on exactly the same creatives — measured on 20 creatives across two advertisers, the two agree on all 20.

Google publishes brackets, never counts, and reading them takes two rules:

  • The two bounds are independent.
    { "impressionsLowerBound": null, "impressionsUpperBound": 1000 }
    is Google saying fewer than a thousand. It is a value, not a gap.
  • A recent ad has no bracket yet, and says when it will. dataAvailableFrom carries the future date Google will publish the figures on. Rather than an empty cell with no explanation, you get the date to come back on. Measured: 13 of the 16 disclosed creatives had their bracket, the other 3 a publication date.

The same six keys appear inside every countryDetails row, so the same volume is readable country by country as well as EEA-wide.

Input

FieldDefaultNotes
searchTermRequired. A domain such as booking.com, or an advertiser name
searchBydomainLook up by the domain the ads point to, or by advertiser name
maxResults40Up to 1000. Results are paginated 40 at a time
adFormatanytext, image or video. Filtering happens at the source, so formats you did not ask for are never fetched or charged
regions[]Google geo target IDs (2250 France, 2840 United States, 2826 United Kingdom)
servedFrom, servedToBounds on the serving period, YYYY-MM-DD
includeDetailsfalseAdds the per-creative lookup described above
{
"searchTerm": "booking.com",
"maxResults": 40,
"adFormat": "video",
"includeDetails": true
}

A RUN_SUMMARY record is written to the run's key-value store: creatives delivered, how many carried readable ad text, how many were skipped for having no content, pages fetched, and how many times Google rate-limited the run.

Limits, stated up front

  • Ad text is available on a minority of creatives, and the field is empty on the rest. Google archives most ads as a picture of themselves, with the wording baked into the pixels; only the creatives it keeps as a rendered preview carry readable text. Measured across two advertisers, that is around 15% of creatives — but every creative that carries a preview returns its text, and asking for the per-creative details does not raise the share: on 40 creatives archived as images, none gained readable text from the extra lookup. Reading the rest would require OCR, which this actor does not do.
  • Audience targeting and impression volumes depend on where the ad ran, for the reason given above. They are a European disclosure, not fields Google fills at random.
  • No exact placement, for the reason given above.
  • No US impression volumes. The registry declares the field next to the European one, and it came back empty on every creative tested. Nothing is shipped for it.
  • Rate limit. The registry caps requests per IP: roughly 40 calls in a row, then every endpoint returns "too many requests" for a few minutes. Requests are spaced out and retried with a growing delay rather than failing the run, so large runs are slower rather than broken.
  • Per-country details are capped at 200 creatives per run, because each one costs an extra request against that same rate limit.
  • No proxy and no login: the registry answers a plain server IP.

Creatives Google holds no content for are neither returned nor charged.