# Google Ads Transparency Scraper: Ads and Election Spend (`sourabhbgp/google-ads-transparency-scraper`) Actor

Track any advertiser's Google ads. Search by advertiser name, landing page domain or advertiser ID across 244 countries and get creatives, formats, run dates and images. Election ads also return spend and impression ranges plus the age, gender and district targeting behind them.

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

## Pricing

Pay per event

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/platform/actors/running/actors-in-store#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 scraper: competitor ads and election ad spend

Track any advertiser's Google ads. Search by advertiser name, landing page domain or advertiser ID, and get every creative with its formats, run dates and images.

Election ads go further: spend, impressions, and the exact age, gender and district targeting behind each one.

**$2 per 1,000 ads, dropping to $0.90 on higher plans. No proxy setup, no browser, no API key.**

Covers 244 countries, from the US and Germany to Japan, Thailand and Nigeria.

### Why this scraper?

- 💰 **Election ad spend and impressions**, which competing scrapers either skip entirely or reduce to a bare on/off flag. Enterprise ad intelligence tools charge thousands a month for this category.
- 🎯 **Real audience targeting**, not just a "targeting was used" flag: which age brackets, which genders, which districts, and which ones were deliberately excluded.
- 🌍 **244 countries** in one input. Ask for three and you get the combined set, deduplicated, not three separate exports to merge.
- 🔗 **Cross advertiser domain search.** One domain returns every advertiser driving traffic there, including resellers and affiliates you didn't know about.
- 🧾 **You are never charged for an empty search.** The actor checks how many ads exist before it scrapes anything, and exits free if the answer is zero.
- 🖼️ **Direct image links** you can download, not redirect URLs that expire.
- ⚡ **Fast and cheap to run.** 50 ads in about 50 seconds, on 256 MB of memory.

### What data can you extract?

<table>
<tr><td>🏢 Advertiser name</td><td>🆔 Advertiser ID</td><td>🎞️ Ad format</td><td>📅 First shown</td></tr>
<tr><td>📆 Last shown</td><td>⏱️ Days actually served</td><td>🌍 Countries shown in</td><td>🖼️ Image links</td></tr>
<tr><td>🔗 Ad page URL</td><td>👁️ Preview link</td><td>🔢 Creative variants</td><td>💵 Spend range</td></tr>
<tr><td>📊 Impressions range</td><td>👥 Ages targeted</td><td>⚧ Genders targeted</td><td>📍 Districts targeted</td></tr>
</table>

The last four are election ads only. Google does not publish spend, impressions or targeting for commercial advertisers, so those fields are simply absent on commercial rows rather than sitting there empty.

#### Countries and scripts

Ads are indexed by country, and the actor accepts all 244 countries Google publishes. Asking for several sends one request per country and merges the results, so an ad running in both Germany and France appears once, not twice.

Advertiser names come back in their own script, untouched:

| Country | Example advertiser |
|---|---|
| 🇯🇵 Japan | 楽天グループ株式会社 |
| 🇰🇷 South Korea | 네이버 주식회사 |
| 🇹🇭 Thailand | ธนาคารกสิกรไทย จำกัด (มหาชน) |
| 🇬🇷 Greece | Εκπαιδευτήρια Δυτικής Ελλάδας μονοπρόσωπη ΙΚΕ |

One gap worth knowing: Russia is not on the list, because Google stopped serving ads there in 2022.

### Scraping modes

#### 🛍️ Commercial ads

Every ad a business is running. Point it at an advertiser name, a landing page domain, or an advertiser ID, then narrow by country, Google surface, format and date.

```json
{
  "mode": "creatives",
  "domain": "nike.com",
  "regions": ["US", "GB", "DE"],
  "platforms": ["SEARCH", "YOUTUBE"],
  "adFormat": "ALL",
  "maxResults": 500
}
```

#### 🗳️ Election ads

The same ads plus what they cost and who saw them. Filter by minimum spend and sort by the biggest spenders or the widest reach.

```json
{
  "mode": "political",
  "regions": ["US"],
  "sortBy": "SPEND",
  "minSpendUsd": 100000,
  "maxResults": 1000
}
```

### How to scrape Google Ads Transparency Center: step by step

1. [Create a free Apify account](https://console.apify.com/sign-up). Takes 30 seconds, no card needed.
2. Open [Google Ads Transparency Scraper](https://console.apify.com/actors/dfSc5VDYClNvIXj1l?addFromActorId=dfSc5VDYClNvIXj1l) in the Apify Console.
3. Type an advertiser name, or paste a domain like `nike.com`, and pick your countries.
4. Click **Start**. A 50 ad run finishes in about a minute.
5. Export as JSON, CSV, or Excel, or pull it straight from the API.

### How much does Google Ads Transparency Scraper cost?

You pay per ad, and the price drops automatically as your Apify plan goes up. No subscription to this actor, no monthly minimum, and the fee to start a run is a twentieth of a cent.

| Your Apify plan | Price per 1,000 ads |
|---|---|
| Free | $2.00 |
| Bronze | $1.70 |
| Silver | $1.40 |
| Gold | $1.10 |
| Platinum | $1.00 |
| Diamond | $0.90 |

The Free plan's $5 of monthly credit is roughly **2,500 ads**. Nothing is charged for a search that returns no ads, and nothing is charged twice when the same ad shows up in two countries.

### Input

```json
{
  "mode": "creatives",
  "advertiserName": "Nike",
  "domain": "nike.com",
  "advertiserIds": ["AR16735076323512287233"],
  "regions": ["US"],
  "platforms": ["SEARCH", "YOUTUBE", "SHOPPING", "MAPS", "PLAY"],
  "adFormat": "ALL",
  "startDate": "2026-01-01",
  "endDate": "2026-08-01",
  "maxResults": 100,
  "detailConcurrency": 10,
  "sortBy": "RECENCY",
  "minSpendUsd": 100000
}
```

| Field | Type | Default | Notes |
|---|---|---|---|
| `mode` | string | `creatives` | `creatives` for businesses, `political` for election ads. |
| `advertiserName` | string | | Finds an advertiser by name. Matches names only, not the words inside ads. |
| `domain` | string | | Exact domain in lowercase, such as `nike.com`. Returns every advertiser sending traffic there. |
| `advertiserIds` | array | `[]` | IDs starting with `AR`. Several are combined together. |
| `regions` | array | `["US"]` | Country codes. One request per country. |
| `platforms` | array | `[]` | Search, YouTube, Shopping, Maps or Play. Empty means all. |
| `adFormat` | string | `ALL` | `TEXT`, `IMAGE` or `VIDEO`. |
| `startDate` | string | | `YYYY-MM-DD`, inclusive. |
| `endDate` | string | | `YYYY-MM-DD`, **exclusive**. Use the day after the last day you want. |
| `maxResults` | integer | `100` | Total across every country and surface. |
| `detailConcurrency` | integer | `10` | How many ads are detailed at once. |
| `sortBy` | string | `RECENCY` | `SPEND` or `IMPRESSIONS`, election ads only. |
| `minSpendUsd` | integer | | Election ads only. Ads in the open ended top bracket are always kept. |

Only one of `advertiserName`, `domain` or `advertiserIds` is needed.

### Output

Commercial ad:

```json
{
  "mode": "creatives",
  "advertiserId": "AR16735076323512287233",
  "advertiserName": "Nike, Inc.",
  "creativeId": "CR11267770087429373953",
  "format": "TEXT",
  "firstShown": "2026-07-21T03:27:58.000Z",
  "lastShown": "2026-08-04T17:19:11.000Z",
  "daysServed": 16,
  "regionsShown": ["US"],
  "adUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR11267770087429373953",
  "imageUrls": ["https://tpc.googlesyndication.com/archive/simgad/11539292750099314527"],
  "previewUrl": "https://displayads-formats.googleusercontent.com/ads/preview/content.js?...",
  "variantCount": 3
}
```

Election ad, with the spend and targeting fields added:

```json
{
  "mode": "political",
  "advertiserName": "HARRIS VICTORY FUND",
  "creativeId": "CR01473782602732142593",
  "format": "TEXT",
  "firstShown": "2024-07-31T19:54:27.000Z",
  "lastShown": "2024-11-11T14:32:00.000Z",
  "daysServed": 104,
  "regionsShown": ["US"],
  "impressionsMin": 2000000,
  "impressionsMax": 2250000,
  "spendMinUsd": 2000000,
  "spendMaxUsd": 2500000,
  "spendCurrency": "USD",
  "targetedAges": ["18-24", "25-34", "35-44", "45-54", "55-64", "65+", "Unknown"],
  "excludedAges": null,
  "targetedGenders": ["Women", "Men", "Unknown"],
  "excludedGenders": null,
  "targetedGeoIds": ["21173", "21138", "21152", "1014895"],
  "excludedGeoIds": null
}
```

Two fields that trip people up. `daysServed` is the number of days the ad actually ran, which is not the gap between the two dates: an ad can sit dormant for months inside its own window. And spend is a bracket, so `spendMaxUsd` being `null` means the top bracket is open ended, as in "$2,000,000 and above", not that the value is missing.

### Use cases

- 🔍 **Competitor ad monitoring** by watching a rival's whole creative library and how long each ad survives.
- 🧲 **Lead generation** by finding businesses actively spending on Google Ads in your niche.
- 💡 **Creative research** by pulling the ads a category leader keeps running, which is the closest thing to a public A/B test result.
- 🗳️ **Election ad transparency** for journalists and researchers tracking who spends what, and which voters they aim at.
- 🕵️ **Affiliate and reseller discovery** by searching a domain and seeing every advertiser pushing traffic to it.
- 📈 **Campaign longevity analysis** using days served to separate the always on winners from the ads that were quietly killed after a week.
- 🌍 **Market entry research** by comparing which ads a brand runs in one country versus another.
- 🗂️ **Compliance archives** that preserve a dated record of what an advertiser was claiming publicly.

### Limitations

- **You cannot search the words inside ads.** Google offers no keyword search here. You search by advertiser, by domain, or by ID.
- **Spend and impressions exist only for election ads.** Google does not publish them for commercial advertisers, at any price, from any tool.
- **Spend and impressions are brackets, not exact figures**, and the top bracket has no upper bound.
- **Age and gender targeting appears on roughly half of election ads.** District level targeting is far more common. When an advertiser did not use a targeting type, the field is empty because there is nothing to report.
- **Ad text and video files are not included.** Google keeps those behind a separate preview page, so you get the image links and the preview URL instead.
- **Russia is unavailable**, because Google stopped serving ads there in 2022. Every other country Google publishes is supported.

### FAQ

#### How much does Google Ads Transparency Scraper cost?

It uses pay per result pricing, starting at **$2.00 per 1,000 ads** and falling to **$0.90** on higher Apify plans. The discount applies automatically, so there is nothing to negotiate. The Free plan's $5 in monthly credits covers around 2,500 ads.

No subscription lock-in. Pause whenever.

#### Is it legal to scrape Google Ads Transparency Center?

Scraping public data is generally allowed in the US and most of the EU, as long as you don't collect personal data covered by GDPR or CCPA without a lawful basis. Google publishes this Transparency Center itself, deliberately, for public scrutiny. How you use the output is on you.

Apify's full breakdown: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/).

#### Can I integrate it with other tools?

Push results into **Make, Zapier, Slack, Airbyte, GitHub, Google Sheets, Google Drive**, and more. Apify treats every actor as a webhook source, so anything that consumes webhooks or pulls from an API works.

Full list: [Apify integrations](https://docs.apify.com/platform/integrations).

#### Can I use it with the Apify API?

Yes. Every run is available via the Apify REST API:

```bash
curl -X POST "https://api.apify.com/v2/acts/sourabhbgp~google-ads-transparency-scraper/runs?token=APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode": "creatives", "domain": "nike.com", "regions": ["US"], "maxResults": 100}'
```

Docs: [Apify API reference](https://docs.apify.com/api/v2).

#### Can I use it through an MCP Server?

Yes. Apify ships an MCP server that exposes every actor as a tool, so Claude Desktop, Cursor, and any other MCP capable client can call this scraper. Setup: [Apify MCP docs](https://docs.apify.com/platform/integrations/mcp).

### Your feedback

Bug, missing field, or odd behavior? Drop a note in the [Issues tab](https://console.apify.com/actors/dfSc5VDYClNvIXj1l/issues). Reports go to a human and fixes usually ship the same week.

# Actor input Schema

## `mode` (type: `string`):

Commercial ads, or election ads which additionally carry spend, impressions and audience targeting.

## `advertiserName` (type: `string`):

Finds an advertiser by name, for example Nike. This matches advertiser names only. Searching the text inside ads is not supported by Google.

## `domain` (type: `string`):

Exact domain in lowercase, for example nike.com. Returns every advertiser sending traffic to that domain, including resellers and affiliates.

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

IDs starting with AR. Several IDs are combined with OR.

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

One request is sent per country, so adding countries adds runtime. Russia is not listed because Google does not publish ads there.

## `platforms` (type: `array`):

Where the ad ran. One request is sent per surface. Leave empty for all surfaces.

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

Filter by creative type. Text, image or video.

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

YYYY-MM-DD. Inclusive.

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

YYYY-MM-DD. This date is EXCLUSIVE: ads shown only on this day are not returned. Use the day after the last day you want.

## `maxResults` (type: `integer`):

Total ads across all countries and surfaces. If you omit this field entirely, the platform uses 50.

## `detailConcurrency` (type: `integer`):

Parallel detail lookups. 10 is the tested sweet spot.

## `minSpendUsd` (type: `integer`):

Election ads only. Keeps ads whose spend range can reach this amount. Ads in the open ended top bucket are always kept.

## `sortBy` (type: `string`):

Election ads only.

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

Datacenter proxy is enough for this target.

## Actor input object example

```json
{
  "mode": "creatives",
  "domain": "nike.com",
  "advertiserIds": [],
  "regions": [
    "US"
  ],
  "platforms": [],
  "adFormat": "ALL",
  "maxResults": 50,
  "detailConcurrency": 10,
  "sortBy": "RECENCY",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

View the scraped ads in the dataset.

# 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 = {
    "mode": "creatives",
    "domain": "nike.com",
    "regions": [
        "US"
    ],
    "adFormat": "ALL",
    "maxResults": 50,
    "detailConcurrency": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("sourabhbgp/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 = {
    "mode": "creatives",
    "domain": "nike.com",
    "regions": ["US"],
    "adFormat": "ALL",
    "maxResults": 50,
    "detailConcurrency": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("sourabhbgp/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 '{
  "mode": "creatives",
  "domain": "nike.com",
  "regions": [
    "US"
  ],
  "adFormat": "ALL",
  "maxResults": 50,
  "detailConcurrency": 10
}' |
apify call sourabhbgp/google-ads-transparency-scraper --silent --output-dataset

```

## MCP server setup

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