# Google Ads Transparency Scraper — Competitor Ads & Monitor (`crawloop/google-ads-transparency-scraper`) Actor

Scrape Google Ads Transparency Center ads by domain, brand, or advertiser ID. Get creatives, landing URLs, days running, and region, and monitor new versus ended ads. A Google Ads Transparency API alternative for Python, Node.js, and MCP.

- **URL**: https://apify.com/crawloop/google-ads-transparency-scraper.md
- **Developed by:** [Andrej Kiva](https://apify.com/crawloop) (community)
- **Categories:** Lead generation, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.99 / 1,000 ad creatives

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Google Ads Transparency Scraper — Competitor Ads, Landing URLs & Monitor

> Unofficial tool for the public Google Ads Transparency Center. Google Ads and related names are trademarks of their respective owners. Not affiliated with, sponsored by, or endorsed by Google LLC. For informational, research, and competitive-intelligence use only. Respect applicable terms of use and law.

**Google Ads Transparency Scraper** ◄── you are here

Scrape **Google Ads Transparency Center** creatives into structured JSON: **ad format**, **landing URL**, **days running**, **region**, **first / last shown**, and image or video previews. Search by **domain**, **brand name**, or **advertiser ID**. Schedule **monitor** mode so a daily job emits only **new and ended ads**. A practical **Google Ads Transparency API alternative** — call from **Python**, **Node.js**, **cURL**, or **Apify MCP**.

Ideal for **agencies**, **D2C brands**, **creative research**, **PPC competitive intel**, and **brand-protection** workflows that need landing pages and longevity — not a silent empty dataset.

> **Crawloop digital intelligence** — competitor Google ads here, then creative-trend and app-store siblings.

| Google Ads Transparency (Search / YouTube / Display) | TikTok Creative Center (hashtags) | Google Play (ASO) |
| :--- | :--- | :--- |
| **Google Ads Transparency Scraper** ◄── you are here | [TikTok Trending Hashtags Scraper](https://apify.com/crawloop/tiktok-trending-hashtags-scraper) | [Google Play Scraper](https://apify.com/crawloop/google-play-scraper) |

### When to use this Actor

- You need a **Google Ads Transparency scraper** / **Google Ads Library** export for one or many competitors as JSON
- You want **landing URLs**, **days running**, and **region** on every creative — the fields agencies actually paste into swipe files
- You schedule **new vs ended** monitoring instead of re-downloading a 2,000-creative dump every morning
- You want a **Google Ads Transparency API alternative** from Python, Node.js, or an MCP / AI assistant
- You run an **ad-check** pass first (`advertisers` mode) to see who is actually spending on Google, then pull creatives for the shortlist

### When not to use this Actor

- **Official Google Ads API / MCC spend, bids, or keywords** — this Actor reads the **public Transparency Center**, not your ad accounts
- **Meta / Facebook Ad Library** — different library; this Actor is Google Search, YouTube, Shopping, Maps, and Play
- **Guaranteed impression or spend numbers on every commercial ad** — Google discloses those mainly for political ads; commercial rows still get dates, format, and assets
- **Silent “zero ads” as a real answer** — if Google’s own advertiser count is non-zero and the creative RPC returns empty, this Actor emits an **error row** instead of pretending the brand went dark

### Modes

| Mode | What it does |
| :--- | :--- |
| `ads` | Creatives for each domain / brand / AR ID (**default**) |
| `advertisers` | One summary row per advertiser (ad-check / lead-gen) |
| `monitor` | Named KV snapshot of creative IDs; emit **new** and **ended** (optional active) |

### Key features

- **Keyword-exact Google Ads Transparency scraper** — domain, brand query, advertiser ID, or pasted Transparency URLs
- **Buyer fields** — `daysRunning`, `region`, `firstShown` / `lastShown`, format, preview/image/video, plus `landingUrl` / headline when Google encodes them (text ads). Not OCR.
- **Monitor new and ended** — not only “only new”; ended creatives come back as tombstone rows with the last known landing URL
- **Loud empty** — payload drift and soft-blocks are error records, not a fake zero
- **Full token pagination** — continues past the first 40-ad page
- **Optional detail pass** — variations + per-country dates when Google discloses them
- **HTTP (no browser)** — Chrome-impersonated RPC, retries, and polite delays
- **Typed dataset rows** — `ad`, `advertiser`, `error`
- **Export-ready** — download the default dataset as JSON, CSV, Excel, or JSONL

### Input

| Parameter | Description |
| :--- | :--- |
| `mode` | `ads` / `advertisers` / `monitor` |
| `domains` / `queries` / `advertiserIds` | Websites, brand names, or AR… IDs |
| `startUrls` | Transparency Center advertiser, creative, or `?domain=` URLs |
| `region` | ISO country (`US`, `DE`) or `ANYWHERE` |
| `platforms` / `adFormat` | Search, YouTube, Shopping, Maps, Play; text / image / video |
| `dateFrom` / `dateTo` | Shown-after / shown-before (`YYYY-MM-DD`) |
| `maxAdsPerTarget` / `maxItems` | Caps |
| `includeDetails` | Extra RPC per ad (variations, regional dates) |
| `outputMode` | Monitor: `all` / `changes_only` / `new_only` / `ended_only` |
| `monitorStoreName` / `monitorBaselineOnly` | Named KV watermarks |
| `webhookUrl` / Telegram fields | Alerts on new and ended |
| `proxyConfiguration` | Residential recommended for scheduled bulk runs |

#### Example — competitor creatives

```json
{
  "mode": "ads",
  "domains": ["nike.com"],
  "region": "US",
  "maxAdsPerTarget": 100,
  "includeDetails": false
}
```

#### Example — daily new / ended monitor

```json
{
  "mode": "monitor",
  "advertiserIds": ["AR04119126533128323073"],
  "region": "US",
  "outputMode": "changes_only",
  "monitorStoreName": "nike-us-ads-monitor",
  "maxAdsPerTarget": 500
}
```

### Output

| Field | Description |
| :--- | :--- |
| `type` | `ad`, `advertiser`, or `error` |
| `changeType` | `new` / `active` / `ended` (monitor) |
| `creativeId` / `advertiserId` / `advertiserName` | Stable Google IDs and display name |
| `format` | `text`, `image`, `video` |
| `headline` / `description` | Search-ad copy when the preview payload decodes |
| `landingUrl` | Destination URL when the creative encodes one (typical for Search/text ads) |
| `imageUrl` / `videoUrl` / `previewUrl` | Creative assets |
| `firstShown` / `lastShown` / `daysRunning` | Longevity |
| `region` | Requested country or `ANYWHERE` |
| `adUrl` | Deep link back to the Transparency Center creative |
| `regionsShown` / `variations` | Only when `includeDetails` is on |

#### Ad output example

```json
{
  "type": "ad",
  "changeType": "new",
  "creativeId": "CR12965115384414863361",
  "advertiserId": "AR04119126533128323073",
  "advertiserName": "Nike, Inc.",
  "domain": "nike.com",
  "format": "image",
  "landingUrl": "https://www.nike.com/launch",
  "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/33210746.png",
  "firstShown": "2024-01-01",
  "lastShown": "2024-08-01",
  "daysRunning": 214,
  "region": "US",
  "adUrl": "https://adstransparency.google.com/advertiser/AR04119126533128323073/creative/CR12965115384414863361?region=us"
}
```

You can download the dataset as JSON, CSV, Excel, or JSONL from the run.

### How to scrape Google Ads Transparency Center

1. Open this Actor and keep **mode** on `ads` (or `monitor` for a scheduled diff).
2. Paste competitor **domains**, **brand names**, or **AR… advertiser IDs**.
3. Set **region** (for example `US`) and an optional **max ads per target**.
4. For a daily watch, set `mode` to `monitor`, give the run a **monitor store name**, and schedule it.
5. Run. Export the default dataset or pull it from the Apify API / MCP.

### Use cases

- **Agency swipe files** — pull live Search / YouTube / Display creatives plus landing URLs
- **D2C competitor watch** — schedule monitor mode; wake up to new launches and killed tests
- **Brand protection** — see who is bidding around a domain and how long each creative has been up
- **Lead-gen ad-check** — `advertisers` mode: which companies in a list actually run Google Ads
- **Creative research** — filter image vs video vs text, sort by `daysRunning` as a proxy for what survived

### Integration examples

#### Node.js

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('crawloop/google-ads-transparency-scraper').call({
  mode: 'ads',
  domains: ['nike.com'],
  region: 'US',
  maxAdsPerTarget: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("crawloop/google-ads-transparency-scraper").call(
    run_input={
        "mode": "ads",
        "domains": ["nike.com"],
        "region": "US",
        "maxAdsPerTarget": 50,
    }
)
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item.get("creativeId"), item.get("landingUrl"), item.get("daysRunning"))
```

#### cURL

```bash
curl "https://api.apify.com/v2/acts/crawloop~google-ads-transparency-scraper/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"mode\":\"ads\",\"domains\":[\"nike.com\"],\"region\":\"US\",\"maxAdsPerTarget\":50}"
```

### MCP and AI assistants

Use this Actor from AI tools via [Apify MCP](https://docs.apify.com/platform/integrations/mcp).
Connect your Apify account, then call this Actor by its Store ID / name.

Example prompts:

- "Run Google Ads Transparency Scraper for nike.com in US and return the top 20 ads with landing URL, days running, and format as JSON"
- "Monitor Google Ads Transparency for advertiser AR04119126533128323073 and list only new and ended creatives"
- "Chain Google Ads Transparency Scraper then [TikTok Trending Hashtags Scraper](https://apify.com/crawloop/tiktok-trending-hashtags-scraper) for the same brand's paid-search vs short-form creative trends"

### Suite next step

After Google ads, run [TikTok Trending Hashtags Scraper](https://apify.com/crawloop/tiktok-trending-hashtags-scraper) for Creative Center trends, or [Google Play Scraper](https://apify.com/crawloop/google-play-scraper) for the same brand's app-store presence.

### FAQ

**Is this a Google Ads Transparency API alternative?**
Yes for the **public** Transparency Center — creatives, dates, region, and assets — without a Google Ads API token. It is not a replacement for the official Ads API (spend, keywords, conversions).

**How do I scrape Google Ads Transparency with Python or Node.js?**
Call `crawloop/google-ads-transparency-scraper` with the Apify client (examples above) or from an MCP assistant. Results land in the default dataset.

**Ads mode vs monitor mode?**
`ads` dumps the current creative set. `monitor` diffs creative IDs against the previous run in a named Key-Value Store and can emit **new** and **ended** only (`outputMode: changes_only`). Seed the first run with `monitorBaselineOnly` if you do not want a full dump on day one.

**Why do some scrapers return empty?**
The Transparency Center RPC fails closed: a missing required field or a payload reshuffle returns `{}`, which looks like “this advertiser has zero ads.” This Actor paginates with the required request fields, retries 429/5xx, and emits an **error row** when Google’s own advertiser count is non-zero but creatives do not come back.

**Do I need a Google login?**
No. The Transparency Center is public.

**Does region always filter the result set?**
The Actor sends the Transparency Center region enum (ISO numeric + 2000). Some commercial creatives still appear globally; `region` is always stored on the row so you can run parallel country jobs and label exports.

**Do asset URLs expire?**
Preview / `simgad` links can rot. Pull the dataset when the run finishes, or turn on `includeDetails` when you need every variation immediately.

**Why is `landingUrl` empty on some image ads?**
Google often omits the click-through URL on image/HTML5 creatives in the public RPC. Search/text ads usually decode a destination. This Actor does not OCR landing pages off screenshots.

**Can I pass Transparency Center URLs?**
Yes — advertiser pages, creative pages, and `?domain=` searches are parsed automatically.

### Related Actors

- [TikTok Trending Hashtags Scraper](https://apify.com/crawloop/tiktok-trending-hashtags-scraper)
- [Google Play Scraper](https://apify.com/crawloop/google-play-scraper)
- [Product Hunt Scraper](https://apify.com/crawloop/producthunt-scraper)
- [Trustpilot Scraper](https://apify.com/crawloop/trustpilot-scraper)

# Actor input Schema

## `mode` (type: `string`):

ads = creatives (default). advertisers = one summary row per advertiser (ad-check / lead-gen). monitor = snapshot creative IDs in a named KV store and emit new + ended ads.

## `domains` (type: `array`):

Advertiser websites (nike.com). Protocol and www are stripped. Best starting point for competitor intel.

## `queries` (type: `array`):

Free-text advertiser names resolved via Transparency Center suggestions (Nike, HelloFresh). Use when you do not have the AR… ID yet.

## `advertiserIds` (type: `array`):

Stable Google advertiser IDs starting with AR (from the Transparency Center URL). Deterministic — preferred for scheduled monitors.

## `startUrls` (type: `array`):

Paste Ads Transparency Center URLs: advertiser pages, creative pages, or ?domain= search pages.

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

ISO 3166-1 alpha-2 country (US, DE, GB) or ANYWHERE. Applied as a Transparency Center region filter when the RPC accepts it; the value is always stored on each row.

## `platforms` (type: `array`):

Restrict to Google surfaces. Empty = all. Google only applies platform filters to ads shown on/after 2023-09-04.

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

Filter by creative format.

## `dateFrom` (type: `string`):

Keep ads whose last-shown date is on or after this day (YYYY-MM-DD).

## `dateTo` (type: `string`):

Keep ads whose first-shown date is on or before this day (YYYY-MM-DD).

## `maxAdsPerTarget` (type: `integer`):

Cap creatives per domain/advertiser. 0 = paginate until Google stops (still bounded by a safety page cap).

## `maxAdvertisersPerQuery` (type: `integer`):

When a brand name matches several AR accounts, how many to scrape.

## `maxItems` (type: `integer`):

Hard cap on pushed rows (all types). 0 = unlimited.

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

One extra RPC per ad: variations plus per-country first/last shown when Google discloses them. Slower; billed as a separate event.

## `outputMode` (type: `string`):

In monitor mode: all = new + active + ended; changes\_only = new + ended; new\_only / ended\_only = one side.

## `monitorStoreName` (type: `string`):

Named Key-Value Store for seen creative IDs. Use a distinct name per competitor set so histories do not mix. Alias: monitorId.

## `monitorBaselineOnly` (type: `boolean`):

First run: seed KV creative IDs without emitting rows or webhooks.

## `resetMonitorState` (type: `boolean`):

Clear MONITOR\_STATE in the named store before this run.

## `webhookUrl` (type: `string`):

Slack / Discord / custom HTTPS endpoint for monitor alerts (JSON POST).

## `telegramToken` (type: `string`):

Optional Telegram bot token for monitor alerts.

## `telegramChatId` (type: `string`):

Telegram chat/user ID for alerts (requires token).

## `notifyOnNewAds` (type: `boolean`):

Send webhook/Telegram when a creative ID appears that was not in the previous snapshot.

## `notifyOnEndedAds` (type: `boolean`):

Send webhook/Telegram when a previously seen creative ID is gone from the current snapshot.

## `includeRawData` (type: `boolean`):

Attach decoded proto-JSON on each row for debugging. Off by default.

## `requestDelaySecs` (type: `number`):

Polite spacing. Raise if you see HTTP 429.

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

Residential proxies recommended for scheduled bulk monitors. Datacenter often works for small lookups.

## Actor input object example

```json
{
  "mode": "ads",
  "domains": [
    "nike.com"
  ],
  "region": "US",
  "platforms": [],
  "adFormat": "ALL",
  "maxAdsPerTarget": 100,
  "maxAdvertisersPerQuery": 5,
  "maxItems": 0,
  "includeDetails": false,
  "outputMode": "changes_only",
  "monitorStoreName": "google-ads-transparency-monitor",
  "monitorBaselineOnly": false,
  "resetMonitorState": false,
  "notifyOnNewAds": true,
  "notifyOnEndedAds": true,
  "includeRawData": false,
  "requestDelaySecs": 0.35,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Default dataset items.

# 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 = {
    "domains": [
        "nike.com"
    ],
    "region": "US"
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawloop/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 = {
    "domains": ["nike.com"],
    "region": "US",
}

# Run the Actor and wait for it to finish
run = client.actor("crawloop/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 '{
  "domains": [
    "nike.com"
  ],
  "region": "US"
}' |
apify call crawloop/google-ads-transparency-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawloop/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/hBTGRylesyvT7iddY/builds/2yQvewXhc17wpNqQI/openapi.json
