# Google Ads Transparency | $2.99 / 1k | (`glasswing/ads-transparency-scraper`) Actor

See every ad a competitor is running. Search by domain or advertiser ID and get ad format, first and last shown dates, days live, creative preview and target regions. Export to CSV, JSON or Excel.

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

## Pricing

from $2.99 / 1,000 results

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?

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

### What does Google Ads Transparency do?

**See every ad a competitor is running right now.** Type `nike.com` and get one row per creative — search text ads, display banners and video — with the countries each ad ran in, the day it started, the day it was last seen and how many days it has been live. Performance marketers use it for competitive ad research, creative strategists use it to find the ads a brand keeps paying for, and compliance teams use it to check what an advertiser is actually claiming in market.

The Actor reads the **public [Google Ads Transparency Center](https://adstransparency.google.com/)** and turns it into clean JSON, CSV or Excel. It works as a **Google Ads Transparency Center API alternative**: give it a website domain, an advertiser id or an advertiser page URL and get results in seconds — no browser, no residential proxies, no scraper to maintain.

✨ **Try it:** press **Start** with the prefilled domains. Twenty ads land in about five seconds.

🔎 **Search by website, not just by id.** Most tools want an advertiser id. This one takes a plain domain and returns the ads of *every* advertiser account that verified that website — brand accounts, regional entities and agencies alike.

### Use cases: competitive ad research, creative inspiration, advertiser verification

- 🎯 **Performance marketers doing competitive ad research.** Pull every live creative of five competitors before a campaign kickoff and see which offers they keep running, which they dropped, and which countries they are pushing hardest.
- 💡 **Creative strategists looking for inspiration that works.** Collect image and video creatives across a category and sort by `daysShown`: the ads an advertiser has been paying for the longest are the ads that survived their own testing.
- ✅ **Brand, legal and compliance teams verifying an advertiser's claims.** Check what a partner, reseller or affiliate is really saying in paid search, in which markets, and since when — with a public source URL you can cite in the ticket.
- 📅 **Agencies monitoring clients and prospects.** Schedule a daily run per client domain and alert on new creatives, new countries or ads that suddenly disappeared. The same data makes a persuasive new-business pitch deck.
- 🔬 **Researchers, analysts and journalists building ad datasets.** Assemble a longitudinal record of advertiser activity per country for market analysis, ad-tech research or brand-safety work.
- 🛒 **E-commerce and affiliate teams sizing a niche.** Count how many advertisers and creatives are live around a product category and how long the average creative survives, before committing budget.

The Actor does not log in, does not defeat access controls and does not collect private user data. It reads only what the Ads Transparency Center publishes to everyone.

### What data you get

One row per ad (per creative). Fields are omitted when the source does not publish them; a missing field is honest, never a guess.

**Who advertised**

| Field | Type | What it tells you |
|---|---|---|
| `advertiserName` | string | Verified business name of the advertiser, e.g. `Nike Retail BV`. |
| `advertiserDomain` | string | Website the advertiser verified, e.g. `nike.com`. Filled when you search by domain. |
| `advertiserId` | string | Advertiser account id, e.g. `AR18378488041124659201`. Stable, and usable as input for a follow-up run. |

**The ad and its flight**

| Field | Type | What it tells you |
|---|---|---|
| `adFormat` | string | `text` (search and text ads), `image` (uploaded display banners), `video`, or `unknown`. |
| `firstShown` | string | ISO 8601 date-time the ad was first recorded as shown. |
| `lastShown` | string | ISO 8601 date-time the ad was last recorded as shown. |
| `daysShown` | integer | How many days the ad was recorded as running. A high number with a recent `lastShown` marks an evergreen winner. |
| `regions` | array | ISO 3166-1 alpha-2 codes of every country the ad ran in, e.g. `["BE","DE","ES","FR","IT"]`. |
| `regionCount` | integer | How many country entries the source published for this ad. |
| `adId` | string | Creative id of this ad, e.g. `CR09696740594663030785`. Unique per advertiser. |

**Creative and run metadata**

| Field | Type | What it tells you |
|---|---|---|
| `previewUrl` | string | Google-hosted rendered preview of the creative — open it in a browser to see the ad. |
| `imageUrl` | string | Direct URL of the creative image, when the source publishes one instead of a rendered preview. |
| `searchRegion` | string | Region the search was scoped to: `anywhere` or an alpha-2 code. |
| `searchTerm` | string | The input entry (domain, advertiser id or URL) this ad was found through — handy when you pass 50 domains in one run. |
| `url` | string | Public Ads Transparency Center page of this ad. |
| `status` | string | `ok`, `not_found` or `error` (see below). |
| `error` | string | Reason when `status` is not `ok`. |
| `scrapedAt` | string | ISO 8601 time of extraction. |

The Ads Transparency Center publishes creatives as rendered previews, so ads carry `previewUrl` and/or `imageUrl` rather than raw headline text. Video ads are published as a preview you can open. The Actor never renders JavaScript, so it does not invent creative copy the source does not publish.

#### Result status (tri-state output)

| `status` | Meaning | Billed? |
|---|---|---|
| `ok` | The ad was found and extracted. | Yes |
| `not_found` | The source answered, but this advertiser publishes no ads for the chosen region and format. | No |
| `error` | The source could not be read after retries (rate limiting, network error, or a change in the endpoint). `error` says why. | No |

### Output

Export the dataset as JSON, HTML, CSV or Excel, or read it from the API. Real rows from a run with the default input:

```json
[
    {
        "url": "https://adstransparency.google.com/advertiser/AR18378488041124659201/creative/CR09696740594663030785?region=anywhere",
        "status": "ok",
        "scrapedAt": "2026-09-08T11:50:13.816Z",
        "advertiserId": "AR18378488041124659201",
        "advertiserName": "Nike Retail BV",
        "advertiserDomain": "nike.com",
        "adId": "CR09696740594663030785",
        "adFormat": "text",
        "firstShown": "2026-07-21T12:24:03.000Z",
        "lastShown": "2026-09-08T11:26:19.000Z",
        "daysShown": 50,
        "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/9612903277308998192",
        "searchRegion": "anywhere",
        "searchTerm": "nike.com",
        "regions": ["BE", "DE", "ES", "FR", "GP", "GR", "IT", "LU", "MQ", "PT", "RE"],
        "regionCount": 11
    },
    {
        "url": "https://adstransparency.google.com/advertiser/AR18378488041124659201/creative/CR15825683433138421761?region=anywhere",
        "status": "ok",
        "scrapedAt": "2026-09-08T11:50:13.816Z",
        "advertiserId": "AR18378488041124659201",
        "advertiserName": "Nike Retail BV",
        "advertiserDomain": "nike.com",
        "adId": "CR15825683433138421761",
        "adFormat": "text",
        "firstShown": "2025-10-22T17:43:25.000Z",
        "lastShown": "2026-09-08T11:24:36.000Z",
        "daysShown": 139,
        "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/8552597266371592728",
        "searchRegion": "anywhere",
        "searchTerm": "nike.com",
        "regions": ["DE", "FR", "NL"],
        "regionCount": 3
    },
    {
        "url": "https://adstransparency.google.com/?region=anywhere&domain=example-with-no-ads.com",
        "status": "not_found",
        "error": "No ads published for \"example-with-no-ads.com\" in region anywhere",
        "scrapedAt": "2026-09-08T11:50:14.002Z"
    }
]
```

The **Ads overview** dataset view shows `advertiserName`, `advertiserDomain`, `adFormat`, `firstShown`, `lastShown`, `daysShown`, `regions`, `url`, `status` and `error`. The **All columns** view adds `advertiserId`, `adId`, `regionCount`, `previewUrl`, `imageUrl`, `searchRegion`, `searchTerm` and `scrapedAt`.

### How to see a competitor's Google ads by domain or advertiser ID

1. Open the Actor in Apify Console and click **Try for free**.
2. Put your advertisers into **Advertiser URLs or domains** — one per line. Any of these work:
   - a website: `nike.com`, `www.booking.com`, or any page URL on that site
   - an advertiser id: `AR18378488041124659201`
   - an advertiser page: `https://adstransparency.google.com/advertiser/AR18378488041124659201?region=US`
3. Optionally pick a **Region** (default: anywhere) and an **Ad format** (default: any).
4. Set **Maximum results** — start with the default 20 to see the shape of the output.
5. Click **Start**. The default input takes about five seconds; 1,000 ads take roughly 2-4 minutes.
6. Open the **Output** tab or **Export** the dataset as JSON, CSV, Excel, XML or HTML.

To automate it, use the **API** tab (Node.js, Python, curl examples) or add a **Schedule**.

### Input

Every field, its default and when you would change it:

| Field | Type | Default | When to change it |
|---|---|---|---|
| `startUrls` | array of strings | `["nike.com", "booking.com"]` | Always — this is your advertiser list. Website domains, advertiser ids (`AR…`) or Ads Transparency advertiser URLs. Pass many in one run and use `searchTerm` to tell the rows apart. |
| `maxItems` | integer | `20` | Raise it for production runs; it is your hard cap on rows and therefore on spend. Ads come back newest-active first, so even a small run shows the current campaigns. |
| `region` | string | `anywhere` | Set an ISO alpha-2 country (`US`, `GB`, `DE`, ...) when you only care about one market. It also decides which country's Ads Transparency page the `url` column points at. |
| `adFormat` | string | `any` | Set `text`, `image` or `video` when you are studying one channel — for example `image` only, when you are collecting display creatives for a moodboard. |
| `proxyConfiguration` | object | Apify Proxy off | Leave it off. Enable Apify Proxy (datacenter group) only if a run reports rate limiting; residential proxies are not needed and not recommended. |

A `?region=` inside an advertiser URL overrides the **Region** field for that one entry, so you can mix countries in a single run.

Example input:

```json
{
    "startUrls": ["nike.com", "booking.com"],
    "maxItems": 20,
    "region": "anywhere",
    "adFormat": "any"
}
```

### How much does it cost to scrape ads transparency data?

This Actor uses **pay-per-event** pricing. The table below is the whole price list:

| Event | Charged when | Price |
|---|---|---|
| Actor start | Once per run, by the Apify platform (one event per GB of memory; the default is 1 GB). | $0.005 per run |
| Ad | One ad with `status: ok` is saved to the dataset. | $0.00299 per ad |

- 1,000 ads cost about **$3.00** ($0.005 start + 1,000 × $0.00299).
- Rows with `status` `not_found` or `error` are **never charged** — an advertiser with no live ads costs you the start fee only.
- The Actor stops gracefully when your run's maximum charge is reached. Cap spending with **Maximum results** and with the run's **Max total charge** option.
- The free Apify plan's $5 of monthly credit covers about 1,670 ads in a single run.

### How it compares

This Actor is the fast, cheap way to turn a list of competitor domains into a structured ad inventory. It is pure HTTP — about 1.1 requests per ad, and three consecutive staging runs of the default input finished 20 ads in 5.0–5.6 seconds on Apify's smallest machine. Domain search, per-ad country lists and a tri-state `status` are the things it does better than a hand-rolled script.

It is not for you if you need ad **headline text or landing-page URLs** (the source publishes rendered previews, not copy), spend and impression figures for general ads (only political ads carry those, and this Actor does not output payer or spend data), or a **keyword search** across all advertisers — the source resolves searches by advertiser account or verified website, so you have to know whose ads you want. It also covers Google's own transparency disclosure only, not other ad platforms' libraries.

### Integrations, API and AI agents

Results export to **CSV, JSON, Excel**, XML and HTML, and can be pushed to **Google Sheets, Airtable, Slack or a CRM** through Apify integrations and webhooks (n8n, Make and Zapier included). Add a **Schedule** to re-run a client or competitor list daily and diff the creatives.

The Actor can be called from the **Apify API** (Node.js, Python or curl — see the **API** tab), from the **Apify MCP server**, or from any AI agent: inputs are plain strings and every row is self-describing thanks to `status` and `error`, so an agent can tell "this advertiser runs no ads" apart from "the source could not be read".

### Tips

- Start with the domain, not the advertiser id: one domain often covers several advertiser accounts (brand, regional entities, agencies), and each row tells you which one via `advertiserId`.
- Copy an `advertiserId` from a first run into a follow-up run to track exactly one account over time.
- Sort by `daysShown` descending to find evergreen creatives, and by `firstShown` descending to see what launched this week.
- Pass several advertisers in one run instead of many single-advertiser runs; you pay the start fee once.
- Keep `maxItems` small while testing, then raise it.

### FAQ

**Can I search by keyword or by product?** No. The source resolves a search to an advertiser account or a verified website, so the input must be a domain, an advertiser id or an advertiser page URL. Find the advertiser you care about first (searching the domain is usually enough), then run this Actor on it.

**Is it legal to scrape ads transparency data?** The Ads Transparency Center is a public transparency disclosure, published by Google so that anyone can look up who is advertising. Reading public pages is generally lawful, but you are responsible for how you use the output. Read the legal notice below and Google's terms of service, and do not collect personal data without a legitimate reason.

**Why do I get several advertisers back for one domain?** Large brands run ads through more than one Google Ads account: a global account, regional entities, and media agencies that verified the same website. A domain search returns all of them, and `advertiserId` and `advertiserName` tell you which account each ad belongs to.

**What does `daysShown` mean exactly?** It is the number of days the source recorded the ad as running. It is never larger than the span between `firstShown` and `lastShown`, and it is usually the better "is this ad working?" signal of the two.

**Do I get the ad's headline text and landing page?** No. The source publishes creatives as rendered previews, so you get `previewUrl` and `imageUrl` rather than copy or the advertiser's click-through URL. Open the preview to read the ad.

**Can I use this Actor from an AI agent or MCP client?** Yes. Every row is self-describing (`status` + `error`), inputs are plain strings, and results can be fetched via the dataset API or the Apify MCP server.

**Why did I get fewer rows than `maxItems`?** The advertiser publishes fewer ads for that region and format, or the run hit your **Max total charge** limit. Check the run log for "Stopping gracefully" and look at any `not_found` rows.

**Do I need a proxy?** No. The Actor works from Apify's datacenter IPs with the proxy off, which is the default. Turn on Apify Proxy (datacenter) only if a run reports rate limiting.

**What if a field is missing?** Optional fields are omitted when the source does not publish them. `regions` and `regionCount` are also omitted on the rare row whose per-ad lookup failed after retries — the rest of the row is still correct. If a field that should always be present is missing, open an issue in the **Issues** tab with the run ID.

### Limitations

- **The endpoint is undocumented.** The Ads Transparency Center has no published public API; this Actor calls the same keyless JSON endpoints the website itself uses. They can change without notice, in which case rows come back as `error` and the Actor is updated quickly (report it in the **Issues** tab).
- **Coverage varies by country.** Google's transparency disclosures differ per region and advertiser type: an advertiser can be fully listed in the EU and thinly listed elsewhere. `regions` shows what the source published, not what an advertiser truly bought.
- **Political and election ads are disclosed differently from general ads.** Political ads carry extra public data (payer, spend and impression ranges) that general ads do not have; this Actor returns the fields that exist for *all* ads and does not output payer names or spend figures.
- **No creative text and no landing-page URL.** Ads are published as rendered previews, so the Actor returns `previewUrl`/`imageUrl` rather than headline text or the advertiser's click-through URL.
- **No free-text keyword search.** The source resolves searches by advertiser account or verified website, so the input is a domain, an advertiser id or an advertiser URL — not a phrase like "running shoes".
- **Verified advertisers only.** Advertisers that are not verified, and ads that have already been removed, are not in the source and cannot be returned.
- **Rate limiting.** Google throttles bursts from a single IP. The Actor keeps concurrency low and backs off automatically; very large runs are best split into several scheduled runs, optionally through Apify Proxy (datacenter).

### Legal and data-protection notice

This Actor extracts only data that the Google Ads Transparency Center publishes publicly; it does not extract private user data such as e-mail addresses, phone numbers, gender or precise location, it does not log in, and it does not circumvent access controls. Advertiser identities in the output are verified business identities. However, your results could still contain personal data — for example when a sole trader advertises under their own name. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you are unsure whether your reason is legitimate, consult your lawyers. You are responsible for complying with Google's terms of service and applicable law when using the extracted data.

This Actor is an independent tool and is not affiliated with, endorsed by or sponsored by Google LLC. All trademarks belong to their respective owners.

# Actor input Schema

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

One advertiser per line. Three forms are accepted: a website domain (`nike.com`, `www.booking.com`, or any page URL on that site), an advertiser id (`AR01614014350098432001`), or an Ads Transparency Center advertiser URL (`https://adstransparency.google.com/advertiser/AR01614014350098432001?region=US` - a `?region=` in the URL overrides the Region field for that entry). A domain search returns the ads of every advertiser account that verified that website.

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

Stop after this many rows have been saved to the dataset. Each saved row with status `ok` is one billable result. Start at 20 for a fast preview, then raise it for production runs.

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

Only return ads that ran in this country. `anywhere` (the default) returns ads from every country the advertiser ran in. The region also decides which country's Ads Transparency page the `url` column points at.

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

Only return ads of one format. `text` covers search and text ads, `image` covers uploaded display banners, `video` covers video ads. Leave it on `any` to get all three.

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

Optional. The Actor is HTTP-only and works from plain datacenter IPs, so leave this off. Enable Apify Proxy (datacenter group) only if a run reports rate limiting; residential proxies are not needed and not recommended for this Actor.

## Actor input object example

```json
{
  "startUrls": [
    "nike.com",
    "booking.com"
  ],
  "maxItems": 20,
  "region": "anywhere",
  "adFormat": "any",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (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 = {
    "startUrls": [
        "nike.com",
        "booking.com"
    ],
    "maxItems": 20,
    "region": "anywhere",
    "adFormat": "any",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("glasswing/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 = {
    "startUrls": [
        "nike.com",
        "booking.com",
    ],
    "maxItems": 20,
    "region": "anywhere",
    "adFormat": "any",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("glasswing/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 '{
  "startUrls": [
    "nike.com",
    "booking.com"
  ],
  "maxItems": 20,
  "region": "anywhere",
  "adFormat": "any",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call glasswing/ads-transparency-scraper --silent --output-dataset

```

## MCP server setup

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