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

Every ad an advertiser runs on Google Search, YouTube, Display, Shopping and Maps, from the Ads Transparency Center: previews, format, first and last shown dates, days active, per-country activity. Search by brand, domain or advertiser ID. No login. From $0.005/run + $0.0015/ad.

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

## Pricing

from $0.90 / 1,000 ad (creative row)s

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

> **Unofficial tool.** Orbots is not affiliated with, sponsored by, or endorsed by Google. "Google", "Google Ads" and "Ads Transparency Center" are trademarks of Google LLC, used here only to describe the public data this Actor collects.

See **every ad an advertiser is running on Google**: Search, YouTube, Display, Shopping and Maps, straight from the public Ads Transparency Center. Give it a brand name, a domain or an advertiser ID and get one clean row per ad: format, preview asset, first and last shown date, days active, and (optionally) the countries each ad ran in. No login, no browser, no cookies. **You only pay for rows that are actually delivered.**

### Why this Actor

- **Three ways to target.** A brand name (`Nike`), a domain (`nike.com`) or a Google advertiser ID (`AR18378488041124659201`). A Transparency Center URL works too. Names are resolved to the advertiser with the most ads among the matches (verified in your requested region when possible); if that advertiser runs nothing in your regions, the next match is tried. Domains return every advertiser using the domain.
- **Region filter that reduces what you pay.** Pass ISO country codes (`US`, `GB`, `BR`) and only ads shown there come back, so you are not charged for creatives you filtered out afterwards.
- **Dates and lifetime on every row.** `first_shown`, `last_shown` and `days_shown` come straight from the Center, so you can tell a campaign that has run for 300 days from one launched yesterday.
- **Per-country activity on demand.** Turn on `includeDetails` to get, for each creative, the list of countries it ran in with first and last dates per country, plus every preview variation. One extra request per ad, priced as its own event.
- **Advertiser check mode.** Screen a list of domains or brands in one run: one row per query saying whether the advertiser runs Google ads at all, with Google's own estimated range of active ads (for example 70,000 to 80,000 for shopify.com) and every verified advertiser found behind the domain.
- **Built for schedules.** Turn on `onlyNew` and each run returns only creatives you have not received before, per query and region set. A daily run reports new campaigns instead of handing you the same list twice and charging for it again.
- **Fast and cheap to run.** Pure HTTP against the Center's own JSON endpoints. In our benchmark, 100 ads across three advertisers took 10 seconds and cost half a cent of platform usage. 150 consecutive searches from one Apify server returned 150 successes with no throttling.
- **Honest billing.** `maxAdsPerQuery` is respected exactly. A run that delivers nothing is not charged at all, not even the start fee.

### What you get

#### Creatives (default)

```json
{
  "type": "creative",
  "query": "nike.com",
  "advertiser_id": "AR16735076323512287233",
  "advertiser_name": "Nike, Inc.",
  "domain": "nike.com",
  "creative_id": "CR02394569508766351361",
  "format": "image",
  "preview_url": "https://tpc.googlesyndication.com/archive/simgad/16786811858631500832",
  "image_url": "https://tpc.googlesyndication.com/archive/simgad/16786811858631500832",
  "video_url": null,
  "youtube_id": null,
  "first_shown": "2025-10-22T15:06:43Z",
  "last_shown": "2026-09-03T00:32:17Z",
  "days_shown": 308,
  "transparency_url": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR02394569508766351361?region=anywhere",
  "scraped_at": "2026-09-03T01:00:09Z"
}
```

`format` is `image`, `text` (text and responsive ads, delivered as a rendered preview link) or `video`. With `includeDetails` each row also carries `regions` (one entry per country with `first_shown` and `last_shown`), `regions_count`, `variants` and `variants_count`.

#### Advertiser check (`outputMode: "advertisers"`)

```json
{
  "type": "advertiser",
  "query": "shopify.com",
  "advertiser_id": "AR01625195283841286145",
  "advertiser_name": "Shopify Inc.",
  "domain": "shopify.com",
  "has_ads": true,
  "total_ads_min": 70000,
  "total_ads_max": 80000,
  "advertisers_found": [{"advertiser_id": "AR01625195283841286145", "advertiser_name": "Shopify Inc.", "domain": "shopify.com"}],
  "regions": [],
  "transparency_url": "https://adstransparency.google.com/advertiser/AR01625195283841286145?region=anywhere",
  "scraped_at": "2026-09-03T01:00:01Z"
}
```

`total_ads_min` and `total_ads_max` are the range Google itself reports for the advertiser, not a count of rows this Actor fetched.

### Input

| Field | What it does |
|---|---|
| `queries` | Brand names, domains or advertiser IDs, one per line. Required. |
| `regions` | ISO country codes. Empty = ads shown anywhere. Default `["US"]`. |
| `maxAdsPerQuery` | Hard cap per query. Default 100. Empty = no cap (large advertisers run tens of thousands of creatives). |
| `formats` | Keep only `image`, `text` and/or `video`. Filtered rows are not charged. |
| `includeDetails` | Adds per-country dates and preview variations to every creative. One extra request per ad, charged as `ad-detail`. |
| `outputMode` | `creatives` (one row per ad) or `advertisers` (one row per query). |
| `onlyNew` | Only creatives not delivered by earlier runs of the same query and regions. History is kept for 180 days in your own account. |
| `proxyConfiguration` | Off by default. The Center answers Apify servers directly; enable a proxy only if your runs start getting throttled. |

A minimal run:

```json
{ "queries": ["nike.com"], "regions": ["US"], "maxAdsPerQuery": 100 }
```

### When a run returns nothing

The Actor separates "something broke" from "there was nothing to return":

- Every query refused by the Center even after retries: the run **fails** with a message, so a schedule notices.
- No advertiser matched a name, or the advertiser has no ads in the requested regions, or `onlyNew` found nothing new: the run **succeeds with a status message** explaining why, and nothing is charged.

Brand names are ambiguous in the Center (dozens of verified advertisers can share a name). For precision, prefer the domain or the advertiser ID; both are shown on the public Transparency Center page.

### Notes and limits

- Ad text is not extracted. Text and responsive ads are delivered as a rendered preview link (`preview_url`), which the Center serves as a script, not as data. Image ads carry a direct image URL; video ads carry the video preview and the YouTube ID when the video is hosted there.
- The Center rate-limits by IP. From Apify servers we measured 150 consecutive searches without a single refusal; a residential IP hitting the same endpoints from a laptop got throttled after a few dozen requests. The Actor backs off and retries on throttling, and rotates IPs when a proxy is configured.
- Data comes from Google's public Transparency Center as it is at run time. Google's estimated ad counts are ranges, not exact numbers.

### Pricing: what a run actually costs

Pay per event. A run that delivers nothing costs nothing.

| Event | Price | When |
|---|---|---|
| Actor start | $0.005 | Once per run, on the first delivered row |
| Ad (`ad`) | $0.0015 per creative on the free plan, down to $0.0008 on higher plans | Every creative row delivered |
| Ad detail (`ad-detail`) | $0.002 | Every creative enriched with `includeDetails` |
| Advertiser check (`advertiser`) | $0.002 | Every advertiser row delivered |

Example: 100 ads for one advertiser, no details, costs $0.005 + 100 x $0.0015 = **$0.155** on the free plan. The same 100 ads with details cost $0.355. Platform usage on top of that was half a cent in our benchmark run.

### Changelog

- **0.1** (2026-09-03): first release. Creatives by name, domain or advertiser ID; region and format filters; per-country details; advertiser check mode; onlyNew for schedules.

# Actor input Schema

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

One entry per line: a brand name (Nike), a domain (nike.com) or a Google advertiser ID (AR18378488041124659201). A Transparency Center URL also works. Names are resolved to the best-matching advertiser; domains return every advertiser using that domain.

## `regions` (type: `array`):

Country codes (ISO 3166-1 alpha-2: US, GB, BR, DE...). Only ads shown in these countries are returned. Leave empty for ads shown anywhere.

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

Hard cap per advertiser, domain or name. The Actor stops at exactly this number and never charges beyond it. Leave empty for no cap (large advertisers run thousands of creatives).

## `formats` (type: `array`):

Keep only these formats. Rows filtered out are not charged.

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

Fetches the detail record of every creative: first and last shown date per country, all preview variations, and the text of each variation. One extra request per ad, charged as an ad-detail event.

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

Creatives = one row per ad. Advertiser check = one row per query saying whether the advertiser runs Google ads, with Google's estimated ad count range; ideal for screening a list of domains.

## `onlyNew` (type: `boolean`):

Built for schedules. The Actor remembers which creatives it already delivered for each query and region set, and returns only the ones it has not sent you before, so a daily run reports new campaigns instead of repeating the whole list and charging for it again. History is kept for 180 days in your own account.

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

Not required: the Transparency Center answers Apify servers directly. Enable a proxy only if your runs start getting throttled.

## Actor input object example

```json
{
  "queries": [
    "nike.com"
  ],
  "regions": [
    "US"
  ],
  "maxAdsPerQuery": 100,
  "formats": [
    "image",
    "text",
    "video"
  ],
  "includeDetails": false,
  "outputMode": "creatives",
  "onlyNew": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Every row collected by the run, in delivery order. Each row carries a "type" field: creative or advertiser.

## `creatives` (type: `string`):

One row per ad: advertiser, domain, format, preview asset, first and last shown dates, days active, and a link to the public Transparency Center page.

## `creativesCsv` (type: `string`):

The same ads as a spreadsheet-ready CSV.

## `advertisers` (type: `string`):

Advertiser-check rows: whether each query runs Google ads, with Google's estimated ad count range.

# 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"
    ]
};

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

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

```

## MCP server setup

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