# Google Ads Transparency Scraper — Competitor Ad Library (`aaronoptimus/google-ads-transparency-scraper`) Actor

Spy on competitor ads in the Google Ads Transparency Center: every Google ad a company or website runs (Search, YouTube, Display, Shopping) with ad text, format, first/last shown dates, previews and countries, plus new-ad alerts. Pay per ad plus a small start fee, no platform fees.

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

## Pricing

from $1.20 / 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.
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

See every ad a competitor runs on Google for **$1.50 per 1,000 ads** (from $1.20 on higher Apify plans), plus a $0.005 start fee per run and no platform fees. Search the public [Google Ads Transparency Center](https://adstransparency.google.com) by **brand name, website domain, advertiser ID or a pasted Transparency Center link**, and get each ad's format, first and last shown dates, how long it has run, Google's screenshot or preview, and optionally its ad text and countries. No login, no cookies, no Google account.

### What Google Ads Transparency data can you scrape?

- **Competitor ad research:** every creative a competitor runs, by country, with the date each one started. Ads that have run for months (`shownForDays`) are usually the ones that work.
- **Ad copy and products:** with *Ad details* on, each ad's headline, description and display URL, the product title and image of Shopping ads, the countries it ran in, and the YouTube video of video ads where Google shows it.
- **New-ad alerts:** turn on *Only new ads* and schedule a daily run. You get, and pay for, only ads you haven't received before.
- **Who advertises for a website:** search a domain like `nike.com` to see every advertiser account whose ads point there, including resellers and agencies.
- **Market research on companies:** run *Advertisers* mode on a list of companies to see which ones advertise on Google, how much (Google's approximate ad count), and from which country.
- **Google Ads IDs:** ads with a Google preview carry Google Ads' own customer, ad group and creative IDs, the same ones an agency sees in the advertiser's Google Ads account.

| What this tool doesn't do |
|---|
| No platform filter yet (Search / YouTube / Shopping / Maps / Play). No political-ads spend data. No landing-page crawling: Google rarely includes landing pages. Ad text comes from Google's preview, so purely visual ads have none. |

### How much does it cost to scrape Google Ads Transparency?

Pay per result plus a small start fee, no platform fees. Your Apify plan sets your price tier:

| Event | Free plan | Starter | Scale | Business |
|---|---|---|---|---|
| Ad (per 1,000) | $1.80 | $1.50 | $1.30 | $1.20 |
| Ad details found (per 1,000, only with *Ad details* on, only where found) | $3.60 | $3.00 | $2.70 | $2.40 |
| Advertiser (per 1,000, Advertisers mode) | $2.00 | $2.00 | $2.00 | $2.00 |
| Run start (per run) | $0.005 | $0.005 | $0.005 | $0.005 |

Apify's $5 free plan ≈ 2,700 ads.

Examples on Starter: 100 ads cost $0.155. 1,000 ads cost $1.505. 1,000 ads with details cost about $4.51. A daily monitoring run that finds 15 new ads costs $0.0275.

Ads your filters skip, ads Google doesn't have, ads already delivered by another of your searches and searches that fail are free. Set *Maximum cost per run* in the run options and the scraper stops exactly there.

### How to scrape Google Ads Transparency

1. Put your search terms in **Search terms**, one per line: `Nike` (advertiser name), `nike.com` or `https://www.nike.com/running` (domain), `AR16735076323512287233` (advertiser ID), or any adstransparency.google.com advertiser, ad or domain link.
2. Pick a **Region** (or *Anywhere*) and how many ads you want per search.
3. Click **Start**. In our own test, three Nike searches (name, domain and advertiser ID) returned 450 ads from 14 requests.

| Field | What it does |
|---|---|
| **Search terms** | Names, domains, advertiser IDs or Transparency Center links, mixed in one run. |
| **What to get** | *Ads* (default): one row per ad. *Advertisers*: one row per advertiser account. |
| **Region** | A country (e.g. United States) or *Anywhere*. Only ads shown in that country. |
| **Max ads per search** | Default 100, up to 10,000 per search term. With a format, date or *Only new ads* filter, a search looks through at most 10× this number (at least 1,000) to find matching ads. |
| **Ad format** | All, Text, Image or Video. |
| **Shown in the last N days** | e.g. 7 for ads shown in the past week. Best for scheduled runs; replaces *Shown on or after* when set. |
| **Shown on or after / on or before** | Date window (YYYY-MM-DD). An ad counts if it was shown at any time inside the window. |
| **Advertiser accounts per name** | Default 3, up to 10. How many matching accounts a name search uses. Exact matches come first; look-alike names (say "Nikes Tavern" for "Nike") are never used. |
| **Ad details** | Ad text (headline, description, display URL, business name), Shopping product title and image, countries shown, variations, YouTube video where shown (extra event, see the cost table). |
| **Only new ads** | Monitoring mode; see below. |
| **Proxy** | Apify Proxy by default; switches to residential IPs automatically if Google keeps refusing (no extra cost to you). |

#### Output

One row per ad. This one is from a real run in October 2026, with times rounded to the day:

```json
{
    "type": "ad",
    "searchTerm": "AR16735076323512287233",
    "searchType": "advertiser-id",
    "region": "US",
    "position": 2,
    "advertiserId": "AR16735076323512287233",
    "advertiserName": "Nike, Inc.",
    "creativeId": "CR06550380396951896065",
    "format": "TEXT",
    "formatCode": 1,
    "firstShown": "2024-10-21T00:00:00.000Z",
    "lastShown": "2026-10-06T00:00:00.000Z",
    "shownForDays": 716,
    "daysSinceLastShown": 0,
    "landingDomain": "nike.com",
    "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/17075086515930010296",
    "previewUrl": null,
    "width": 348,
    "height": 160,
    "googleCustomerId": null,
    "googleAdGroupId": null,
    "googleCreativeId": null,
    "adUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR06550380396951896065?region=US",
    "advertiserUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233?region=US"
}
```

With *Ad details* on, the same ad also had:

```json
{
    "regionsShown": ["US"],
    "adHeadline": "Nike® Official Site",
    "adDescription": "The classic Nike Shox are back with fresh and vibrant colors. Shop now at Nike®.",
    "adDisplayUrl": "nike.com",
    "productTitle": null,
    "detailsFound": true
}
```

- `imageUrl` is Google's own picture of the ad: for text ads Google stores a screenshot. Image, Shopping and video ads come with a `previewUrl` (Google's preview script) instead; *Ad details* reads the ad text, product and image out of it.
- `shownForDays` counts calendar days from first to last shown. `daysSinceLastShown` is 0–1 for ads running today.
- Detail fields: `regionsShown` (country codes), `variations`, `adHeadline`, `adDescription`, `adDisplayUrl`, `adBusinessName`, `productTitle`, `productImageUrl`, `adTextParts` (every text snippet found), `youtubeVideoId`, `youtubeUrl`, `landingUrl` (rarely available) and `detailsFound`. Fields Google doesn't show for an ad are `null`. Dynamic search ads have no fixed headline (Google writes it from the landing page), so `adHeadline` is `null` there.

In *Advertisers* mode, one row per advertiser account:

```json
{
    "type": "advertiser",
    "searchTerm": "Nike",
    "searchType": "name",
    "region": "anywhere",
    "advertiserId": "AR16735076323512287233",
    "advertiserName": "Nike, Inc.",
    "country": "US",
    "approxAdCountMin": 9000,
    "approxAdCountMax": 10000,
    "adsFound": null,
    "formats": null,
    "firstShown": null,
    "lastShown": null,
    "advertiserUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233?region=anywhere"
}
```

With a *Region*, name searches keep only the accounts that have ads in that country (Google's ad counts are still worldwide). For a domain or advertiser ID, Advertisers mode looks through up to *Max ads per search* of its ads and returns each advertiser account found, with `adsFound`, `formats` (ads per format) and the first/last shown dates of those ads.

The run's key-value store has an `OUTPUT` summary: per search term the advertiser accounts used, results delivered, ads looked at, whether the look-through limit was reached, and any error.

#### Monitoring competitors' new ads

1. Put your competitors in *Search terms*, turn on **Only new ads**, and give the job a **Monitoring memory name** (e.g. `competitors-us`).
2. Run it once: you get the competitors' ads (up to *Max ads per search* each), and the tool remembers them in a key-value store of that name in your Apify account.
3. Schedule it (Apify → Schedules), daily or weekly. Add *Shown in the last N days* (e.g. 7) to skip long-retired ads on the first run. Each run returns only ads it hasn't delivered before, and you pay only for those. Connect Slack, email or Zapier to the run to get alerts.

Set *Max ads per search* high enough to cover a competitor's current ads on the first run. If it is lower, the next runs also return older ads that didn't fit before; check `firstShown` to tell freshly launched ads apart. Delete or rename the memory store to start over.

### Google Ads Transparency API: Python, JavaScript, Zapier, Make and AI agents (MCP)

Run it from your own code with the Apify API or client libraries (the **API** tab shows ready-made Python, JavaScript and cURL snippets), from Zapier or Make with the Apify app, or from an AI agent through Apify's MCP server: `https://mcp.apify.com?tools=aaronoptimus/google-ads-transparency-scraper`.

Example input:

```json
{
    "searchTerms": ["nike.com", "Adidas", "AR16735076323512287233"],
    "region": "US",
    "maxAdsPerSearch": 200,
    "adFormat": "video",
    "shownInLastDays": 30
}
```

### Good to know

- The data is what Google publishes in its Ads Transparency Center. Google shows ads it served since 2018-05-31 (political ads in some regions earlier); ad counts in Advertisers mode are Google's own approximate ranges.
- A domain search returns every advertiser Google links to that domain, which can include resellers and unrelated accounts.
- Each ad is delivered once per run. If two of your search terms find the same ad, the second one skips it, and you aren't charged twice.
- Google limits requests per IP. The scraper rotates Apify proxy sessions, retries refused requests with growing pauses, and moves to residential IPs if needed. It never solves CAPTCHAs or logs in.
- A search that still fails is listed in the run log and the `OUTPUT` summary and is not charged. If Google ever changes its answer format, searches fail with a clear message instead of returning an empty "success".
- Runs time out after 1 hour by default. Plain ad searches take about a second per page of 100 ads; *Ad details* add a few requests per ad. For thousands of ads with details, raise the timeout in Run options. A run that nears its timeout stops cleanly and keeps everything delivered.
- If Google refuses the detail lookups for 3 ads in a row, the run delivers the rest of the ads without details (not charged for details).

### FAQ

**Do I need a Google account or API key?** No. The scraper reads the public Transparency Center, logged out.

**Why did a search return fewer ads than I asked for?** The advertiser has fewer ads (in that region), or your filters matched fewer within the look-through limit. The `OUTPUT` summary shows how many ads each search looked at.

**Is ad text included?** Yes, with *Ad details* on: headline, description, display URL and business name, or product title for Shopping ads, wherever Google's preview carries them. Without details you get Google's screenshot of text ads (`imageUrl`).

**What does a failed search cost?** Nothing. Only delivered ads, details and advertisers are charged, plus the run start fee.

**Is this legal?** The tool reads only the public, logged-out Google Ads Transparency Center, the same pages anyone can open in a browser. It collects advertiser information Google publishes for transparency and nothing about people who saw the ads. Most advertisers are companies, but some are individuals (sole traders, freelancers, political candidates) whose names Google publishes after verifying them. Don't use the data to profile or contact private persons; you are responsible for using it lawfully (including GDPR where it applies) and in line with Google's terms.

### Related tools

- [Google Trends Scraper](https://apify.com/aaronoptimus/google-trends-scraper): search interest over time and by region.
- [Google Hotels Scraper](https://apify.com/aaronoptimus/google-hotels-scraper): hotel prices and details from Google Hotels.
- [Google Jobs Scraper](https://apify.com/aaronoptimus/google-jobs-scraper): job listings from Google's job search.

### Support

Found a problem or need a field? Open an issue on the Issues tab. If the Actor saves you time, a short review helps others find it.

This Actor is an independent tool and is not affiliated with, endorsed by or sponsored by Google.

# Changelog

This Actor's version history is a separate document: https://apify.com/aaronoptimus/google-ads-transparency-scraper/changelog.md

# Actor input Schema

## `searchTerms` (type: `array`):

One per line: an advertiser or brand name (e.g. Nike), a website domain or URL (e.g. nike.com: every advertiser whose ads point there), an advertiser ID (AR followed by 20 digits), or a link copied from adstransparency.google.com (advertiser, ad or domain page).

## `resultType` (type: `string`):

Ads: every ad with format, first/last shown dates, preview and links. Advertisers: who advertises (name, ID, country, verification, Google's approximate ad count); for a domain or ID, the advertiser accounts found in up to "Max ads per search" of its ads.

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

Only ads shown in this country. Anywhere returns ads from all countries.

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

Stop each search term after this many ads (in Advertisers mode: how many ads of a domain or ID to look through). Big brands have thousands of ads. With a format, date or only-new filter, a search looks through at most 10× this number (at least 1,000).

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

Only ads of this format. Ads of other formats are skipped and not charged.

## `shownInLastDays` (type: `integer`):

Only ads shown within the last N days, today included (7 = the past week). Replaces "Shown on or after" when set. Handy for scheduled runs. 0 or empty = off.

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

Only ads shown on or after this date (YYYY-MM-DD), i.e. last shown on or after it. Google's archive starts on 2018-05-31.

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

Only ads shown on or before this date (YYYY-MM-DD), i.e. first shown on or before it.

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

A name like "Nike" matches several advertiser accounts (Nike, Inc., Nike Retail BV, …). Exact matches come first, then names that contain your words, biggest first. Look-alike names (e.g. "Nikes Tavern") are never used.

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

For each ad, also read its text (headline, description, display URL, business name) or Shopping product title and image from Google's preview, the countries it was shown in, its variations, and the YouTube video of video ads where Google shows it. Charged per ad only when details are found. Slower: up to two extra requests per ad.

## `onlyNewAds` (type: `boolean`):

Return only ads this tool hasn't delivered for the same search in earlier runs. The first run returns everything and remembers it. Schedule it daily or weekly to get competitors' new ads; you pay only for new ones.

## `monitorStoreName` (type: `string`):

Name of the key-value store in your Apify account that remembers delivered ads. Use a different name for each separate monitoring job.

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

Google limits how many requests one IP can make. Apify Proxy is recommended; sessions and IPs rotate automatically.

## `useResidentialFallback` (type: `boolean`):

If Google keeps refusing the default proxy, switch to Apify residential proxy IPs automatically. No extra cost to you.

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

How many search terms run at the same time, each from its own proxy session.

## `maxRetries` (type: `integer`):

How often a refused or failed request is retried (each time from a new proxy IP, with a growing pause) before the search is reported as failed. Failed searches are free.

## `saveRawSamples` (type: `boolean`):

Save the first few raw answers from Google to the run's key-value store (RAW-…). Only useful when reporting a problem.

## Actor input object example

```json
{
  "searchTerms": [
    "nike.com",
    "Coca-Cola"
  ],
  "resultType": "ads",
  "region": "US",
  "maxAdsPerSearch": 20,
  "adFormat": "all",
  "maxAdvertisersPerName": 3,
  "includeDetails": false,
  "onlyNewAds": false,
  "monitorStoreName": "ads-transparency-monitor",
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "useResidentialFallback": true,
  "maxConcurrency": 3,
  "maxRetries": 6,
  "saveRawSamples": false
}
```

# Actor output Schema

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

No description

## `runSummary` (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 = {
    "searchTerms": [
        "nike.com",
        "Coca-Cola"
    ],
    "region": "US",
    "maxAdsPerSearch": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("aaronoptimus/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 = {
    "searchTerms": [
        "nike.com",
        "Coca-Cola",
    ],
    "region": "US",
    "maxAdsPerSearch": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

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