Google Ads Transparency Scraper & Monitor - Ad Library, MCP
Pricing
from $0.70 / 1,000 results
Google Ads Transparency Scraper & Monitor - Ad Library, MCP
Google Ads Transparency scraper, Google Ads Library API and competitor ad monitor: every ad a brand runs on Google Search, YouTube, Shopping and Maps, by advertiser, domain or link, with ad copy, regions, EU reach and targeting. Tracks new and stopped ads with Slack, Discord or Teams alerts and MCP.
Pricing
from $0.70 / 1,000 results
Rating
0.0
(0)
Developer
Akhil rajesh
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
an hour ago
Last modified
Categories
Share
Google Ads Transparency Scraper & Monitor
Scrape Google's Ads Transparency Center (Google's ad library): every ad an advertiser runs on Google Search, YouTube, Google Shopping, Google Maps and Google Play, or every advertiser's ads for a website domain. Each ad comes with its format (text, image, video), first and last shown days, days shown, whether it is running now, a preview image and its Transparency Center link. Ad details add a text ad's ad copy (headline, description, display URL, sitelinks, callouts, locations) where Google serves it as text, the Google Ads account and ad group behind the ad, its variations, every region it ran in, the platforms, a video ad's YouTube link, a Shopping or Maps ad's words, and for ads shown in the EU Google's times-shown ranges, the ad's topic and its audience selection. Filter by region, format, platform and dates, or paste a Transparency Center link with its own.
One price, no extras: $1.00 per 1,000 results, with platform usage included and no row cap on Apify's free plan. (Apify's Store page lists platform usage too, because the live API below adds its own; ordinary runs never do.)
It is also a competitor ad monitor. Schedule it with Only changes and each run returns only what moved since the last one: new ads, ads that stopped running, and ads running again, posted to Slack, Discord or Microsoft Teams if you like. It runs as a live API and MCP server for AI agents too.
Why this scraper
- It tracks changes, not just ads. Most Ads Transparency scrapers return the same ads every run, and you work out what changed. This one keeps a history per advertiser and filters, and returns each new, stopped or restarted ad once.
- "Stopped" is checked, not guessed. An ad missing from a search is looked up on its own: if Google still shows it (it only left your date window or the cap), nothing is reported; if Google no longer has it, the row says so.
- Domains find every account. Brands advertise under legal names and agencies (
Nike Retail BV,WPP Media Management).nike.comreturns every advertiser's ads for the site, and one row per domain lists the advertisers found. - Google's own filters. Region (243 countries), format, platform and a date window go to Google with the search, so a run reads only what matches. A Transparency Center link you paste keeps its own filters and dates.
- Ad copy as Google serves it. Where Google serves a text ad's copy as text, you get the headline, description, display URL, sitelinks, callouts and store locations as fields, not a guess read off a picture. Ads whose copy Google serves only as a picture keep the picture.
- Ads grouped the way the advertiser runs them. Each ad's Google Ads account and ad group (from Google's own preview link) show which ads run together, and which of a brand's accounts runs them.
- Fast. Ads come 100 per answer: 1,000 ads read in under 15 seconds, details at about one ad a second.
- No runaway bills. Every run stops at Max results (1,000 unless you set it) or at your maximum cost per run, and inputs Google doesn't know are free.
| Typical Ads Transparency scrapers | This Actor | |
|---|---|---|
| New, stopped and restarted ads since the last run | You compare runs yourself | Built in (Only changes) |
| Alerts to Slack, Discord, Teams | Rare | Yes |
| Every advertiser's ads for a domain | Some | Yes, with a row listing the advertisers |
| Variations, regions, EU times shown, platforms | Some | Yes (Ad details) |
| Text ads' headline, description, sitelinks, callouts | Some (a few read them off the ad's picture with OCR) | Yes, where Google serves them as text (Ad details) |
| EU topic and audience selection | Several | Yes (Ad details) |
| Google Ads account and ad group of each ad | Rare | Yes (image and video ads, and text ads with their copy) |
| YouTube link of video ads, words of Shopping and Maps ads | Rare | Yes |
| MCP server for AI agents | Rare | Its own (4 tools) |
| Price per 1,000 ads | $1.50 and $2.00 at the two most used (one charges ad details extra) | $1.00, less on paid plans, details included |
Use cases
- Competitor ad monitoring: a daily schedule of your competitors' domains that posts each new ad and each ad they stop to Slack.
- Creative research: every ad a brand runs on YouTube in Germany in the last 30 days, with each video's link.
- Ad copy research: the headlines, descriptions and sitelinks a competitor runs on Search, grouped by ad group.
- Agency and media analysis: which accounts and agencies advertise for a domain, and Google's estimate of their ads.
- Ad longevity: ads that have run for hundreds of days are the ones that work; sort by
daysShown. - Shopping and local ads: product titles of a retailer's Shopping ads, a chain's Maps ads with their headlines.
- AI agents: ask an assistant "what YouTube ads has HelloFresh started this month?" through the MCP server.
How to use it in 4 steps
- Add Advertisers or domains: a website (
nike.com), an advertiser's Transparency Center link or id (AR16735076323512287233), an ad's link, or an advertiser's name (Nike). - Pick a Region (a country, or anywhere), and if you like a format, platform and Shown within (days).
- Set Max results, and Ad details to read for variations, regions and the YouTube link, then run it.
- To monitor, switch on Only changes since the last run, add an Alert webhook URL for chat alerts, and schedule it.
What you get
One row per ad (type: "ad"). Example (a real row, a Nike Search ad for nike.com in the United States, read in full; shortened to one of its five store locations):
{"type": "ad","search": "nike.com","adId": "CR02884820646712311809","advertiserId": "AR16735076323512287233","advertiserName": "Nike, Inc.","format": "text","firstShown": "2023-11-17","lastShown": "2026-10-27","daysShown": 896,"running": true,"domain": "nike.com","region": "US","previewImageUrl": "https://tpc.googlesyndication.com/archive/simgad/2486371562653617280","adUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR02884820646712311809?region=US","headline": "Nike® Official Site","description": "Shop shoes that provide the support, cushioning, and stability you need.","displayUrl": "nike.com","businessName": "Nike","adLocations": [{"name": "Nike House of Innovation NYC", "address": "650 5th Avenue", "city": "New York","region": "New York", "postalCode": "10019", "country": "US"}],"copySource": "preview","adsAccountId": "9975158271","adGroupId": "148805191594","adsCreativeId": "681141666371","variationCount": 3,"regionsShown": [{"region": "US", "regionName": "United States", "lastShown": "2026-10-27"}],"regionCount": 1,"adDetailsRead": true,"summary": "Text ad by Nike, Inc. for nike.com, shown 2023-11-17 to 2026-10-27 (896 days): \"Nike® Official Site\"; in 1 region."}
Every ad row has the advertiser, format, first and last shown days, days shown, whether it is running (shown within the last 2 days), the domain it points to, a preview (previewImageUrl, a picture of the ad, or Google's preview script previewUrl) and its links. Ad details (Ad details to read, or an ad given by link) add:
- Ad copy of text ads, where Google serves it as text:
headline,description,displayUrl,businessName,sitelinks,callouts, storeadLocationswith their addresses, and for local adsbusinessRating,businessCategoryandadActions(Directions, Call). Dynamic Search Ads, whose headline Google writes from the landing page, say so (dynamicHeadline). Google serves some advertisers' text ads this way and others only as a picture of the ad: Nike's copy came as text for 39 of its 49 newest US text ads, Expedia's and Zalando's for none of 50. A picture-only ad keeps itspreviewImageUrl. - The Google Ads account and ad group behind the ad (
adsAccountId,adGroupId, and Google Ads' own ad idadsCreativeId), from Google's preview link: on image and video ads, and on text ads whose copy came as text. Ads of one ad group run together, and one brand can run several accounts: Nike's 50 newest US ads, read in full, came from 2 accounts and 40 ad groups. - The variations and their previews, and every region the ad ran in with its first and last day.
- For ads shown in the EU: Google's times-shown ranges per region and platform (
euTimesShown,platformsShown), the ad's topic (Apparel,Travel & Tourism) and its audience selection (audienceSelection: whether the advertiser included or excluded people by demographics, locations, contextual signals, topics of interest or customer lists, with the ages, genders and places where Google names them). - A video ad's
youtubeVideoIdandyoutubeUrl(or, for one not on YouTube, its MP4 filevideoUrland lengthvideoDurationSecs); a Shopping ad's product title and merchant, or a Maps ad's business, headline and text (adTexts), and for some Shopping ads the product page the ad leads to (landingUrl).
Google reports times shown only for ads shown in the EU (under the Digital Services Act), as ranges such as 10,000-15,000, and the audience selection only for those ads too. It doesn't publish spend, clicks or keywords.
Each run also returns one row per advertiser read (type: "advertiser": name, country, legal name, Google's estimate of its ads in your filters) and per domain read (type: "domain": Google's estimate of the ads that point to it, and the advertisers whose ads were read, most ads first). Inputs Google doesn't know get a free notFound row with the reason.
With Only changes, each ad row also has change:
| change | meaning |
|---|---|
newAd | first shown since the last run |
adStopped | running at the last run, not shown since (previousLastShown; note when Google no longer has the ad) |
adResumed | reported stopped before, shown again (stoppedDate) |
firstRun | the first run's baseline: the ads there now |
The dataset has views for Ads, Changes, Ad copy, Ad details, Advertisers and domains and Not found (a view picks columns: every view lists every row, so filter on type or change if you need to).
How to use it
Advertisers and domains
- A domain (
nike.com, or a link to the site): every advertiser's ads that point to it. The surest way to find a brand: big brands advertise under several accounts and through agencies. - An advertiser's id or Transparency Center link (
adstransparency.google.com/advertiser/AR...): that account's ads. A pasted link (an advertiser's page or the site's domain search) keeps its own region, platform, format and dates when you set none: the site's Today, Yesterday, Last 7 days and Last 30 days, or a date range. - An ad's link (
.../advertiser/AR.../creative/CR...): that ad, read whole with its details. - A name (
Nike,HelloFresh): looked up in the Transparency Center's search box; the accounts named so are read, biggest first (Accounts per name, 3 by default; accounts with under a tenth of the biggest one's ads are left out). The search box sometimes refuses Apify's servers, so a name can come back as not loaded: the run says so, and a domain or link always works.
Ads come newest shown first. Max ads per advertiser (1,000 by default) sets how far each advertiser or domain is read; set it to 0 for only the advertiser and domain rows with Google's estimate of their ads, a domain's row listing the advertisers among its 100 newest ads (a quick check of who advertises). Max results is shared between them.
Filters
Sent to Google with every search: Region (243 countries by name or code, or anywhere), Ad format (text, image, video), Platform (Search, YouTube, Shopping, Maps or Play: the Transparency Center filters by one at a time), and Shown within (days) or a Shown from / Shown to window. Shown within 7 days is the 7 days before today, as the Transparency Center's own "Last 7 days" counts them; Shown from and Shown to include both days. Google's date filter reaches back about a year; every ad's first and last shown days are in its row anyway.
Ad details
Ad details to read (0 by default, at most 500 a run) reads that many ads in full: one request each, plus the ad's preview script where it has one (image and video ads, and text ads whose copy Google serves as text). With Only changes, the changes are read first.
Monitoring competitors' ads on a schedule
- Switch on Only changes since the last run. Optionally pick the Changes to return.
- Run it once: the first run returns the ads there now as
firstRunand saves them as the baseline. - Schedule it (Apify Console, Schedules): daily suits most monitors, as Google updates last-shown days once a day. Each later run returns only the changes.
How it decides:
- Each advertiser or domain is read whole, up to Max ads per advertiser, newest shown first, and every ad is compared with the last run.
- An ad is running when Google showed it within the last 2 days (Google's days run a day behind). A running ad not shown since is
adStoppedonce; a stopped ad shown again isadResumed; an ad first shown since the last run isnewAd. An older ad the tracker hadn't met (a new filter, a raised cap) is recorded quietly. - A running ad missing from a search is looked up on its own (up to 50 a run): still shown means no change; not shown since, or gone from the Transparency Center, means stopped.
- Histories are kept per advertiser or domain and filters (two monitors with different filters don't mix), in the key-value store
google-ads-monitor-history, or one you name in History name. - Only what a run returns moves the history: if Max results or your spending limit stops a run, the changes it didn't return come with the next run. New ads come first, then stopped, then restarted.
Alerts in Slack, Discord or Microsoft Teams
Paste an incoming-webhook URL in Alert webhook URL (Slack, Discord, Microsoft Teams, or any HTTPS endpoint that takes JSON, such as Zapier, Make or n8n). It switches on Only changes. The first run posts one short "alerts are set up" message; each later run posts its changes (new and stopped ads by default, or those you pick in Alert on), up to 50 per run, each with the ad's preview, dates and link. The URL is treated as a secret and masked in logs. If posting fails, the run still succeeds and its status says why.
Run summary for pipelines
Each run saves a RUN_SUMMARY record in its key-value store: per advertiser or domain, Google's estimate of its ads, the ads read and whether it was read whole; the names and the accounts they were read as; the changes; what didn't load and why; and the filters used. Every ad row also has a one-sentence summary, ready for a report, an alert or an AI agent.
Google Ads Transparency API: use it from code or from an AI assistant
Start a run and get the rows in one call (replace <YOUR_TOKEN>; a call that waits gives up after 5 minutes, so start bigger runs without waiting and read the dataset afterwards):
curl -X POST "https://api.apify.com/v2/acts/akhil_rajesh~google-ads-transparency-scraper/run-sync-get-dataset-items" \-H "Authorization: Bearer <YOUR_TOKEN>" \-H "Content-Type: application/json" \-d '{"advertisers": ["hellofresh.com"], "region": "US", "adFormat": "video", "shownWithinDays": 30, "maxResults": 100}'
Or from Python with apify-client:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_TOKEN>")run = client.actor("akhil_rajesh/google-ads-transparency-scraper").call(run_input={"advertisers": ["nike.com", "adidas.com"], "region": "DE", "platform": "youtube","maxResults": 300, "maxAdDetails": 50,})for row in client.dataset(run.default_dataset_id).iterate_items():if row["type"] == "ad":print(row["summary"], row.get("youtubeUrl"))
For AI agents: MCP server and live API
The Actor also runs as a live endpoint (Apify Standby): an MCP server that agents call directly, and plain HTTP endpoints. Once a Standby run is up, a request is answered in seconds; the first request starts one. Authenticate with your Apify API token in the Authorization: Bearer <token> header.
MCP server (Streamable HTTP): https://akhil-rajesh--google-ads-transparency-scraper.apify.actor/mcp
{"mcpServers": {"google-ads": {"type": "http", "url": "https://akhil-rajesh--google-ads-transparency-scraper.apify.actor/mcp","headers": {"Authorization": "Bearer <YOUR_APIFY_TOKEN>"}}}}
In Claude Code:
$claude mcp add --transport http google-ads https://akhil-rajesh--google-ads-transparency-scraper.apify.actor/mcp --header "Authorization: Bearer <YOUR_APIFY_TOKEN>"
A client that can't send headers can use https://akhil-rajesh--google-ads-transparency-scraper.apify.actor/mcp?token=<YOUR_APIFY_TOKEN>; keep that URL private, as it carries your token. Through Apify's MCP server (https://mcp.apify.com, for Claude, ChatGPT, Cursor and other clients), add the tools with https://mcp.apify.com?tools=akhil_rajesh/google-ads-transparency-scraper (they appear as akhil_rajesh--google-ads-transparency-scraper--search_ads and so on), then ask in plain words, for example "which YouTube ads did hellofresh.com run in the US this month?". Add them that way rather than through Apify's generic call-actor tool, which returns the rows only as text. Apify's MCP server doesn't offer Actors with a live endpoint to agents that pay per call with x402 or Skyfire: connect with an Apify account or API token.
| Tool | What it returns |
|---|---|
search_ads | Ads for up to 3 advertisers or domains, newest shown first, with format, dates, preview, link and a one-line summary; region, format, platform and date filters; ad details on request |
get_ads | Ads read by link with their details: ad copy where Google serves it as text, Google Ads account and ad group, variations, regions, EU times shown, topic and audience, platforms, a video's YouTube link |
find_advertisers | The accounts and domains the Transparency Center lists for a name (free) |
run_actor | The Actor's whole input in one call |
HTTP endpoints, such as GET https://akhil-rajesh--google-ads-transparency-scraper.apify.actor/ads?advertisers=nike.com|adidas.com®ion=US&format=video&max=100 (separate several advertisers, domains or ads with |; defaults in brackets). The Actor's Endpoints tab in Apify Console lists them too, and lets you try them.
| Endpoint | Parameters |
|---|---|
GET /ads | advertisers, region, format, platform, shownWithinDays, max (100), maxPerAdvertiser, details (0) |
GET /ad | ads (links) |
GET /advertisers | q (a name; free) |
POST /run | The Actor's whole input as the JSON body |
Answers carry the rows, rowsByType, notFound (inputs Google doesn't know: free), notLoaded (what Google didn't answer), notRead (what a limit left out: not charged) and notes. A request that reads nothing gets an error and nothing is charged: HTTP 400 for an argument it can't read (a tool error over MCP), 503 when Google didn't answer or the run was busy (send it again), 402 when your spending limit for the run is reached (it lifts when the run ends, after 2 minutes without requests). A 503 can also carry rows, when the platform stopped the run while a request was being read: those were stored and charged, and notRead names the rest.
Limits per request: an MCP tool call reads up to 3 advertisers or domains, 200 ads and 10 ads' details, about 350 kB of rows, within 50 seconds, and asks for 50 ads unless told otherwise (MCP clients stop waiting at 60 seconds, and Apify's MCP server drops answers over about 1 MB); an HTTP request reads up to 10 advertisers or domains, 2,000 ads, 40 ads' details and about 6 MB within 170 seconds. What a limit leaves out is named in notRead and isn't charged. A request that has started runs to its end even if you stop waiting: Apify's Standby proxy keeps it open, so its rows are read and charged. Ask for what you need. Monitoring (Only changes) and alerts belong to scheduled runs: the live endpoint answers each request on its own, so it ignores those fields.
How much does it cost?
You pay $1.00 per 1,000 results, less on paid Apify plans, plus a start fee of $0.00005 per run. A result is an ad, or an advertiser's or domain's row. Platform usage is included in runs of the Actor: there is no compute charge on top, and no row cap on Apify's free plan. (The Store page's pricing box mentions platform usage because of the live endpoint, which charges its own; ordinary runs never do.) Ad details are included in the ad's price. Not-found rows are free. With Only changes you pay only for the changes returned. The live endpoint (MCP server and HTTP API) charges results at the same prices, plus the Standby run's platform usage while it serves you and until it has been idle for 2 minutes (a short session costs a fraction of a cent).
| Apify plan | Per 1,000 results |
|---|---|
| Free | $1.00 |
| Starter | $0.90 |
| Scale | $0.80 |
| Business and above | $0.70 |
| Run | Results | Cost (Free plan) |
|---|---|---|
| A competitor's newest 1,000 ads | 1,001 | about $1.00 |
| 300 ads with their details | 301 | about $0.30 |
| A daily monitor of 5 competitors, about 10 changes a day | 300 a month | about $0.30 a month |
| Who advertises: 50 domains with Max ads per advertiser 0 | 50 | about $0.05 |
Apify's free plan ($5 of monthly credit) covers about 5,000 results. To cap spending, lower Max results or set a maximum cost per run in the run options; the Actor stops cleanly at the limit (and with Only changes, the rest comes with the next run).
Good to know
- Speed: a page of 100 ads takes about a second; an ad's details about a second.
- What Google publishes: format, first and last shown days, previews, regions, and for ads shown in the EU times-shown ranges, platforms, topic and audience selection. Not spend, clicks or keywords. Some advertisers' text ads come with their copy as text; the rest only as a picture of the ad, which this Actor doesn't read with OCR.
- Freshness: Google updates an ad's last shown day once a day, about a day behind, so a monitor finds nothing new more often than daily.
- Names: the Transparency Center's search box, which reads names, sometimes refuses Apify's servers. A refused name is named in the status (not charged); a domain, advertiser id or link always works.
- Refusals: a run that meets a refusal asks again a few times, then fails without charging; ad details refused once aren't asked again in that run.
FAQ
How do I monitor a competitor's Google ads? Put their domain in Advertisers or domains, switch on Only changes, add a Slack, Discord or Teams webhook if you like, and schedule it daily. Each new ad and each ad they stop is returned once.
Can it find all of a brand's advertiser accounts? Search their domain: every advertiser's ads for it come back, and the domain row lists the accounts (brand entities, resellers, agencies). A name returns the accounts named so, biggest first.
Does it get YouTube video ads? Yes: set Platform to YouTube or Ad format to video, and Ad details to read for each video's YouTube link.
Does it show ad spend or impressions? Google publishes neither for most ads. For ads shown in the EU it gives times-shown ranges per region and platform, which the Actor returns with the ad's details.
Does it get the ad copy of Search ads? Yes, where Google serves it as text: set Ad details to read, and each such text ad has its headline, description, displayUrl, sitelinks, callouts and store locations (the Ad copy view lists them). It depends on the advertiser: Nike's copy came as text for 39 of its 49 newest US text ads, Expedia's and Zalando's for none of 50. Those ads' copy is only in the picture of the ad (previewImageUrl). Shopping and Maps ads' words come as text too (adTexts).
Does it show who an ad targets? For ads shown in the EU, Google publishes the ad's topic and which kinds of criteria the advertiser used to choose the audience (demographics, locations, contextual signals, topics of interest, customer lists), included or excluded; the Actor returns them with the ad's details (topic, audienceSelection). Elsewhere Google publishes no targeting.
Can I group ads by campaign? Each ad read in full has the Google Ads account and ad group behind it (adsAccountId, adGroupId) when Google's preview link carries them: image and video ads, and text ads whose copy came as text. Google doesn't publish campaign names.
Can I paste a Transparency Center link? Yes: an advertiser's page or the site's domain search (each with its region, platform, format and dates: Today, Yesterday, Last 7 days, Last 30 days or a date range), or an ad's page.
Which countries? All 243 regions the Transparency Center lists, or anywhere.
Do I need a proxy? No: the Transparency Center answers Apify's servers directly. You can use your own proxies; Apify's residential proxies aren't available in this Actor, as they're billed per GB on top of the result price.
Is it legal? The Actor reads the ads Google publishes for transparency, through the same requests the Transparency Center's own pages make, at a modest pace and without logging in. Use the data in line with Google's terms and the laws that apply to you.
Other Actors by this developer
- Yahoo Finance Scraper: quotes, history, financials, options and news, with an MCP server
- App Store Reviews Scraper and Google Play Reviews Scraper: app reviews with alerts and an MCP server
- Amazon.ca Product & Trending Tracker: Amazon Best Sellers, prices, search positions and reviews on 23 marketplaces, with change tracking
- Craigslist Scraper & Tracker: listings with price drops, reposts and gone listings, plus alerts
Disclaimer
This Actor is an independent tool. It is not affiliated with, endorsed by or sponsored by Google LLC. It reads the ad data Google publishes in its Ads Transparency Center at a modest pace. Use the data in line with Google's terms and the laws that apply to you.