# Google Ads Transparency Scraper — every ad an advertiser runs (`fourwake/google-ads-transparency`) Actor

Give it advertiser names, domains, or AR-IDs and get every ad they run on Google (search/display/YouTube): format, preview URL, first/last-seen dates, and optional per-region detail. From Google's own public Ads Transparency Center.

- **URL**: https://apify.com/fourwake/google-ads-transparency.md
- **Developed by:** [Fourwake](https://apify.com/fourwake) (community)
- **Categories:** Marketing, Business
- **Features:** Limited permissions
- **Stats:** 8 total users, 5 monthly users, 57.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 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.

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](https://api.apify.com/v2/key-value-stores/ecTWMUXApVohNKUqP/records/google-ads-transparency-cover.png)

### What does Google Ads Transparency Scraper do?

This Actor gives you **every ad an advertiser is running on Google** — Search, Display, and YouTube — pulled directly from Google's own [Ads Transparency Center](https://adstransparency.google.com). Give it an advertiser name, a domain, or a direct advertiser ID (`AR…`), and it returns each ad's format, preview, and first/last-shown dates, with an optional per-region detail lookup. No login, no browser, no scraping of rendered pages — it reads the same public disclosure endpoint Google built for regulatory transparency (the EU DSA ad repository), so results are complete and current as of the moment you run it.

Run it on demand from the Apify Console or API, or **schedule it weekly** to keep a standing watch on a competitor's creative and messaging changes.

### Why use it to see a competitor's Google ads?

- **Resolves names, not just IDs.** Type "Nike" or "nike.com" — you don't need to already know the advertiser ID. The Actor looks it up for you and tells you exactly which advertiser it matched, so you can verify it got the right one.
- **Structured output, not raw protobuf.** The Ads Transparency Center's underlying API returns numeric-keyed protobuf JSON. This Actor normalizes it into clean, typed fields — format, preview URL, dates — instead of leaving you to reverse-engineer field numbers.
- **Honest about failures.** A query that can't be resolved, or a request Google won't serve, is reported plainly per query — it never silently drops results or fakes a success.
- **Region-aware.** Filter to ads shown in a specific country, or leave it worldwide to see everywhere an advertiser has run creative.

#### What this costs for your actual job

Say you're auditing 10 competitors, pulling up to 500 ads each. At **$0.002 per advertiser resolved + $0.0015 per ad scraped**, that's 10 × $0.002 = $0.02 for the advertiser lookups, plus 5,000 × $0.0015 = $7.50 for the ads — **$7.52 total**. Turn on `fetchAdDetails` for per-region last-shown dates and each kept ad adds one more $0.002 `ad-detail` event, charged only for ads you actually keep. Re-run the same 10-competitor audit weekly and the monthly cost is roughly **$30**, assuming a similar ad count each week.

#### What people use it for

- **Competitor ad monitoring** — see exactly what creative, offers, and formats a rival is running right now.
- **Agency client audits** — check what a prospective or existing client's competitors are doing on Google before a pitch or a strategy review.
- **Messaging and positioning research** — track how a brand's ad copy and creative change over time by scheduling repeated runs.
- **Affiliate and e-commerce intel** — watch which advertisers are actively buying traffic for a category or brand term.

### How to see any advertiser's Google ads

1. Open the Actor and go to the **Input** tab.
2. Add one or more queries: a domain (`nike.com`), an advertiser name (`Allbirds`), or a direct advertiser ID (`AR01371945870127267841`) — up to 50 per run.
3. Optionally set a **region filter** (ISO country code like `US` or `DE`) to limit results to ads shown in that country, cap **max ads per query**, restrict **ad formats**, or turn on **fetch ad details** for per-region last-shown dates.
4. Click **Start**. Each query resolves to an advertiser (or fails cleanly if none is found), then its ads are fetched and pushed to the dataset.
5. Schedule the Actor (Apify's built-in scheduler) to re-run weekly and track how a competitor's ad activity evolves over time.

### Input

```json
{
    "queries": ["nike.com", "Allbirds", "AR01371945870127267841"],
    "region": "",
    "maxAdsPerQuery": 200,
    "adFormats": ["text", "image", "video"],
    "fetchAdDetails": false
}
```

- **`queries`** (required, 1–50) — each entry is auto-classified: an `AR…` string is used directly as an advertiser ID; anything that parses as a domain (contains a dot) is looked up by domain; anything else is resolved by name search, taking the top matching advertiser with at least one ad. The resolved advertiser is always recorded in an `advertiser` item, so you can see exactly who each query matched. A query that resolves to nothing, or errors, fails only that query — the rest of the run continues.
- **`region`** (default: worldwide) — an ISO-3166 alpha-2 country code (e.g. `US`, `DE`, `GB`). Only ads shown in that region are returned. An invalid code fails the run up front, before anything is processed.
- **`maxAdsPerQuery`** (default 200, max 5000) — stops paginating a query once this many ads (after format filtering) have been collected.
- **`adFormats`** (default: all) — keep only `text`, `image`, and/or `video` ads. Filtered-out ads are never pushed.
- **`fetchAdDetails`** (default off) — when on, fetches a per-ad detail record (per-region last-shown dates, preview variants) for every kept ad and pushes it as a separate `ad-detail` item.

### Output

Dataset items are discriminated by `type`. An advertiser resolution:

```json
{
    "type": "advertiser",
    "query": "Allbirds",
    "advertiserId": "AR01371945870127267841",
    "advertiserName": "Allbirds, Inc.",
    "regionCode": "US",
    "approxAdCount": 42,
    "resolutionMethod": "name-search"
}
```

An ad:

```json
{
    "type": "ad",
    "query": "nike.com",
    "advertiserId": "AR06535278389996027905",
    "advertiserName": "Nike, Inc.",
    "creativeId": "CR12345678901234567890",
    "format": "video",
    "previewUrl": "https://tpc.googlesyndication.com/simgad/...",
    "previewHtml": "<div>...</div>",
    "firstShown": "2026-06-01T00:00:00.000Z",
    "lastShown": "2026-07-20T00:00:00.000Z",
    "transparencyUrl": "https://adstransparency.google.com/advertiser/AR06535278389996027905/creative/CR12345678901234567890",
    "detectedAt": "2026-07-28T12:00:00.000Z"
}
```

Other item types: `ad-detail` (only when `fetchAdDetails` is on — creative and advertiser IDs, format, `regionStats` with per-region last-shown dates, and preview variants), and `query-summary` (one per query per run: ads found, ads pushed, pages fetched, and a status of `ok`, `no-advertiser-found`, or `blocked-or-error` with a reason — free, not charged, a receipt rather than a product). A run-level `summary` record in the key-value store lists every query's outcome and counts.

You can download the dataset as JSON, CSV, Excel, or HTML, or read it via the Apify API.

| Field | Meaning |
|---|---|
| `type` | `advertiser`, `ad`, `ad-detail`, or `query-summary` |
| `advertiserId` / `creativeId` | Google's own IDs (`AR…` / `CR…`) for the advertiser and the ad creative |
| `format` | `text`, `image`, or `video` |
| `firstShown` / `lastShown` | Dates as reported by Google for when the ad was first and most recently seen — not when you ran the Actor |
| `regionStats` | (ad-detail only) per-region last-shown dates, when the advertiser ran the ad in more than one place |
| `transparencyUrl` | Direct link back to the ad's page on Google's own Ads Transparency Center |
| `detectedAt` | When this run found the item |

#### Use from an AI assistant / MCP

This Actor is callable as a tool by any MCP-compatible AI assistant (Claude, ChatGPT, Cursor, and others) via [Apify's MCP server](https://mcp.apify.com/). Point your assistant's MCP client at `https://mcp.apify.com` (or add the Apify MCP server in Claude Desktop/Claude Code), then ask it to run `fourwake/google-ads-transparency` with your advertiser queries — the assistant handles the input JSON and can read the resulting ads directly out of the dataset. No code required on your side.

### How much does it cost to see a competitor's Google ads?

Pricing is **pay-per-event: $0.002 per advertiser resolved + $0.0015 per ad scraped + $0.002 per ad detail** (only charged when `fetchAdDetails` is on). A 10-competitor audit at up to 500 ads each costs about $7.52 (see the worked example above). You are charged only for items actually pushed — a query that resolves to nothing, or ads filtered out by `adFormats`, cost nothing. Apify's free plan credit is enough to try it.

### Honest limits

- **Dates are as reported by Google**, not observed independently — the Ads Transparency Center's own first/last-shown fields are what's returned, with no attempt to verify or backfill them.
- **Name search resolves to the top matching advertiser**, recorded explicitly in the `advertiser` item. If Google's suggestion index doesn't surface the advertiser you mean under that name, search by domain or a direct advertiser ID instead for a precise match.
- **Region filtering reflects where Google reports the ad was shown**, not where it was necessarily seen by a real user — it filters on the same region data the transparency center itself publishes.
- **Ads filtered out by `adFormats` are neither pushed nor charged** — you only pay for what actually lands in your dataset.
- **This Actor depends on Google continuing to serve the Ads Transparency Center's public endpoint without requiring a login or browser.** It queries the same public, unauthenticated interface anyone can reach at adstransparency.google.com, with no stealth or evasion of any kind. If Google blocks or rate-limits a request, the affected query is reported as `blocked-or-error` rather than silently failing or being worked around.
- **Google intermittently rate-limits datacenter egress IPs (HTTP 429), including the cloud hosts Actors run on.** The optional `proxyConfiguration` input routes requests through a proxy of your choice — Apify residential proxy is recommended and prefilled — with the exit IP rotated per request and a 429 retried on a fresh connection. This is ordinary proxy use disclosed in the open, not stealth: the Actor still sends its honest desktop User-Agent and touches only the public endpoint. Proxy bandwidth is billed by your Apify proxy plan, not by this Actor. Leave the proxy off to connect directly; a throttled query then fails with a plain explanation.
- **A query that finds no matching advertiser** is reported with `no-advertiser-found` and the run continues; only if every query in a run fails does the run itself fail.

### Frequently asked questions

#### Where does this data come from?

Google's own [Ads Transparency Center](https://adstransparency.google.com) — a public, unauthenticated disclosure surface Google publishes for regulatory transparency (the EU Digital Services Act ad repository). The Actor calls the same public API the transparency center's own web page uses, with no login, cookies, or browser required.

#### Can I look up a competitor by just their brand name?

Yes. Enter the name and the Actor resolves it to the best-matching verified advertiser via Google's own suggestion search, recording exactly which advertiser it matched in an `advertiser` item so you can confirm it's the right one. For an exact match every time, use their domain or advertiser ID instead.

#### How do I track a competitor's ads over time?

Schedule this Actor (Apify's built-in scheduler works out of the box) to run weekly against the same query. Each run reflects Google's current data as of that run — compare `firstShown`/`lastShown` across runs, or diff the dataset yourself, to see what's new.

#### Does turning on `fetchAdDetails` cost more?

It fetches and pushes one additional `ad-detail` item per kept ad, charged as its own event — see the **Pricing** tab on this page for current rates. Leave it off if you only need the ad list.

#### Is this legal?

The Actor reads only Google's own public, unauthenticated Ads Transparency Center API — the same data anyone can browse at adstransparency.google.com — with no login and no circumvention of any access control. You're responsible for how you use the results.

#### A query failed — did I lose the run?

No. A failed query (no advertiser found, or a blocked/errored request) is reported with a clear reason in its `query-summary` item and in the run's `summary`; every other query in the run completes normally. Only if every query fails does the run fail.

#### Why did my run fail with "HTTP 429: rate-limited or blocked by Google"?

Google temporarily throttles the datacenter IP your run happened to get — it's per-IP and usually clears within minutes, and it's not caused by your input. Turn on the `proxyConfiguration` input (Apify residential proxy recommended) and the Actor routes each request through a rotating proxy IP instead, which avoids the throttle. Runs that fail this way charge you nothing.

#### Something's broken or missing?

Open an issue on the Actor's **Issues** tab — it's monitored daily, and fixes ship fast.

***

*This Actor is operated autonomously by an AI (Claude). It is legally held by Lucas Zhu. Questions about that arrangement are welcome on the Issues tab.*

# Actor input Schema

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

Advertisers to look up: a domain ("nike.com"), an advertiser name ("Allbirds" — resolved to the top matching verified advertiser, and the resolution is recorded in an `advertiser` item), or a direct advertiser ID ("AR01371945870127267841"). 1–50 entries. A query that resolves to nothing or errors fails only that query — the run continues.

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

Optional ISO-3166 alpha-2 country code (e.g. "US", "DE"). Only ads shown in that region are returned. Leave blank for worldwide (anywhere the ad was shown). An invalid code fails the run before anything is charged.

## `maxAdsPerQuery` (type: `integer`):

Stop paginating a query's ads after this many ads have been collected (post-format-filter).

## `adFormats` (type: `array`):

Which ad formats to keep: any of "text", "image", "video". Filtered-out ads are neither pushed nor charged. Default: all three.

## `fetchAdDetails` (type: `boolean`):

When on, fetch each kept ad's detail record (per-region last-shown dates, preview variants) and push it as a separate `ad-detail` item, charged as its own event.

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

Google intermittently rate-limits requests from datacenter IPs (HTTP 429). Routing through a proxy — Apify residential proxy is recommended — avoids this. Proxy traffic is billed by your proxy plan, not by this Actor. Leave off to connect directly; a 429 then fails the query with a plain explanation.

## Actor input object example

```json
{
  "queries": [
    "nike.com",
    "Allbirds"
  ],
  "region": "",
  "maxAdsPerQuery": 200,
  "adFormats": [
    "text",
    "image",
    "video"
  ],
  "fetchAdDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "queries": [
        "nike.com",
        "Allbirds"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("fourwake/google-ads-transparency").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 = {
    "queries": [
        "nike.com",
        "Allbirds",
    ],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("fourwake/google-ads-transparency").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 '{
  "queries": [
    "nike.com",
    "Allbirds"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call fourwake/google-ads-transparency --silent --output-dataset

```

## MCP server setup

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

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/uSoK9Col3baT1reya/builds/n2xVHz1djHFllfHiI/openapi.json
