# Google Ads Transparency Center Scraper & API - Competitor Ads (`rel8ble/google-ads-transparency-scraper`) Actor

Google Ads Transparency Center scraper for competitor ads. Input: domains, advertiser names or IDs. One result = one ad: advertiser, format (text/image/video), first/last shown, days shown, creative image or preview, ad link. Optional regions, variants, EU impressions. $0.50 per 1,000 ads.

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

## Pricing

$0.50 / 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?

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 Center Scraper & API - Competitor Ads

This **Google Ads Transparency scraper** is a **Google Ads Transparency Center** scraper and unofficial **Google ad library API**: give it website domains, advertiser names or advertiser IDs and get every ad those companies run on Google Search, YouTube, Shopping, Maps and Play as clean JSON, CSV or Excel. One row per ad: advertiser name and ID, format (text, image, video), first and last shown dates, days shown, the **ad creative** image or preview URL, and a link to the ad in the Transparency Center. Turn on details to add every creative variant, the countries each ad ran in with dates, the ad topic and EU impression ranges.

It calls the same data endpoints the Transparency Center website uses, over plain HTTP with **no headless browser**: 100 ads per request, about 5,000 ads in 30 seconds. Use it for **competitor ad research**, ad spy and creative swipe files, lead generation (which companies are actively buying Google ads), agency prospecting, brand monitoring and feeding AI agents with live ad data.

### What you get

One dataset item per ad, newest last-shown date first:

- **Advertiser**: `advertiserId`, `advertiserName`, `domain` (for domain queries), `advertiserUrl`.
- **Ad**: `creativeId`, `format` (`text`, `image` or `video`), `adUrl` (the ad's page in the Transparency Center).
- **Run dates**: `firstShown`, `lastShown` (ISO timestamps) and `daysShown` (the number of days Google counts the ad as shown).
- **Creative**: `imageUrl` with `imageWidth` / `imageHeight` when Google serves the ad as an image (most text and image ads), otherwise `previewUrl`, Google's embeddable preview script for the ad (most video and shopping ads).
- **Context**: `position`, `query`, `queryType`, `regionFilter`, `scrapedAt`.

With **Include details** each ad also has:

- `variants` and `variantsCount`: every version of the creative (image or preview URL, size).
- `regions`, `regionCountries` and `regionsCount`: each country the ad was shown in, with `lastShown` and, where Google publishes it, `firstShown`.
- `euImpressionsMin` / `euImpressionsMax` and per-country `impressionsMin` / `impressionsMax` with a per-platform split. Google publishes impressions for EU countries only.
- `topic` (for example "Apparel & Accessories") when Google assigns one.

A `RUN_SUMMARY` record in the key-value store lists per-query counts, the total number of ads Google reports for each advertiser or domain, which advertiser ID a typed name resolved to, and why each query stopped.

### Sample output

From a real cloud run (`allbirds.com`, all regions):

| advertiserName | creativeId | format | firstShown | lastShown | daysShown |
|---|---|---|---|---|---|
| Allbirds Inc | CR02410131008503414785 | text | 2026-04-07 | 2026-10-10 | 163 |
| Allbirds Inc | CR04508276176740941825 | video | 2025-06-02 | 2026-10-10 | 441 |
| Allbirds Inc | CR10908757559317889025 | text | 2025-03-12 | 2026-10-10 | 534 |

### Use cases

- **Competitor ad research**: pull every active ad for a list of competitor domains and see which creatives they keep running longest (`daysShown`).
- **Lead generation for agencies**: check a list of prospect domains and keep the ones that are running Google ads right now (`lastShown` in the last few days) and how many.
- **Creative swipe file**: collect image and video ads for a niche, with links back to the source.
- **Market entry**: use details to see which countries a brand advertises in and when it started in each.
- **Monitoring**: schedule a daily run with a date range and get only what is new.

### Pricing

**$0.50 per 1,000 ads** (pay per result; failed requests are never charged). Same price with or without details, and queries with no ads cost nothing. The most-used Google Ads Transparency scrapers on the Store charge $1.50-$2.00 per 1,000 ads.

| You scrape | You pay |
|---|---|
| 100 ads | $0.05 |
| 1,000 ads | $0.50 |
| 10,000 ads | $5.00 |
| 100,000 ads | $50.00 |

No start fee. The Apify free plan's $5 monthly credit covers about 10,000 ads. The prefilled input (allbirds.com, 20 ads) finishes in about 5 seconds and costs $0.01.

#### Why this one

- **Domain, name or ID in, ads out**: no need to look up advertiser IDs first; `allbirds.com` or `Nike, Inc.` works.
- **Creative URLs on every row**: image or preview link, format, first and last shown dates and days running.
- **Details for the same price**: every variant, the countries each ad ran in with dates, ad topic and EU impression ranges.
- **Filters**: region, format (text, image, video), platform (Search, YouTube, Shopping, Maps, Play) and date range.

### FAQ

**Is it legal?**
The Ads Transparency Center is public information Google publishes so anyone can see who is advertising. This actor collects business advertising data, not private personal data, and does not log in. You are responsible for how you use the results. This is not legal advice.

**Is this an official Google API? Does it need a login?**
No. Google has no public API for the Ads Transparency Center. This actor reads the same public data the website shows to any visitor, with no login, cookies or API key.

**How fast is it and how many ads can I pull?**
100 ads per request, about 5,000 ads in 30 seconds. There is no fixed cap: raise `maxAdsPerQuery`. In testing, five advertisers x 1,000 ads finished in 32 seconds with no failed requests. Details mode adds one request per ad and runs slower.

**Which proxy should I use?**
The default (Apify Proxy, datacenter) worked on every cloud test. Switch to residential only if a run reports blocks.

**Can I schedule it or use it via API?**
Yes: Apify Schedules (use `dateFrom` to get only new ads), the REST API and JavaScript / Python clients, Make, Zapier, n8n, webhooks, or the Apify MCP server for AI agents.

**How do I find a competitor's ads?**
Enter their website domain. That returns ads from every advertiser account pointing at that domain, which is usually what you want. Use the advertiser name or ID when one company runs several brands. Set `dateFrom` to today or yesterday to see only the ads running right now.

**Can I get the ad headline and landing page?**
Not as text. Google only publishes the rendered creative. Use `imageUrl` (you can run OCR or a vision model on it) or open `adUrl`.

### How to use

1. Paste one company per line into **Domains, advertiser names or advertiser IDs**: a domain (`allbirds.com`), an advertiser name (`Nike, Inc.`), an advertiser ID (`AR16735076323512287233`) or an Ads Transparency Center URL. Domains are the most reliable: they return ads from every advertiser account that links to that site.
2. Optionally narrow by **Region** (two-letter country), **Ad format**, **Google platform** and a **date range**, and set **Max ads per query** (default 100). Tick **Include details** for regions, variants and EU impressions.
3. Click **Start**. Download the results as JSON, CSV, Excel or HTML from the **Output** tab, or pull them through the Apify API, Make, Zapier, n8n or an MCP client.

### Input example

```json
{
    "queries": ["allbirds.com", "Nike, Inc.", "AR01371945870127267841"],
    "region": "US",
    "format": "all",
    "platform": "all",
    "dateFrom": "2026-09-01",
    "maxAdsPerQuery": 500,
    "includeDetails": false
}
```

| Field | Type | Default | What it does |
| --- | --- | --- | --- |
| `queries` | array of strings | `["allbirds.com"]` | Domains, advertiser names, advertiser IDs (`AR...`) or Ads Transparency Center URLs, one per line. |
| `region` | string | `anywhere` | Two-letter country code: only ads shown in that country. |
| `format` | string | `all` | `text`, `image` or `video`. |
| `platform` | string | `all` | `search`, `youtube`, `shopping`, `maps` or `play`. |
| `dateFrom`, `dateTo` | string | empty | `YYYY-MM-DD`. Only ads shown inside the range. |
| `maxAdsPerQuery` | integer | `100` | Max ads saved per line. |
| `includeDetails` | boolean | `false` | Adds variants, regions, topic and EU impressions (one extra request per ad). |
| `maxAdvertisersPerName` | integer | `1` | For name lines: how many matching advertiser accounts to include. |

### Output example

Real row from a cloud run (`allbirds.com`, all regions):

```json
{
    "position": 1,
    "query": "allbirds.com",
    "queryType": "domain",
    "advertiserId": "AR01371945870127267841",
    "advertiserName": "Allbirds Inc",
    "creativeId": "CR02410131008503414785",
    "format": "text",
    "domain": "allbirds.com",
    "firstShown": "2026-04-07T15:44:46.000Z",
    "lastShown": "2026-10-10T16:50:18.000Z",
    "daysShown": 163,
    "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/14549710068258611529",
    "imageWidth": 348,
    "imageHeight": 503,
    "previewUrl": null,
    "regionFilter": "anywhere",
    "adUrl": "https://adstransparency.google.com/advertiser/AR01371945870127267841/creative/CR02410131008503414785?region=anywhere",
    "advertiserUrl": "https://adstransparency.google.com/advertiser/AR01371945870127267841?region=anywhere",
    "scrapedAt": "2026-10-10T17:18:19.423Z"
}
```

The extra fields from a real **Include details** run (same advertiser, lists shortened):

```json
{
    "creativeId": "CR10908757559317889025",
    "format": "text",
    "firstShown": "2025-03-12T19:33:40.000Z",
    "lastShown": "2026-10-10T00:53:48.000Z",
    "daysShown": 534,
    "topic": null,
    "variantsCount": 2,
    "variants": [
        { "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/18199488945461523136", "previewUrl": null, "width": 348, "height": 321 },
        { "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/8468202034987102549", "previewUrl": null, "width": 348, "height": 174 }
    ],
    "regionsCount": 5,
    "regionCountries": ["US", "HR", "MX", "IS", "SI"],
    "regions": [
        { "country": "US", "regionCode": 2840, "firstShown": null, "lastShown": "2026-10-09", "impressionsMin": null, "impressionsMax": null, "platforms": [] },
        { "country": "HR", "regionCode": 2191, "firstShown": "2025-04-17", "lastShown": "2026-08-31", "impressionsMin": null, "impressionsMax": 1000, "platforms": [{ "platform": "search", "impressionsMin": null, "impressionsMax": 1000 }] }
    ],
    "euImpressionsMin": 0,
    "euImpressionsMax": 3000
}
```

### API example

Python (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("rel8ble/google-ads-transparency-scraper").call(run_input={"queries": ["allbirds.com", "Nike, Inc."], "region": "US", "maxAdsPerQuery": 100})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["advertiserName"], item["format"], item["firstShown"], item["lastShown"], item["adUrl"])
```

One HTTP call that runs the actor and returns the rows (curl):

```bash
curl -X POST "https://api.apify.com/v2/acts/rel8ble~google-ads-transparency-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"queries": ["allbirds.com", "Nike, Inc."], "region": "US", "maxAdsPerQuery": 100}'
```

### Integrations

- **API**: start runs and read datasets over the Apify REST API or the JavaScript / Python clients.
- **MCP / AI agents**: call it from Claude, ChatGPT or any MCP client through the Apify MCP server; inputs and outputs are documented field by field.
- **No-code**: Make, Zapier, n8n, Google Sheets, Airtable, Slack, webhooks.
- **Scheduling**: run daily or weekly in Apify Schedules with `dateFrom` to track new competitor ads.

### Limits (read before large runs)

- The ad's text is not a separate field. Google serves text ads to the Transparency Center as rendered images (`imageUrl`); video and shopping ads come as a preview script (`previewUrl`) that draws the ad in a browser. There is no headline, description or landing-page field in Google's data.
- Google reports the total number of ads as a range (for example 800-900); it is in the run summary.
- Impressions exist for EU countries only, and only as ranges. Google does not publish spend or clicks for commercial ads.
- An advertiser name can belong to several accounts. Check `resolvedAdvertisers` in the run summary, or use the domain or the advertiser ID to be exact.
- Ads Google removed for policy reasons are not returned.

### How it works (for developers)

Each query is classified as a domain, an advertiser ID, an Ads Transparency URL or a name. Names go through the site's suggestion endpoint and the best match is taken (exact name first, then the account with the most ads). Ads are listed with `SearchService/SearchCreatives`, 100 per request, following the page token until `maxAdsPerQuery`; region, format, platform and dates are sent as server-side filters. With details on, each ad gets one `LookupService/GetCreativeById` call. Requests go over HTTP/1.1 with session rotation; rate-limit and captcha answers retire the session and retry on a new IP. Region codes are Google geo criterion IDs (2000 + the ISO numeric country code) and are mapped back to two-letter countries.

# Actor input Schema

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

Required. One company per line, in any of these forms: a website domain ("allbirds.com" - returns ads from every advertiser account that links to that domain, the most reliable form), an advertiser name ("Nike, Inc." - resolved to the best-matching verified advertiser), a Google advertiser ID ("AR16735076323512287233"), or an Ads Transparency Center URL (https://adstransparency.google.com/advertiser/AR16735076323512287233?region=US). Each line returns up to maxAdsPerQuery ads. Typical cost: $0.10 per 100 ads. Default \["allbirds.com"] (demo).

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

Optional. Two-letter country code to keep only ads shown in that country: "US", "GB", "DE", "FR", "CA", "AU", "IN", "BR", "JP"... Use "anywhere" (default) for ads shown in any country. A region inside an Ads Transparency URL overrides this for that line.

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

Optional. "all" (default), "text" (search text ads), "image" (display / shopping image ads) or "video" (YouTube and video ads).

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

Optional. Keep only ads shown on one Google surface: "search", "youtube", "shopping", "maps" or "play". Default "all".

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

Optional. Date as YYYY-MM-DD (e.g. "2026-09-01"). Keeps only ads that were shown on or after this day. Use with dateTo to see what a competitor ran in a given period. Empty = no lower limit.

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

Optional. Date as YYYY-MM-DD (e.g. "2026-09-30"). Keeps only ads that were shown on or before this day. Empty = up to today.

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

Optional integer. Maximum number of ads saved for each line in queries, newest last-shown first. One ad = one billed result. Default 100. Large advertisers have thousands of ads: raise this to get them all (100 ads are read per request, so 5,000 ads take about a minute).

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

Optional boolean. true = one extra request per ad to add: every creative variant (image or preview URL), the list of countries the ad ran in with first / last shown date per country, the ad topic, and impression ranges for EU countries (Google publishes impressions only for the EU). Same price per ad, runs slower. Default false.

## `maxAdvertisersPerName` (type: `integer`):

Optional integer. Only used for advertiser-name lines. Several advertiser accounts can share a name; 1 (default) takes the best match (exact name, most ads). Raise to 2-10 to include namesakes and regional accounts. The run summary lists which advertiser IDs were used.

## `maxConcurrency` (type: `integer`):

Optional integer. Parallel requests. Default 10. Lower it if you see retries in the log.

## `maxRequestRetries` (type: `integer`):

Optional integer. How many times a blocked or failed request is retried on a new IP before it is given up. Default 8.

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

Optional. Default: Apify Proxy (automatic datacenter IPs), which is enough for the Ads Transparency Center and the cheapest. Switch to RESIDENTIAL only if a run reports blocks.

## Actor input object example

```json
{
  "queries": [
    "allbirds.com"
  ],
  "region": "anywhere",
  "format": "all",
  "platform": "all",
  "maxAdsPerQuery": 20,
  "includeDetails": false,
  "maxAdvertisersPerName": 1,
  "maxConcurrency": 10,
  "maxRequestRetries": 8,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All ads found: advertiser, creative ID, format, first and last shown dates, creative image or preview URL, Ads Transparency link, and (with includeDetails) variants, regions and EU impressions.

## `summary` (type: `string`):

Per-query counts, the total number of ads Google reports for each advertiser or domain, which advertiser a typed name resolved to, and stop reasons.

# 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": [
        "allbirds.com"
    ],
    "maxAdsPerQuery": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("rel8ble/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 = {
    "queries": ["allbirds.com"],
    "maxAdsPerQuery": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

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