# Google Ads Transparency Scraper: Ads by Advertiser or Domain (`fetchwise/google-ads-transparency-scraper`) Actor

Ads from the Google Ads Transparency Center by domain, advertiser ID or name: format, dates shown, regions and image links. No proxy needed. Pay per ad.

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

## Pricing

from $1.20 / 1,000 ad founds

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?

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

Get every ad a company runs on Google Search, YouTube, Maps, Play and Shopping, straight from the [Google Ads Transparency Center](https://adstransparency.google.com). Search by domain, advertiser ID or company name, filter by country, platform, format and dates, and get one clean row per ad. Countries, impressions, targeting and who paid are included at no extra charge. It uses plain HTTP and Apify datacenter proxy (no browser, no residential proxy), so it is fast and you only pay per ad.

### What you can use it for

- **Competitor research:** see every ad a competitor runs, when each one started and whether it is still running.
- **Creative inspiration:** collect image and text ads for a market or a brand, with links to each ad.
- **Launch monitoring:** schedule a run and watch `firstShown` and `lastShown` to spot new campaigns and paused ones.
- **Agency audits and pitches:** list a prospect's live ads by country and platform before the first call.
- **Brand protection:** find advertisers that promote your domain or use your brand name.
- **EU ad research:** impression ranges, platforms and targeting criteria that Google publishes for ads shown in the EU.

### Input

Give at least one domain, advertiser ID or advertiser name.

| Field | Description |
|---|---|
| `domains` | Websites such as `nike.com`. Finds ads from every advertiser that promotes the domain. A full URL is fine. |
| `advertiserIds` | IDs starting with `AR`, or advertiser page URLs copied from adstransparency.google.com. |
| `advertiserNames` | Company or brand names such as `Nike`. Each name is matched to the advertiser with that name and the most ads; the run log shows which one was picked. |
| `maxAdvertisersPerName` | How many matching advertisers to scrape per name (default 1). Big brands often have one account per country. |
| `region` | Only ads shown in this country (default anywhere). |
| `platform` | Google Search, YouTube, Google Maps, Google Play or Google Shopping (default all). |
| `adFormat` | Text, image or video (default all). |
| `dateFrom`, `dateTo` | Only ads shown in this date range. |
| `includeDetails` | Adds per-country dates and impressions, platforms, targeting, category, payer, variations and the advertiser's legal name, country and verification (default off). One extra request per ad, so runs are slower; no extra charge. |
| `maxAdsPerSearch` | Ads per domain, advertiser ID or matched advertiser (default 100, up to 10,000). The most recently shown ads come first. |
| `maxAds` | Ads in the whole run (default 1,000, up to 50,000). |
| `maxConcurrency` | Requests in flight (default 3). The Actor also paces itself to about 2 requests per second and slows down when Google asks it to. |
| `timeoutSecs` | Time limit per request (default 20 s). |
| `proxyConfiguration` | Apify datacenter proxy by default: when Google refuses an IP, the Actor moves to a new one. You can also use your own proxy URLs, or turn the proxy off. Residential proxy is not supported. |

Example:

```json
{
    "domains": ["nike.com"],
    "advertiserNames": ["Adidas"],
    "region": "US",
    "adFormat": "IMAGE",
    "includeDetails": true,
    "maxAdsPerSearch": 200
}
```

### Output

One row per ad. With `includeDetails` on (`previewUrl` shortened):

```json
{
    "searchType": "domain",
    "searchValue": "nike.com",
    "advertiserId": "AR18378488041124659201",
    "advertiserName": "Nike Retail BV",
    "advertiserLegalName": "Nike Retail BV",
    "advertiserCountry": "NL",
    "advertiserVerified": true,
    "creativeId": "CR07893733415659241473",
    "format": "IMAGE",
    "firstShown": "2021-10-25T07:00:00.000Z",
    "lastShown": "2026-10-21T04:21:23.645Z",
    "daysShown": 1380,
    "matchedDomain": "nike.com",
    "adUrl": "https://adstransparency.google.com/advertiser/AR18378488041124659201/creative/CR07893733415659241473?region=anywhere",
    "imageUrl": null,
    "imageWidth": null,
    "imageHeight": null,
    "previewUrl": "https://displayads-formats.googleusercontent.com/ads/preview/content.js?client=ads-integrity-transparency&creativeId=475652781299&…",
    "region": "anywhere",
    "regionCount": 1,
    "regions": [
        {
            "country": "FR",
            "firstShown": "2023-03-01",
            "lastShown": "2026-10-20",
            "impressionsMin": 10000000,
            "impressionsMax": null,
            "platforms": [
                { "platform": "SHOPPING", "impressionsMin": 15000, "impressionsMax": 20000 },
                { "platform": "SEARCH", "impressionsMin": 10000000, "impressionsMax": null }
            ]
        }
    ],
    "platforms": ["SEARCH", "SHOPPING"],
    "euImpressionsMin": 10000000,
    "euImpressionsMax": null,
    "targeting": {
        "demographics": { "included": true, "excluded": false },
        "geography": { "included": true, "excluded": false },
        "contextual": { "included": true, "excluded": true },
        "customerLists": { "included": true, "excluded": false }
    },
    "category": "Apparel & Accessories",
    "paidBy": "Nike Retail BV",
    "variationCount": 3,
    "variationImageUrls": [],
    "billable": true,
    "error": null,
    "scrapedAt": "2026-10-21T04:42:18.558Z"
}
```

- An impression range with `impressionsMax: null` is open-ended, e.g. "10M+".
- `imageUrl` is Google's archived picture of the ad. Image ads and most text ads have one; others have a `previewUrl` to Google's preview script, and every ad has `adUrl`.
- Without `includeDetails`, `advertiserLegalName`, `advertiserCountry`, `advertiserVerified` and the detail fields (`regionCount` to `variationImageUrls`) are `null`.
- `billable` says whether the row was charged; `error` says why a search or an ad failed. A search that finds nothing gets one row with an error, so you can see which inputs had no ads.
- The run's key-value store has a `SUMMARY` record: ads saved, failed searches, requests and retries.

### Pricing

Pay per event:

| Event | Free plan | Starter | Scale | Business |
|---|---|---|---|---|
| Ad found (only rows with `billable: true`) | $0.002 | $0.002 | $0.0016 | $0.0012 |
| Actor start (Apify's standard start fee) | $0.00005 | $0.00005 | $0.00005 | $0.00005 |

That is $2 per 1,000 ads on the Free and Starter plans. Ad details cost nothing extra. Rows with an error, invalid input and duplicates are free: an ad found by two of your searches is saved and charged once. Set a maximum cost per run in the run options; the Actor stops cleanly when it is reached.

### Limits

- Data comes from what Google publishes in the Transparency Center. Impression ranges, platforms and targeting are mostly published for ads shown in the EU (and for political ads), so ads shown only elsewhere usually have countries and dates but no impressions.
- The headline and description of text ads are not extracted: Google archives most text ads as images (`imageUrl`).
- **Speed.** Without details a run needs one request per 100 ads: 5,000 ads take under a minute. With details every ad needs its own request, so the Actor handles about 2 ads per second (1,000 ads in about 9 minutes).
- **Google's limit per IP.** Google allows each IP only a few hundred requests in a short time, then refuses it for a while; the shared IPs of cloud servers are sometimes refused from the start. That is why the Actor uses Apify datacenter proxy by default and moves to a new IP whenever Google refuses one. How far a large run with details gets depends on how many fresh proxy IPs your plan has (in our tests one run got 980 ads with details; without a proxy, about 300).
- **When Google refuses.** The Actor pauses and retries. If Google keeps refusing, the run stops asking, keeps what it saved and says so in the status and the `SUMMARY` record; ads it could not finish are not charged. If Google refuses from the very first request, the run fails without any charge: try again later.
- Only public data from the Transparency Center. You are responsible for how you use it.

# Actor input Schema

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

Websites whose ads you want, such as nike.com. Finds ads from every advertiser that promotes the domain. A full URL is fine; only the domain is used.

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

Advertiser IDs (they start with AR), or advertiser page URLs copied from adstransparency.google.com.

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

Company or brand names, such as "Nike". Each name is matched to the advertiser(s) with that name and the most ads; the log shows which ones were picked.

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

How many matching advertisers to scrape for each name. Big brands often have several accounts, one per country.

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

Only ads shown in this country.

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

Only ads shown on this Google platform.

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

Only ads of this format.

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

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

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

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

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

Adds the countries each ad ran in (with first and last day), impression ranges, platforms and targeting where Google publishes them (mostly EU ads), the ad category, who paid, all image variations, and the advertiser's legal name, country and verification. One extra request per ad, so runs are slower, at no extra charge. With details the Actor handles about 2 ads per second; Google stops one IP after a few hundred requests, and the Actor then moves to a new proxy IP.

## `maxAdsPerSearch` (type: `integer`):

Stop each domain, advertiser ID or matched advertiser after this many ads. Newest ads come first.

## `maxAds` (type: `integer`):

Stop the whole run after this many ads. You can also set a maximum cost per run in the run options.

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

Requests in flight at the same time. The Actor also paces itself to about 2 requests per second and slows down when Google asks it to.

## `timeoutSecs` (type: `integer`):

A request that takes longer is retried; an ad whose details still fail is saved with an error and not charged.

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

Apify datacenter proxy by default: Google refuses IPs that asked too much, and the Actor then moves to a new proxy IP. You can also use your own proxy URLs. Residential proxy is not supported.

## Actor input object example

```json
{
  "domains": [
    "nike.com"
  ],
  "maxAdvertisersPerName": 1,
  "region": "anywhere",
  "platform": "ALL",
  "adFormat": "ALL",
  "includeDetails": true,
  "maxAdsPerSearch": 20,
  "maxAds": 1000,
  "maxConcurrency": 3,
  "timeoutSecs": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per ad: advertiser, format, first and last shown, image and link, and whether the row was charged.

## `details` (type: `string`):

Countries, platforms, EU impressions, category and payer per ad. Filled only when Include ad details is on.

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

Ads saved, failed searches, requests and rate limits, and why the run stopped early, if it did.

# 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"
    ],
    "includeDetails": true,
    "maxAdsPerSearch": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

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

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

```

## MCP server setup

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