Google Ads Scraper: Ad Copy & Click-Through Links
Pricing
$19.99/month + usage
Google Ads Scraper: Ad Copy & Click-Through Links
Google Ads Scraper: Ad Copy & Click-Through Links extracts SERP ad data—headlines, descriptions, URLs, sitelinks & advertiser domains—for any keyword. 🚀 Perfect for PPC research, competitor monitoring & ad copy insights. 📊 Export CSV/JSON, schedule runs & automate reports.
Pricing
$19.99/month + usage
Rating
0.0
(0)
Developer
ScrapeMesh
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
📝 Google Ads Scraper: Ad Copy & Click-Through Links
A Google Ads Transparency scraper that goes one step past the plain creative list: for every
listed ad it opens the ad's own preview document — the content.js render file every ad already
carries as previewUrl — and reads out the headline, description, long headline and call-to-action
button text, the click-through link the ad sends people to (with its display URL and click
tracker), and, when the preview says so, the app, video or shopping product the ad is promoting.
Give it a Google Ads Transparency profile URL or an advertiser ID. No login, no API key, no
cookies, no browser — one extra plain GET per ad, logged out, against a page Google already serves.
🔑 What it collects
| Capability | Detail |
|---|---|
| 📰 Ad copy | Headline, description, long headline and call-to-action, read from the ad's own rendered preview |
| 🎯 Click-through link | The exact destination_url the ad sends people to, plus its short display_url and the raw googleadservices.com/pagead/aclk click tracker |
| 🛍️ Promoted product | App-install ads: app name, store id, store, developer, category, blurb. Shopping ads: product item ids and ad-group id. Video ads: the YouTube video id, url, duration and thumbnail |
| ✂️ Ad-copy filter | Keep only ads whose preview actually gave up a headline or a link — Google renders text/search ads as flat pictures with none |
| 🔗 Destination filter | Keep only ads whose click-through link contains a domain, store or campaign-parameter string you name |
| 🧱 Everything the base collects | Ad Library URL, advertiser id/name, creative id, regions, first/last shown, format, preview URL, region statistics — unchanged |
📥 Input
| Field | Type | Default | What it does |
|---|---|---|---|
startUrls | array of strings, required | prefilled | Google Ads Transparency profile URLs or AR… advertiser IDs |
maxItems | integer 1-10000 | 10 | Max ad creatives to collect per advertiser. Counts rows that pass the filters below, not just listed creatives |
proxyConfiguration | object | direct | Proxy settings for the listing request |
openAdPreviews | boolean | true | Open each ad's own preview and read its copy and click-through link. One extra request per ad with a preview |
onlyAdsWithAdCopy | boolean | true | Keep only ads whose preview gave up a headline or a link. Off = keep every ad, with nulls where Google published nothing |
destinationDomainFilter | array of strings | [] | Keep only ads whose click-through link contains one of these strings (shop.example.com, play.google.com, utm_source=). Empty = keep everything |
includePromotedProduct | boolean | true | Also return the app / video / shopping-product record when the preview carries one |
Example input
{"startUrls": ["https://adstransparency.google.com/advertiser/AR04619580580634296321"],"maxItems": 20,"openAdPreviews": true,"onlyAdsWithAdCopy": true,"destinationDomainFilter": ["play.google.com"],"includePromotedProduct": true,"proxyConfiguration": { "useApifyProxy": false }}
📤 Output
One row per ad creative. Every base field is reproduced unchanged, in base order, base shape and
base value — including the base's own known quirks (see Limits below). Every added field is
present on every row for a stable shape, null (or [] for the array fields) when Google's preview
didn't carry it.
{"adLibraryUrl": "https://adstransparency.google.com/advertiser/AR04619580580634296321/creative/CR02562382857502720001","advertiserId": "AR04619580580634296321","advertiserName": "Pokemon Co., Ltd.","creativeId": "CR02562382857502720001","creativeRegions": ["Region 137"],"firstShown": "2026-04-01","format": "VIDEO","lastShown": "2026-08-15T06:46:35.069986Z","previewUrl": "https://displayads-formats.googleusercontent.com/ads/preview/content.js?...","regionStats": [{ "regionCode": "137", "regionName": "Region 137", "firstShown": "2026-04-01","lastShown": "2026-08-15", "impressions": { "lowerBound": 0, "upperBound": 1000 } }],"adHeadline": null,"adDescription": null,"adLongHeadline": null,"adCallToAction": "INSTALL","destinationUrl": "https://play.google.com/store/apps/details?id=jp.pokemon.pokemonsleep","displayUrl": "play.google.com/store","finalUrl": null,"clickTrackerUrl": "https://www.googleadservices.com/pagead/aclk?sa=L&ai=C5w5Q...","hasAdCopy": true,"promotedApp": {"appName": "Pokémon Sleep", "shortAppName": "Pokémon Sleep","appId": "jp.pokemon.pokemonsleep", "appStore": "2", "appStoreName": "Google Play","developer": "The Pokémon Company", "appCategory": "GAME_SIMULATION","shortDescription": "Track your sleep with a smart device to discover adorable Pokémon sleep styles!"},"adVideoId": "G6qzzxZou2U","adVideoUrl": "https://www.youtube.com/watch?v=G6qzzxZou2U","adVideoDuration": null,"adVideoThumbnail": null,"shoppingItemIds": [],"adGroupId": null,"googleCreativeId": "802897023323","obfuscatedCustomerId": "5664803232","adWidth": 320,"adHeight": 568,"creativeTypeCode": 46}
| Field | Type | Meaning |
|---|---|---|
adLibraryUrl … regionStats | — | Unchanged base fields — see Limits for the base's own known quirks, preserved here |
adHeadline / adDescription / adLongHeadline | string | null | Ad copy read from the preview. Present only when the preview's template carries these keys (measured ~24% / ~45% of all creatives) |
adCallToAction | string | null | Button text, e.g. INSTALL |
destinationUrl | string | null | The click-through link, un-escaped, verified to start with http(s):// |
displayUrl | string | null | The short URL Google shows on the ad itself |
finalUrl | string | null | A second landing-link field Google's preview carries. Measured empty in 100% of observations — a nullable fallback, never a promise |
clickTrackerUrl | string | null | The googleadservices.com/pagead/aclk?… tracker Google serves, returned as the string it is. Never followed — no second request, no landing page fetched |
hasAdCopy | boolean | true when a headline or a click-through link was read. Convenience only — not the point of the row |
promotedApp | object | null | App-install record when the preview is one. null for every other ad, or when includePromotedProduct is off |
adVideoId / adVideoUrl / adVideoDuration / adVideoThumbnail | — | The YouTube video a video ad plays. adVideoDuration is Google's own m:ss string, never converted to seconds |
shoppingItemIds | array | Shopping-ad product item ids, from the preview URL's own query string |
adGroupId / googleCreativeId / obfuscatedCustomerId | string | null | Google Ads account plumbing ids, read from the preview URL's query string — zero extra requests, present even when openAdPreviews is off |
adWidth / adHeight / creativeTypeCode | number | null | The preview's own rendered dimensions and Google's internal creative-type code |
📊 Measured coverage (live, 2026-08-15, Pokémon AR04619580580634296321)
| Measurement | Result |
|---|---|
| Ads with a preview document at all | measured 70/160 creatives (44%) across 4 advertisers — the rest are text/search ads rendered as flat images with nothing to read |
| Preview fetch success | 40/40 plain GETs returned HTTP 200 |
| Previews carrying a headline | 22/40 fetched previews |
| Previews carrying a destination link | 18/40 fetched previews |
| Coverage swings hard by advertiser | Nike: 0/10 destination URLs. Pokémon: 11/12. HelloFresh: 4/4 previews with neither copy nor a link |
onlyAdsWithAdCopy filter, live | default run: 40 listed → 8 qualifying (headline or link present). onlyAdsWithAdCopy:false: same 40 listed, 4 pass / 11 fail, all 15 kept |
destinationDomainFilter filter, live | ["play.google.com"] against the same advertiser: 5/5 returned rows contain play.google.com in destinationUrl |
includePromotedProduct:false, live | promotedApp, adVideoId, shoppingItemIds all forced to null/[] while adCallToAction/destinationUrl stay populated |
⚠️ Limits — please read
- Only roughly a quarter of all creatives carry readable copy. Google renders text and search ads
as flat pictures with no headline string and no link at all.
onlyAdsWithAdCopydefaults totruebecause of this — turn it off to see every ad, including the blanks. - Coverage is not a promise. It swings from 0% to over 90% by advertiser, measured live (see table above).
finalUrlhas never been observed with a value. It is present in the preview but always empty; it exists only as a nullable fallback fordestinationUrl, never as a claim of its own.- One extra request per ad that has a preview.
openAdPreviews:falsereturns exactly the base's behaviour — no preview fetch, no ad copy, no click-through link. - Preview links are signed and expire. They are fetched in the same run they are listed in; a
failed or expired fetch returns
nulls for that row rather than retrying forever. maxItemscounts qualifying rows, not listed creatives. WithonlyAdsWithAdCopyon, the run pages further to find enough readable ads, up to an internal safety cap of 5 extra pages / 200 listed creatives per advertiser.- Nothing is downloaded, decoded pixel-by-pixel or guessed. Every field is a string or number Google's own preview document serves. There is no OCR, no score, no ranking, no spend estimate and no comparison with a previous run.
- Base quirks are preserved, not fixed (this variant's job is ad copy, not a repair):
creativeRegions/regionStats[].regionCodecarry the base'sRegion <N>-style placeholders (the base misreads a days-shown counter as a region id),regionStats[].impressionsis a constant{0, 1000}on every region, andformatreads"UNKNOWN"on text ads. See the base contract for the full list. - Everything here is logged out. No cookie, no login, no API key, against pages Google publishes for public inspection.
💳 Pricing
Pay per event: one creative_result event per ad creative written to the dataset. Rows dropped by
onlyAdsWithAdCopy or destinationDomainFilter are never pushed and never charged.
❓ FAQ
Do I need a Google account, cookie or API key? No. The whole run is logged-out.
Why is adHeadline null on some rows even though hasAdCopy is true? hasAdCopy is true when
either a headline OR a destination link was read. A row can carry a link with no headline, or a
headline with no link — see the measured coverage table.
Can I get the advertiser's landing page contents? No. destinationUrl is returned as a string;
the page behind it is never fetched.
Does this follow the click tracker redirect? No. clickTrackerUrl is returned exactly as Google
serves it — following it would be a second live request per ad and would leave Google's own site.
What can I export? The dataset exports to JSON, CSV, Excel, XML and JSONL from the Apify console or the API.
⚖️ Legal & compliance
This actor reads only the public, logged-out Google Ads Transparency Center and the ad's own public preview document, both of which Google serves for ad-transparency inspection. It collects no personal data, uses no credentials and bypasses no access control. Respect Google's terms and the law of your jurisdiction when using the data.
Keywords: Google Ads scraper · Google Ads Transparency Center · ad copy scraper · ad creative text · click-through link · destination URL extractor · landing page link · call-to-action scraper · competitor ad research · advertiser ID lookup · app install ad scraper · YouTube ad scraper · shopping ad scraper · ad headline extractor · promoted app data · export JSON CSV Excel · no login required