# Google Ads Transparency Scraper & New Ads Monitor (`babymum7/google-ads-monitor`) Actor

Scrape competitors' Google ads from the Ads Transparency Center, then pay only for new ones. Text, image and video ads with their copy and dates, on a schedule.

- **URL**: https://apify.com/babymum7/google-ads-monitor.md
- **Developed by:** [Trong Nguyen](https://apify.com/babymum7) (community)
- **Categories:** Lead generation, SEO tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 ads

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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 & New Ads Monitor

Know the week a competitor launches a new Google ad. Add their websites, put the scraper on a schedule, and get back only the ads that were not there last time: text, image and video ads with their headlines and descriptions, straight from the public [Google Ads Transparency Center](https://adstransparency.google.com/).

Most Ads Transparency scrapers hand you every ad an advertiser has running, every time. That is fine once. Run it each morning on five competitors and you pay for the same thousand rows again and still have to work out what changed. This one remembers what it has already shown you. The first run saves a baseline. After that, a quiet day returns nothing and costs nothing, and a launch day returns just the launch.

### Who uses it

- **PPC managers and agencies** see the new offers in a client's market before the client asks about them.
- **E-commerce and DTC brands** catch a rival's sale, bundle or product launch the week it goes live.
- **SaaS marketers** follow how competitors pitch free trials, pricing changes and new features.
- **Creative teams** build a swipe file of the image and video ads advertisers keep paying to run.

### Why monitor instead of re-scraping

Watching 5 competitors every day, 200 recent ads each, at the same price per ad:

| | Re-scrape everything daily | This Actor |
| --- | --- | --- |
| Ads you pay for each day | 1,000 | Only the new ones |
| Cost over 30 days | about $45 | $1.50 for the baseline, then cents (10 new ads a day comes to $0.45) |
| What changed today | You compare the lists yourself | Every row is new, marked `isNew: true` |

### What you get

- The ads an advertiser runs across Google Search, YouTube, Shopping, Maps and Play, as listed in the Transparency Center
- The advertiser's verified name and ID, the ad format, the first and last day it ran, and how many days it was shown
- The headline, description and display URL of each text ad, and the words on image ads. Google publishes most text ads as pictures; the Actor reads them for you
- An image of each ad, a preview link for video ads, and a link to the ad's own page in the Transparency Center
- On request, the countries each ad ran in with dates, Google's impression ranges where it publishes them (EU countries), and every variation of the ad
- Results in JSON, CSV, Excel or HTML, through the API, or sent on to Slack, Google Sheets, Make, Zapier or n8n

### How to see your competitors' Google ads

1. In **Advertisers**, enter a competitor's website (`nike.com`), an advertiser ID (`AR16735076323512287233`), or an advertiser page URL from the Transparency Center.
2. Choose a **Country** to see ads shown there, or leave it on Anywhere. Narrow it to text, image or video ads if you like.
3. Click **Start**. The first run lists their current ads and saves them as your baseline.
4. Turn **Only new ads** on and add a daily or weekly schedule with this input. From now on each run returns only new ads.

With **Only new ads** off, every run returns every ad, each still marked new or not. Through the API it is on unless you turn it off.

### Examples

#### 1. Get a message when a competitor launches new ads

1. Open the **Input** tab, put your competitors in **Advertisers** (for example `adidas.com` and `puma.com`), set **Country** to where you sell, and turn **Only new ads** on.
2. Click **Start**. This first run saves what they show today.
3. In **Schedules**, create a daily schedule for this Actor with the same input ([how schedules work](https://docs.apify.com/platform/schedules)).
4. On the Actor's **Integrations** tab, add Slack or email so each finished run sends you its new ads ([Apify integrations](https://docs.apify.com/platform/integrations)).

From then on, a quiet day costs almost nothing and a launch day lands in your inbox.

#### 2. Pull an advertiser's whole video library once

```json
{
  "advertisers": ["https://adstransparency.google.com/advertiser/AR16735076323512287233?region=GB"],
  "region": "GB",
  "format": "video",
  "onlyNewAds": false,
  "maxAdsPerAdvertiser": 2000
}
```

With **Only new ads** off, every run returns all ads, so you can repeat it without touching your monitoring baseline. Each video row has a `previewUrl`.

#### 3. Call it from your own code

The API returns the ads in the same request:

```bash
curl -X POST "https://api.apify.com/v2/acts/babymum7~google-ads-monitor/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"advertisers": ["nike.com"], "region": "US"}'
```

That request waits up to 5 minutes, enough for about 500 ads with their text. For bigger runs use the Python client
below, which waits as long as the run takes.

Or with Python (`pip install "apify-client>=3"`):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("babymum7/google-ads-monitor").call(run_input={"advertisers": ["nike.com"], "region": "US"})
for ad in client.dataset(run.default_dataset_id).iterate_items():
    if ad["isNew"]:
        print(ad["firstShown"], ad["format"], ad["headline"], ad["adUrl"])
```

#### What it costs

| Run | Ads returned | Cost |
| --- | --- | --- |
| Baseline for 1 advertiser, default limit | 200 | $0.30 |
| Daily check, 5 advertisers, 8 new ads | 8 | $0.012 |
| Daily check with nothing new | 0 | $0 for ads |

### Ready-made tasks

Each of these opens with the input already filled in. Try one, then put in your own advertisers.

| Task | What it shows |
| --- | --- |
| [Get alerts when competitors launch new Google ads](https://apify.com/babymum7/google-ads-monitor/examples/competitor-new-google-ads-alerts) | Only new ads on each scheduled run |
| [See every Google ad a competitor is running](https://apify.com/babymum7/google-ads-monitor/examples/see-competitors-google-ads) | One advertiser's text, image and video ads |
| [Export Google Ads Transparency Center data to CSV or Excel](https://apify.com/babymum7/google-ads-monitor/examples/export-google-ads-transparency-data) | Up to 500 ads in one download |
| [Find competitors' YouTube and Google video ads](https://apify.com/babymum7/google-ads-monitor/examples/competitor-youtube-video-ads) | Video ads with preview links |
| [Get Google Ads Transparency Center data through an API](https://apify.com/babymum7/google-ads-monitor/examples/google-ads-transparency-api) | Ads as JSON from one API call |
| [Analyze SaaS competitors' Google ads](https://apify.com/babymum7/google-ads-monitor/examples/saas-competitor-google-ads) | HubSpot, Salesforce, monday.com |
| [Monitor UK retailers' Google ads](https://apify.com/babymum7/google-ads-monitor/examples/uk-retailer-google-ads) | Tesco, Sainsbury's, Argos, John Lewis in the UK |
| [Track German online shops' Google ads](https://apify.com/babymum7/google-ads-monitor/examples/germany-online-shop-google-ads) | Zalando, Otto, About You in Germany |
| [Research travel sites' Google Search ads](https://apify.com/babymum7/google-ads-monitor/examples/travel-google-search-ads) | Booking.com, Expedia, Kayak, Hotels.com text ads |

### Input reference

```json
{
  "advertisers": ["nike.com", "adidas.com", "AR14842347578342768641"],
  "region": "US",
  "format": "all",
  "onlyNewAds": true,
  "readAdText": true,
  "maxAdsPerAdvertiser": 200,
  "ownAdsOnly": false,
  "includeDetails": false
}
```

| Field | What it does |
| --- | --- |
| `advertisers` | Websites, advertiser IDs (`AR...`) or Transparency Center advertiser URLs |
| `region` | A country code or name (`US`, `UK`, `Germany`), or `anywhere` |
| `format` | `all`, `text`, `image` or `video` |
| `onlyNewAds` | Return only ads not seen in earlier runs (the first run is the baseline) |
| `readAdText` | Read the headline, description and display URL of text ads, and the words on image ads. About half a second per ad returned |
| `maxAdsPerAdvertiser` | How many ads to check per advertiser and run |
| `ownAdsOnly` | For a website, keep only ads from advertisers carrying its brand name and drop agencies, resellers and partners that link to it |
| `includeDetails` | Add regions with dates, impression ranges and variations; one extra request per ad |

### Output example

Each ad is one row in the dataset. Export it as JSON, CSV, Excel, or HTML, or read it through the API.

```json
{
  "isNew": true,
  "advertiserId": "AR16735076323512287233",
  "advertiserName": "Nike, Inc.",
  "domain": "nike.com",
  "creativeId": "CR00181255934947885057",
  "format": "text",
  "headline": "Zoom Vomero Running Shoes. Nike.com",
  "description": "Shop The Official Nike Store For The Latest Nike Shoes, Apparel & Gear. Gear Up For Sport And Style With Nike Products Designed For Performance And Comfort. Live Support Available. Styles: Vaporfly NEXT%, Zoom Fly, Joyride Flyknit, Pegasus.",
  "displayUrl": "www.nike.com/",
  "adText": "Nike\nwww.nike.com/\nZoom Vomero Running Shoes.\nNike.com\nShop The Official Nike Store For The Latest Nike\n...",
  "firstShown": "2022-11-30",
  "lastShown": "2026-11-04",
  "daysShown": 1387,
  "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/11964775834604724905",
  "previewUrl": null,
  "adUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR00181255934947885057?region=US"
}
```

| Field | Meaning |
| --- | --- |
| `isNew` | `true` when the ad started running after the previous run (with three days' leeway) and no earlier run returned it, for this advertiser, region, and format |
| `advertiserName`, `advertiserId`, `domain` | Who paid for the ad |
| `format` | `text`, `image`, or `video` |
| `headline`, `description`, `displayUrl` | The words of a text ad; `null` for video ads |
| `adText` | Every line of text on the ad, including sitelinks and ratings; for image ads, the words on the banner |
| `firstShown`, `lastShown`, `daysShown` | When Google first and last showed the ad, and for how many days |
| `imageUrl` | Image of the ad (text ads are shown as images too) |
| `previewUrl` | Preview script for video and rich ads |
| `adUrl` | The ad's page in the Transparency Center |
| `regions`, `impressionsMin`, `impressionsMax`, `variations` | With **Regions, impressions and variations** on: each country with first and last shown dates and an impression range where Google publishes one, the ad's overall impression range, and a link to every variation |

### How "new" is decided

The Actor keeps the creative IDs it has returned in a named key-value store in your account (`google-ads-monitor-state`), one record per advertiser, region, and format. A run compares what Google shows now with that record. Change the region or format and the Actor treats it as a new watch list with its own baseline. Delete the store to start over.

An ad counts as new only if its first day shown is no more than three days before the previous run and no earlier run returned it. The date check matters: Google lists the ads of an advertiser with thousands running at once in a different order on every request, so an ad from 2021 can be missing from one run and turn up in the next without being new.

After the baseline, each run asks Google only for ads shown since the previous run (three days' leeway), up to **Max ads per advertiser**. For most advertisers that is a short list, read to the end. For the largest ones (Google counts about 10,000 `nike.com` ads shown in three days) the default of 200 is only a sample, and the run's status says so, for example *checked 200 of about 10,000 ads shown since 2026-11-02*. Raise **Max ads per advertiser** to check them all: in our test 2,000 ads took 17 seconds, and you pay only for the new ads it finds.

### Pricing

$1.50 per 1,000 ads returned, and nothing else to pay for: no start fee and no charge for compute. Paid Apify plans get the same ads for less:

| Apify plan | Per 1,000 ads |
| --- | --- |
| Free | $1.50 |
| Starter (Bronze) | $1.20 |
| Scale (Silver) | $1.00 |
| Business (Gold) and up | $0.80 |

A scheduled run that finds nothing new costs nothing for ads. If one advertiser fails, the run says so in its status and in the `SUMMARY` record and carries on with the rest.

### FAQ

**How do I see my competitors' Google ads?** Enter their website in **Advertisers** and run the scraper. You get every ad Google lists for them in the Ads Transparency Center, with dates, format and a link to each ad.

**Do I need a Google Ads account or API key?** No. The Ads Transparency Center is public, so all you need is an Apify account.

**Is this data public?** Yes. Google publishes it in the Ads Transparency Center for anyone to view, without logging in.

**Can I see how much a competitor spends?** Not for commercial ads. Google does not publish spend in the Transparency Center. In EU countries it does publish impression ranges: turn on **Regions, impressions and variations** to get them. Elsewhere, `daysShown` and how long an ad keeps running are the best clues to what is working.

**Can I get the ad copy?** Yes. Google publishes most text ads as pictures, and the Actor reads the headline, description and display URL from them. Ads are read in the language of the country you search, so German, French, Spanish, Italian, Portuguese and Dutch ads keep their accents (für, großen instead of fur, groRen); with **Region** set to anywhere, the advertiser's domain decides (zalando.de reads as German). Seller ratings and store addresses are left out of the description. Reading a picture can get a character wrong now and then, so `imageUrl` always links the original. Ads written in Thai, Cyrillic, Chinese and other non-Latin scripts come back with empty text fields rather than misread ones. Reading takes about half a second per ad returned, so a 200-ad first run takes about a minute and a half; scheduled runs only read the new ads. Turn off **Read the ad text** if you only need dates and links. Google does not publish the landing page itself, only the display URL.

**Why do I see ads from other companies for a domain?** Google lists every advertiser whose ads link to that website, including agencies, resellers and partners. Turn on **Only the advertiser's own ads** to keep just the ones carrying the brand's name.

**Why did an old ad show up as new?** If an advertiser restarts an ad that was beyond your **Max ads per advertiser** limit when the baseline was taken, it counts as new to you.

This Actor is independent and not affiliated with Google.

# Actor input Schema

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

Who to watch. Enter a competitor's website (nike.com), an advertiser ID from the Ads Transparency Center (AR16735076323512287233), or the advertiser's page URL. One per line, as many as you like.

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

Only ads shown in this country. Pick from the list or type a code or name (US, UK, Germany). Leave it on Anywhere to see ads from every country.

## `format` (type: `string`):

Limit the results to text, image or video ads. Text ads come as an image of the ad, the way Google publishes them.

## `onlyNewAds` (type: `boolean`):

On: the first run saves each advertiser's current ads, and every run after that returns only ads that started running since the previous run. Turn it on for a daily or weekly schedule. Off: every run returns all ads, each still marked new or not, and an existing baseline is left as it is.

## `readAdText` (type: `boolean`):

Adds the headline, description and display URL of each text ad, and the words on image ads. Google publishes most text ads as pictures, so this reads them, which takes about half a second per ad returned (a 100-ad first run takes under a minute; later runs read only the new ads). Turn it off if you only need links and dates.

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

How many ads to check per advertiser and run. After the first run only ads shown since the previous run are checked, so 200 covers most advertisers; for the largest (thousands of ads running at once) the run checks a sample and says so in its status. Raise it to check them all, or to export an advertiser's full history.

## `ownAdsOnly` (type: `boolean`):

For a domain, drop ads from other companies that link to it, such as agencies, resellers or partners (Nike, Inc. and Nike Retail BV stay for nike.com; an agency's ads do not). Advertiser IDs are never filtered.

## `includeDetails` (type: `boolean`):

Adds the countries each ad ran in with dates, Google's impression ranges where it publishes them (EU countries), and every variation of the ad. One extra request per ad, so runs take longer.

## `proxyConfiguration` (type: `object`):

Apify Proxy spreads requests across IP addresses so big runs are not rate-limited. The default works for most runs.

## Actor input object example

```json
{
  "advertisers": [
    "nike.com"
  ],
  "region": "anywhere",
  "format": "all",
  "onlyNewAds": false,
  "readAdText": true,
  "maxAdsPerAdvertiser": 40,
  "ownAdsOnly": false,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `summary` (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"
    ],
    "onlyNewAds": false,
    "maxAdsPerAdvertiser": 40
};

// Run the Actor and wait for it to finish
const run = await client.actor("babymum7/google-ads-monitor").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"],
    "onlyNewAds": False,
    "maxAdsPerAdvertiser": 40,
}

# Run the Actor and wait for it to finish
run = client.actor("babymum7/google-ads-monitor").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"
  ],
  "onlyNewAds": false,
  "maxAdsPerAdvertiser": 40
}' |
apify call babymum7/google-ads-monitor --silent --output-dataset

```

## MCP server setup

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

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/AJziPzGnVARapbe9f/builds/UVsxX1hp5Jl1goVkY/openapi.json
