# Google Ads Transparency Scraper & Monitor - Ad Library, MCP (`akhil_rajesh/google-ads-transparency-scraper`) Actor

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.

- **URL**: https://apify.com/akhil_rajesh/google-ads-transparency-scraper.md
- **Developed by:** [Akhil rajesh](https://apify.com/akhil_rajesh) (community)
- **Categories:** Marketing, Lead generation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## 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.com` returns 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

1. 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`).
2. Pick a **Region** (a country, or anywhere), and if you like a **format**, **platform** and **Shown within (days)**.
3. Set **Max results**, and **Ad details to read** for variations, regions and the YouTube link, then run it.
4. 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):

```json
{
    "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`, store `adLocations` with their addresses, and for local ads `businessRating`, `businessCategory` and `adActions` (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 its `previewImageUrl`.
- The **Google Ads account and ad group** behind the ad (`adsAccountId`, `adGroupId`, and Google Ads' own ad id `adsCreativeId`), 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 `youtubeVideoId` and `youtubeUrl` (or, for one not on YouTube, its MP4 file `videoUrl` and length `videoDurationSecs`); 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

1. Switch on **Only changes since the last run**. Optionally pick the **Changes to return**.
2. Run it once: the first run returns the ads there now as `firstRun` and saves them as the baseline.
3. 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 `adStopped` once; a stopped ad shown again is `adResumed`; an ad first shown since the last run is `newAd`. 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):

```bash
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`:

```python
from apify_client import ApifyClient

client = 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`

```json
{"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:

```bash
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&region=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](https://apify.com/akhil_rajesh/yahoo-finance-scraper): quotes, history, financials, options and news, with an MCP server
- [App Store Reviews Scraper](https://apify.com/akhil_rajesh/app-store-reviews-scraper) and [Google Play Reviews Scraper](https://apify.com/akhil_rajesh/google-play-reviews-scraper): app reviews with alerts and an MCP server
- [Amazon.ca Product & Trending Tracker](https://apify.com/akhil_rajesh/amazon-ca-product-trending-tracker): Amazon Best Sellers, prices, search positions and reviews on 23 marketplaces, with change tracking
- [Craigslist Scraper & Tracker](https://apify.com/akhil_rajesh/craigslist-scraper): 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.

# Actor input Schema

## `advertisers` (type: `array`):

What to read: a website's domain ('nike.com': every advertiser's ads that point to it), an advertiser's Transparency Center link (adstransparency.google.com/advertiser/AR...) or id (AR16735076323512287233), an ad's link (.../creative/CR..., read with its details), or an advertiser's name ('Nike': the accounts named so, biggest first). A pasted Transparency Center link keeps its own region, platform, format and dates (Last 7 days, a date range) when you set none here. Names go through Google's search box, which sometimes refuses Apify's servers; domains, ids and links always work. Brands often advertise under their legal name, so a domain finds them all.

## `region` (type: `string`):

The country the ads were shown in, by name or two-letter code ('United States', 'US', 'Germany', 'DE'), or 'anywhere' (the default: every region). A pasted Transparency Center link keeps its own region when this is empty.

## `adFormat` (type: `string`):

Only ads of this format, as the Transparency Center's own filter calls them (Search ads are text ads).

## `platform` (type: `string`):

Only ads shown on this Google platform (the Transparency Center filters by one at a time).

## `shownWithinDays` (type: `integer`):

Only ads Google showed in the last N days before today, as the Transparency Center's own 'Last 7 days' counts them: 2 for the ads running now, 30 for the last month. Its date filter reaches back about a year (365). Leave empty for every ad.

## `startDate` (type: `string`):

Or a date window: only ads shown on or after this day (within the last year).

## `endDate` (type: `string`):

Only ads shown on or before this day (the day itself included).

## `maxResults` (type: `integer`):

Most ads a run returns, shared between the advertisers and domains. With Only changes: most changes a run returns (new ads first; the rest come with the next run).

## `maxAdsPerAdvertiser` (type: `integer`):

Most ads read per advertiser account or domain, newest shown first (Google lists up to tens of thousands for the biggest). 0 returns only each advertiser's row with Google's estimate of its ads: a quick check of which companies run Google ads.

## `accountsPerName` (type: `integer`):

For an advertiser given by name: how many of the accounts named so to read, biggest first (accounts with under a tenth of the biggest one's ads are left out).

## `maxAdDetails` (type: `integer`):

Read this many ads in full per run (at most 500): a text ad's copy (headline, description, display URL, sitelinks, callouts, locations) where Google serves it as text (some advertisers' text ads, not all), a video's YouTube link, a Shopping or Maps ad's words, the Google Ads account and ad group behind the ad, and every ad's variations, regions (with Google's times-shown ranges, topic and audience selection for ads shown in the EU) and platforms. About a second or two per ad. With Only changes, the changes are read first. 0 for the fastest runs.

## `onlyChanges` (type: `boolean`):

Monitor competitors: each run returns only what changed since the last run with the same advertisers and filters (new ads, ads that stopped running, ads running again). The first run saves the ads there now as the baseline and returns them as firstRun.

## `changeTypes` (type: `array`):

Which changes Only changes returns. Leave empty for all.

## `alertWebhookUrl` (type: `string`):

Post each run's changes to Slack, Discord or Microsoft Teams (their incoming-webhook URL), or to any HTTPS endpoint that takes JSON (Zapier, Make, n8n). Switches on Only changes. The first run posts a short 'alerts are set up' message.

## `alertChangeTypes` (type: `array`):

Which changes are posted. Leave empty for new ads and ads that stopped.

## `historyName` (type: `string`):

Keep a separate history for this monitor (a-z, 0-9 and hyphens). Leave empty to share the default one: histories are kept per advertiser and filters anyway.

## `proxy` (type: `object`):

Not needed: the Transparency Center answers Apify's servers directly. You can use your own proxies; residential proxies aren't available in this Actor.

## Actor input object example

```json
{
  "advertisers": [
    "nike.com"
  ],
  "region": "United States",
  "maxResults": 100,
  "maxAdsPerAdvertiser": 1000,
  "accountsPerName": 3,
  "maxAdDetails": 20
}
```

# Actor output Schema

## `ads` (type: `string`):

No description

## `changes` (type: `string`):

No description

## `copy` (type: `string`):

No description

## `details` (type: `string`):

No description

## `advertisers` (type: `string`):

No description

## `notFound` (type: `string`):

No description

## `allData` (type: `string`):

No description

## `runSummary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "advertisers": [
        "nike.com"
    ],
    "region": "United States",
    "maxResults": 100,
    "maxAdDetails": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("akhil_rajesh/google-ads-transparency-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "advertisers": ["nike.com"],
    "region": "United States",
    "maxResults": 100,
    "maxAdDetails": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("akhil_rajesh/google-ads-transparency-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "advertisers": [
    "nike.com"
  ],
  "region": "United States",
  "maxResults": 100,
  "maxAdDetails": 20
}' |
apify call akhil_rajesh/google-ads-transparency-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,akhil_rajesh/google-ads-transparency-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/9nBNPP3UdPDgfwyl1/builds/1XTCe7RW5zOwGdf2Z/openapi.json
