# Google Ads Transparency Scraper (`datamech/google-ads-transparency-scraper`) Actor

Scrape ads from the Google Ads Transparency Center by domain, advertiser name, advertiser ID or URL. Get creatives, formats, first/last shown dates, regions, platforms and impressions. HTTP-only, no login. $0.10 per 1,000 ads.

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

## Pricing

from $0.10 / 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

**Scrape public Google ads by domain, advertiser name, advertiser ID, or Transparency Center URL — HTTP only, no browser, no login.**

This Actor reads the same public JSON-RPC endpoints that [Google Ads Transparency Center](https://adstransparency.google.com/) uses in the browser. Give it `nike.com`, `Nike, Inc.`, an `AR…` advertiser ID, or a pasted Transparency Center link and it returns the creatives that advertiser is running: format, first/last shown dates, regions, preview image, and a link back to the official transparency page.

Empty input is valid. A run with `{}` searches `nike.com` and stores 20 ads so Apify Store automated tests succeed.

### What does Google Ads Transparency Scraper do?

It collects **one dataset row per ad creative** from Google's public ad library:

- Advertiser ID (`AR…`) and display name
- Creative ID (`CR…`)
- Format: `text`, `image`, or `video`
- First shown and last shown dates (ISO 8601)
- Approximate days the ad has been active
- Preview / image URL and the official transparency page URL
- Optional add-on (`includeAdDetails`): per-country impression ranges, platforms, headline, body copy, and landing URL when Google publishes them

All of this is public data. The Actor never logs into Google and never opens a browser.

### Why scrape the Google Ads Transparency Center?

- **Competitor ad research** — see which creatives a brand is still spending on, and which ones disappeared
- **Ad spy for agencies** — export a client's or rival's Google/YouTube/Display library to CSV or Excel
- **Brand safety and political ads** — archive who ran what, where, and for how long
- **Creative analysis** — pull headlines and landing URLs (when published) without clicking through thousands of cards

Google's UI is an infinite scroll with no export button. This Actor is the download button.

### What data can it extract?

| Field | Description |
| --- | --- |
| `creativeId` | Google creative ID (`CR…`) |
| `advertiserId` / `advertiserName` | Advertiser ID (`AR…`) and public name |
| `domain` | Advertised domain when returned by search |
| `format` / `formatCode` | `text`, `image`, or `video` plus the raw RPC code |
| `firstShown` / `lastShown` | ISO timestamps |
| `shownForDays` | Approximate active span |
| `transparencyUrl` | Official Ads Transparency Center page |
| `previewUrl` / `imageUrl` / `videoUrl` | Creative assets |
| `headline` / `body` / `destinationUrl` | Ad copy and landing URL (list overlay or details) |
| `regions` / `regionsShown` | Countries and optional impression ranges |
| `platforms` | Search, YouTube, Display, … when published |
| `detailsIncluded` | Whether the optional details add-on succeeded |

### How to scrape Google Ads Transparency Center

1. Open the Actor in Apify Console (or call it through the API).
2. Leave the defaults to try `nike.com`, or paste domains, `AR…` IDs, brand names, or Transparency Center URLs.
3. Optionally set a country (`US`, `DE`, `FR`, …), a format, and a date window.
4. Turn on **Fetch per-ad details** only if you need impression ranges or extra copy — it costs one extra `ad-details` event per successful enrichment.
5. Run. Results land in the default dataset (JSON / CSV / Excel / table view).

### How much will it cost?

Pricing is **pay per result**, with no Actor-start fee.

Store prices:

| Event | When it is charged | Price |
| --- | --- | --- |
| `ad` | One successful dataset row | **$0.0001** ($0.10 / 1,000 ads) |
| `ad-details` | Only if `includeAdDetails` actually added extra fields | **$0.0004** ($0.40 / 1,000 ads) |

Empty searches, failed lookups, and advertisers with zero ads are **not** charged. If the run hits `ACTOR_MAX_TOTAL_CHARGE_USD`, the Actor stops cleanly, keeps the ads already saved, and exits successfully.

Compute cost stays tiny: the Actor is HTTP-only and defaults to **256 MB** RAM. Live measurements from this repository (21 Oct 2026, no proxy):

| Run | Ads | HTTP requests | Body traffic | Wall time |
| --- | ---: | ---: | ---: | ---: |
| Default `{}` (`nike.com`, 20 ads) | 20 | 1 | 0.023 MB | ~3 s |
| One advertiser, 1,000 ads | 1,000 | 25 | 0.333 MB | 13.4 s |
| **Per 1,000 list ads** | 1,000 | **25** | **0.33 MB** | — |

`includeAdDetails` adds one `GetCreativeById` RPC per ad (~3 KB). A `content.js` preview is fetched only when that RPC did not already return detail fields.

Apify Proxy is **off by default** — direct HTTP currently works better for list searches. If Google returns HTTP 302 `/sorry/`, the Actor enables proxy and retries; if the proxy is also blocked it retries without proxy / another IP.

### Input

All fields are optional. Schema defaults make `{}` a valid, successful run.

```json
{
    "domains": ["nike.com"],
    "maxAdsPerAdvertiser": 20
}
```

Useful combinations:

```json
{
    "advertiserIds": ["AR16735076323512287233"],
    "region": "US",
    "format": "IMAGE",
    "maxAdsPerAdvertiser": 100
}
```

```json
{
    "advertiserNames": ["Nike, Inc."],
    "includeAdDetails": true,
    "maxAdsPerAdvertiser": 10
}
```

```json
{
    "startUrls": [
        { "url": "https://adstransparency.google.com/advertiser/AR16735076323512287233" }
    ]
}
```

| Field | Default | Notes |
| --- | --- | --- |
| `domains` | empty input → `["nike.com"]` | Prefill only; not injected when you send names, IDs, or URLs |
| `advertiserIds` | `[]` | `AR…` IDs |
| `advertiserNames` | `[]` | Resolved via `SearchSuggestions` |
| `startUrls` | `[]` | Advertiser, creative, or search URLs |
| `region` | `ANYWHERE` | ISO alpha-2 or `ANYWHERE` |
| `format` | `ALL` | `ALL` / `TEXT` / `IMAGE` / `VIDEO` |
| `startDate` / `endDate` | — | `YYYY-MM-DD` |
| `maxAdsPerAdvertiser` | `20` | Per domain or advertiser |
| `maxTotalAds` | `0` | `0` = no extra cap |
| `includeAdDetails` | `false` | Extra RPC / preview decode |
| `proxyConfiguration` | `{ useApifyProxy: false }` | Auto-enabled on `/sorry/`; dropped again if proxy is also blocked |

### Output

One flat JSON object per ad. Example (trimmed from a live `nike.com` run):

```json
{
    "creativeId": "CR14775126100300267521",
    "advertiserId": "AR16735076323512287233",
    "advertiserName": "Nike, Inc.",
    "domain": "nike.com",
    "format": "image",
    "formatCode": 1,
    "firstShown": "2023-11-16T23:56:41.000Z",
    "lastShown": "2026-10-21T16:03:07.000Z",
    "shownForDays": 897,
    "region": "ANYWHERE",
    "transparencyUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR14775126100300267521",
    "previewUrl": "https://tpc.googlesyndication.com/archive/simgad/16121937908686408129",
    "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/16121937908686408129",
    "matchedInput": "nike.com"
}
```

Download the dataset as JSON, CSV, or Excel, or use the **Overview** table view (image, advertiser, format, dates, transparency link).

### Tips

- Start with `maxAdsPerAdvertiser: 20` to inspect the schema, then raise the cap.
- Domain search returns every advertiser whose ads mention that domain (subsidiaries, media agencies, regional entities). Filter on `advertiserName` in the dataset if you only want the parent brand.
- `includeAdDetails` is best-effort. Google hides impression ranges outside some EEA countries, and many image ads have no extractable copy.
- Leave proxy off unless a run hits `/sorry/`. The Actor will try Apify Proxy and then fall back to direct / another IP. If it is still blocked, retry later or switch the proxy group to `RESIDENTIAL`.
- Deduplication is by `creativeId` across the whole run.

### FAQ

**Does this need a Google account or API key?**\
No. It calls the same anonymous RPCs the public website uses.

**Will an empty run work?**\
Yes. `{}` searches `nike.com` and stores up to 20 ads.

**Why is an advertiser missing?**\
Some local businesses never run Google ads, or run them only in a country you filtered out. A zero-ad target is logged and not billed.

**Is format filtering reliable?**\
Yes for the list RPC. Live checks on 2026-10-21 showed SearchCreatives field `4` = 1 image, 2 text, 3 video. The raw `formatCode` is always stored so you can remap if Google changes the enum.

**Can I use this as an API?**\
Yes. Run the Actor through the Apify API and read `defaultDatasetId`, or add it to an integration.

### Legality and disclaimer

This Actor collects **publicly available** information from the Google Ads Transparency Center. It is not affiliated with, endorsed by, or maintained by Google. You are responsible for how you use the data (including advertising-research and privacy rules that apply in your jurisdiction, such as GDPR if you combine results with personal data). Do not use the output to impersonate advertisers or to violate Google's terms.

### Issues and API

Use the **Issues** tab on the Actor page for bugs and feature requests. Use the **API** tab for scheduled runs, webhooks, and code snippets.

# Actor input Schema

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

Advertiser website domains to search (e.g. nike.com). Each domain is looked up in the Transparency Center.

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

Google advertiser IDs starting with AR (from a Transparency Center URL).

## `advertiserNames` (type: `array`):

Brand or legal names (e.g. Nike, Inc.). Resolved to advertiser IDs via Transparency Center suggestions.

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

Paste Ads Transparency Center URLs (advertiser pages, creative pages, or search URLs). IDs, domains, and region are parsed automatically.

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

ISO 3166-1 alpha-2 country code (US, DE, FR, …) or ANYWHERE for all regions.

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

Filter by creative format.

## `startDate` (type: `string`):

Only ads last shown on or after this date (YYYY-MM-DD).

## `endDate` (type: `string`):

Only ads last shown on or before this date (YYYY-MM-DD).

## `maxAdsPerAdvertiser` (type: `integer`):

Maximum creatives to collect per advertiser or domain. Keep the default low for cheap test runs.

## `maxTotalAds` (type: `integer`):

Stop after this many ads across all advertisers. 0 means no extra cap beyond maxAdsPerAdvertiser.

## `includeAdDetails` (type: `boolean`):

Extra request(s) per ad for region impression ranges, platforms, and text/headline/landing URL when Google publishes them. Billed as a separate ad-details event only when extra fields are actually found.

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

Parallel HTTP requests for optional ad-details enrichment. Search pagination is sequential.

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

Optional Apify Proxy. Off by default — direct HTTP currently works better from most IPs. If Google returns 302 /sorry/, the Actor enables proxy automatically and retries; if proxy is also blocked it retries without proxy / another IP.

## Actor input object example

```json
{
  "domains": [
    "nike.com"
  ],
  "region": "ANYWHERE",
  "format": "ALL",
  "maxAdsPerAdvertiser": 20,
  "maxTotalAds": 0,
  "includeAdDetails": false,
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `ads` (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 = {
    "domains": [
        "nike.com"
    ],
    "region": "ANYWHERE",
    "format": "ALL",
    "maxAdsPerAdvertiser": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("datamech/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": "ANYWHERE",
    "format": "ALL",
    "maxAdsPerAdvertiser": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("datamech/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": "ANYWHERE",
  "format": "ALL",
  "maxAdsPerAdvertiser": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call datamech/google-ads-transparency-scraper --silent --output-dataset

```

## MCP server setup

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