Google Ads Transparency Center Scraper
Pricing
from $0.90 / 1,000 ads
Google Ads Transparency Center Scraper
Scrape ads from the Google Ads Transparency Center by brand, domain, advertiser ID or URL. Get text, image and video ads with dates, regions, ad copy, landing pages, YouTube IDs, EU impressions and advertiser profiles.
Pricing
from $0.90 / 1,000 ads
Rating
0.0
(0)
Developer
Matt
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
8 days ago
Last modified
Categories
Share
Google Ads Transparency Center Scraper turns adstransparency.google.com, Google's public library of ads, into structured data. Give it brand names, domains, advertiser IDs or links copied from the site, and get every ad with its advertiser, format, first and last shown dates, regions, ad copy, images, YouTube video, landing page and, for the EU, impressions and audience targeting. Political ads come with spend ranges. No login, no browser, pay only for the ads you get.
What you can extract
- Ads by brand, domain, advertiser or URL: the same ads the site lists, filtered by region, date range, format (text, image, video) and platform (Search, YouTube, Shopping, Maps, Play).
- For every ad: ad ID and link, advertiser name and ID, format, first shown, last shown, number of days shown, preview picture or preview script, size.
- With "Include ad details" (extra charge per ad):
- Ad copy: headline, long headline, description, business name, display URL, call to action, sitelinks and other extensions.
- Search text ads that Google only shows as a picture are read with OCR, in many languages, with a confidence score.
- Landing page URL (when the ad contains it), YouTube video ID and link, video length and channel, Shopping product title, price and merchant.
- All variations of the ad, and every region where it ran with its last shown date.
- Ads shown in the EU: impressions per region and per platform, audience targeting (demographics, locations, contextual signals, topics of interest, customer lists) and the ad's topic.
- Political ads: impressions and spend ranges with currency, and the regions targeted.
- Advertiser profiles (optional): legal name, country, verification status, whether they run political ads, and how many ads match your filters.
- Monitoring: return only ads that earlier runs have not returned yet.
Use cases
- Competitor research: see every ad a competitor runs, where, in which formats, and since when.
- Creative inspiration: collect headlines, descriptions and videos from the best advertisers in a niche.
- Ad monitoring: schedule a daily run with "Only new ads" and get only the ads launched since the last run.
- Lead generation and ad checks: find out which companies advertise on Google, and roughly how many ads they run, without paying for the ads themselves.
- Brand protection: list every advertiser whose ads point to your domain (resellers, affiliates, agencies).
- Political ad research and journalism: spend, reach and targeting of election ads by region.
- Market research: compare ad activity by country, platform and format.
How to use it
- Enter what to look up: brand names or domains in Brands, advertiser names or domains, or paste links from adstransparency.google.com in Ads Transparency Center URLs.
- Optional: pick a Region, a date range, an Ad format or a Platform.
- Set Max ads per search (default 100).
- Turn on Include ad details if you need the ad copy, landing pages, videos and EU data, and Include advertiser profiles if you need one row per advertiser.
- Click Start. Download the results as JSON, CSV or Excel, or read them through the API.
Input example
{"searchTerms": ["nike.com", "Zalando"],"advertiserIds": ["AR10072600183532683265"],"startUrls": [{ "url": "https://adstransparency.google.com/?region=DE&domain=hellofresh.de&preset-date=Last+30+days" }],"region": "US","datePreset": "LAST_30_DAYS","format": "ALL","maxAdsPerTarget": 50,"includeAdDetails": true,"includeAdvertiserInfo": true}
- A domain (nike.com) returns every ad that points to that website, from all advertiser accounts.
- A brand name (Zalando) is matched to the advertiser account with that name through the site's own search. Raise Advertisers per name to also get the brand's other accounts (brands often run one per country).
- Pasted links keep their own filters (here: Germany, last 30 days). Advertiser pages, single ads, domain searches and political pages all work.
- Ad check: set Max ads per search to
0and turn on Include advertiser profiles to get only the advertisers and their ad counts. - Political ads: paste a link such as
https://adstransparency.google.com/political?region=US, or turn on Political ads only with a region (US, GB, BR, IN, AU, MX, AR, CL, IL, NZ, ZA or TW).
Output example
Real rows from a run on 2026-10-13 (advertiser HubSpot, region US, details and profiles on). Fields that were empty are left out here to keep it short; in the dataset every row has all fields, with null where a value doesn't apply.
A search text ad, read from Google's picture of the ad:
{"type": "ad","status": "ok","adId": "CR08761365368351490049","adUrl": "https://adstransparency.google.com/advertiser/AR10072600183532683265/creative/CR08761365368351490049?region=US","advertiserId": "AR10072600183532683265","advertiserName": "Hubspot, Inc.","format": "TEXT","firstShown": "2026-04-14T15:56:57.608Z","lastShown": "2026-10-13T13:25:51.063Z","daysShown": 183,"imageUrl": "https://tpc.googlesyndication.com/archive/simgad/15074397727829361511","headline": "Full AEO Plan, Half the Price - Start Winning AEO in Minutes","description": "See where competitors beat you in AI search and what to do. Try it free for 28 days. Get more than...","businessName": "HubSpot","displayUrl": "www.hubspot.com/","adTextSource": "ocr","ocrConfidence": 93,"sitelinks": [{ "title": "Try it Free for 28 Days", "description": null },{ "title": "The AEO Tool With a Plan", "description": null }],"variationCount": 1,"regions": [{ "regionCode": "US", "regionName": "United States", "lastShown": "2026-10-13" },{ "regionCode": "CA", "regionName": "Canada", "lastShown": "2026-10-12" }],"regionCodes": ["US", "CA"],"legalName": "Hubspot, Inc.","advertiserCountry": "US","advertiserVerified": true,"detailsIncluded": true,"inputType": "advertiserId","inputValue": "AR10072600183532683265","searchRegion": "US","scrapedAt": "2026-10-13T14:22:51.032Z"}
A YouTube video ad (trimmed):
{"type": "ad","adId": "CR01664706036616921089","advertiserName": "Hubspot, Inc.","format": "VIDEO","firstShown": "2026-06-17T15:27:01.218Z","lastShown": "2026-10-13T13:44:16.970Z","youtubeVideoId": "ppJHa9Clfds","videoUrl": "https://www.youtube.com/watch?v=ppJHa9Clfds","headline": "More leads. More deals. One Smart CRM.","longHeadline": "Everything your team needs to grow. Get started free with HubSpot Smart CRM.","description": "HubSpot helps teams grow faster and keep customers happy.","landingPageUrl": "https://www.hubspot.com/crm/e010a","adTextSource": "preview","videoDuration": "0:15","channelName": "HubSpot Ads","variationCount": 4,"regionCodes": ["US", "CA"]}
EU data on an ad shown in Germany (other run, trimmed):
{"adId": "CR10176161929622454273","advertiserName": "Zalando SE","headline": "Kinderbademäntel Größe 152 online von Top-Marken bei Zalando -...","regions": [{"regionCode": "DE","firstShown": "2024-07-06","lastShown": "2026-10-13","impressionsLowerBound": 3000,"impressionsUpperBound": 4000,"platformImpressions": [{ "platform": "YOUTUBE", "impressionsLowerBound": 0, "impressionsUpperBound": 1000 },{ "platform": "SEARCH", "impressionsLowerBound": 3000, "impressionsUpperBound": 4000 }]}],"platforms": ["SEARCH", "YOUTUBE"],"audienceSelection": { "demographics": "included", "geographicLocations": "includedAndExcluded", "contextualSignals": "includedAndExcluded" },"topic": "Apparel","topicSource": "google"}
An advertiser profile row:
{"type": "advertiser","status": "ok","advertiserId": "AR10072600183532683265","advertiserName": "Hubspot, Inc.","legalName": "Hubspot, Inc.","advertiserCountry": "US","advertiserVerified": true,"adCountLowerBound": 600,"adCountUpperBound": 700,"hasPoliticalAds": false,"inputValue": "AR10072600183532683265","searchRegion": "US"}
Main fields
| Field | What it is |
|---|---|
type | ad, advertiser, error or no_results |
adId, adUrl | Google's ad (creative) ID and the ad's page on the Transparency Center |
advertiserId, advertiserName | Advertiser account |
format | TEXT, IMAGE or VIDEO |
firstShown, lastShown, daysShown | When the ad ran (ISO 8601) |
imageUrl, previewUrl | Google's picture of the ad, or its preview script / archived page |
headline, description, displayUrl, businessName, sitelinks, callouts | Ad copy (details) |
adText | All ad copy in one text block (details) |
adTextSource, ocrConfidence | preview (exact text from Google's markup) or ocr (read from the picture, confidence 0-100) |
landingPageUrl, callToAction | Where the ad links to, button text (details, when present in the ad) |
youtubeVideoId, videoUrl, videoDuration, channelName | Video ads (details) |
product | Shopping ads: title, price, currency, merchant (details) |
variations, variationCount | Every version of the ad |
regions, regionCodes | Where the ad ran, with dates and (EU) impressions per platform |
platforms, impressionsLowerBound, impressionsUpperBound | EU and political ads |
audienceSelection, topic, topicSource | EU ads: how the audience was selected and the ad's topic |
spendLowerBound, spendUpperBound, spendCurrency | Political ads |
legalName, advertiserCountry, advertiserVerified, adCountLowerBound, adCountUpperBound | Advertiser profile |
inputType, inputValue, searchRegion, scrapedAt | Which input produced the row, and when |
The dataset has ready-made views: Ads, Ad copy, Advertisers, Political ads and Notices (errors and inputs without results). Each run also saves a RUN_SUMMARY record in its key-value store with counts, request statistics and the reason it stopped.
Pricing
You pay per result:
- $1.50 per 1,000 ads on the Free plan, down to $0.90 per 1,000 on Apify's Gold plan and higher.
- Ad details: +$1.50 per 1,000 ads (down to $0.90). Only charged for ads whose details were actually retrieved.
- Advertiser profiles: $2.00 per 1,000 (down to $1.20).
- Rows for errors, inputs without results and monitoring notices are free.
Examples on the Free plan: the default run (20 ads) costs $0.03; 1,000 ads cost $1.50; 1,000 ads with details cost $3.00. Set a maximum cost per run in the run options and the Actor stops cleanly when it is reached. See the Pricing tab for the exact current prices.
Speed and reliability
Measured on the Apify platform in October 2026, with the default proxy and 1 GB memory:
| Run | Time |
|---|---|
| Default input (20 ads) | about 5 s |
| 1,000 ads from 5 domains | 31 s |
| 3,000 ads from one domain | 118 s |
| 800 ads + 81 advertiser profiles from 8 domains | 35 s |
| 100 ads with details (about 70 text ads read with OCR) | 2.5-4 min |
| 10 ads with details + 1 advertiser profile | 39 s |
All 27 test runs finished successfully. Google rate-limited 113 of 1,337 requests (8.5%) in the 25 runs we logged in detail; every one was retried automatically and no input failed because of it.
Reading text ads (OCR) uses a lot of CPU, and Apify gives 1 CPU core per 4 GB of memory. For large detail runs, use 4 GB: in our test, 30 text ads in several languages took 66 s at 4 GB and 115 s at 1 GB.
Use it from code
JavaScript (apify-client):
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('mattwensey/google-ads-transparency-scraper').call({searchTerms: ['nike.com'],region: 'US',maxAdsPerTarget: 50,includeAdDetails: true,});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const ad of items.filter((i) => i.type === 'ad')) {console.log(ad.adId, ad.format, ad.lastShown, ad.headline);}
Python (apify-client):
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("mattwensey/google-ads-transparency-scraper").call(run_input={"searchTerms": ["nike.com"],"region": "US","maxAdsPerTarget": 50,"includeAdDetails": True,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():if item["type"] == "ad":print(item["adId"], item["format"], item["lastShown"], item["headline"])
AI agents (MCP): add the Actor to Claude, Cursor or any MCP client through Apify's MCP server, for example:
{"mcpServers": {"apify": {"command": "npx","args": ["-y", "@apify/actors-mcp-server", "--actors", "mattwensey/google-ads-transparency-scraper"],"env": { "APIFY_TOKEN": "<YOUR_APIFY_TOKEN>" }}}}
Then ask, for example: "Which ads has hubspot.com run in Germany in the last 30 days?" The input fields are described for agents, so they can fill them in from a plain question.
Monitoring new ads
Turn on Only new ads and give the job a Monitor name (for example competitors-uk). The Actor remembers the IDs of the ads it returned in a key-value store of that name in your account, and later runs with the same name return only ads it has not seen. You pay only for new ads. Schedule the run daily or weekly and connect a webhook, Slack or email integration to get the new ads delivered. Use a different monitor name for each set of competitors.
How it works
The Actor calls the same JSON API that the Transparency Center website uses, with browser-like HTTP requests made by impit (no headless browser). Ad details come from the site's ad lookup and from Google's ad previews. Most search text ads are only available as a picture; the Actor reads those with Tesseract.js OCR and splits the text into headline, description, display URL and extensions using the layout and colours of the picture. Requests go through Apify Proxy. When Google rate-limits a request, the Actor retries it with a new IP and browser fingerprint, and switches to residential proxies if datacenter IPs keep getting blocked.
FAQ
Is it legal to scrape the Google Ads Transparency Center? The Actor collects only data that Google publishes for everyone on the Transparency Center: ads and the business details of the advertisers who paid for them. It does not log in or collect personal data about people. Whether your specific use is allowed depends on your jurisdiction and purpose (for example if you republish ads or creatives), so check with a lawyer if you are unsure.
Do I need proxies? Yes, keep Apify Proxy on (the default). Google limits how many requests one IP address can make. The default datacenter proxy works for most runs, and requests that keep getting blocked are retried through residential proxies automatically. For very large runs you can select residential proxies directly.
Why are some fields empty? Google only publishes some data for some ads:
- Impressions, platforms and audience targeting exist only for ads shown in the EU, and for political ads.
- Landing pages are only available when the ad itself contains the link (mostly video, display and app ads); Google does not publish them for search text ads.
- Spend is only published for political ads.
- Ad copy needs Include ad details. Text that OCR could not read with enough confidence (below 60) is left empty rather than guessed.
How accurate is the OCR?
The text is read from Google's picture of the ad, so it is what users saw, but small recognition errors are possible (for example accents or letters that look alike). Each row has adTextSource and ocrConfidence, so you can filter. English is always used, plus the language of your region, of the ad's domain (.de, .fr, ...) or of its wording. Ads in other scripts, such as Japanese, Thai, Russian or Hebrew, are retried with the languages of the countries where they ran. For right-to-left ads (Hebrew, Arabic) sitelinks and extensions are left out, because their mirrored layout is not read reliably.
Why does Google show "~600-700 ads" instead of an exact number?
Google publishes ad counts only as ranges. The Actor reports them as adCountLowerBound and adCountUpperBound, and the log shows the range for each search.
I searched a brand name and got the wrong advertiser. Names are matched to advertiser accounts with the site's own search, preferring exact names and then the account with the most ads. To be sure, use the domain, the advertiser ID (AR...) or the advertiser's link from the site. Raise Advertisers per name to get several accounts per name.
What are the limits?
- Max ads per search accepts up to 100,000 and a run up to 5,000 inputs; the largest run we tested returned 3,000 ads from one search. Use Max ads in total to cap a whole run.
- One region per run (pasted links can each have their own region).
- Ads that the site shows only to signed-in users (age-restricted ads) are not available.
- Political ads are available only in the regions where Google publishes them.
- Some video ads are hosted outside YouTube; those have no YouTube ID.
The run failed with "Invalid input". The message says what to fix, for example "Nothing to scrape" when no search term, domain, advertiser ID or link was given, or an unrecognized link. Links must come from adstransparency.google.com.
Some rows have type: "error" or "no_results".
These rows are free. no_results means the input had no ads with your filters (for example a domain that does not advertise in that region). error means the input failed after all retries; the errorMessage says why. The rest of the run is not affected.
Changelog
See CHANGELOG.md.
Support
Found a bug or need a field that isn't there? Open an issue on the Actor's Issues tab with the run ID, and we'll look into it.