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

Google Ads Transparency scraper: get every ad creative from the Google Ads Transparency Center by domain, advertiser ID, URL or advertiser name, with format, first/last shown dates, regions, platforms, impressions, ad text, landing URL and media links. Monitor new ads.

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

## Pricing

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

## Google Ads Transparency Scraper

Google Ads Transparency Scraper pulls every public ad a company runs on Google — Search, YouTube, Shopping, Maps and Play — from the [Google Ads Transparency Center](https://adstransparency.google.com/) into a clean dataset. Give it a domain, an advertiser ID, a Transparency Center link or a brand name and get each ad's format, run dates, regions, platforms, impression ranges, ad copy and media links.

![Google Ads Transparency Scraper output in Apify: advertiser, ad format, first and last shown dates, platforms, regions, impressions, headline and description](https://api.apify.com/v2/key-value-stores/lwQu1lCMCLQIIhSMQ/records/google-ads-transparency-scraper-output.png)

*Real output from a default run of Google Ads Transparency Scraper in Apify Console.*

### What can it do?

- **Four ways to pick advertisers** — domains (`nike.com`), advertiser IDs (`AR…`), Transparency Center URLs (advertiser, single ad or domain pages) and advertiser-name search (`Nike`).
- **All filters the Transparency Center has** — country (240+ regions), date range, format (text, image, video) and platform (Google Search, YouTube, Google Shopping, Google Maps, Google Play). Filters inside a pasted URL are respected.
- **Ad copy, not just a screenshot** — reads Google's rendered preview to return headline, description, display URL, call to action, YouTube video ID and, when Google exposes it, the landing URL. All visible preview text is kept in `adTextLines`.
- **Reach and targeting** — regions where each ad ran, per-region first/last shown dates, impression ranges per platform (where Google publishes them) and the audience-selection categories the advertiser used.
- **Advertiser facts** — legal name, country and whether Google verified the advertiser's identity, plus a per-advertiser rollup in the key-value store.
- **Monitoring mode** — `onlyNewAds` remembers what earlier runs returned, so a scheduled run outputs only ads you haven't seen.
- **Fast mode** — switch off details and previews to list about 1,000 ads per minute when you only need IDs, formats, dates and image links.
- **Built to keep running** — browser-grade request headers, a new proxy IP on every retry, automatic residential fallback when Google throttles datacenter IPs, and a timeout guard that saves everything collected so far.

### What data you get

| Field | Description |
|---|---|
| `advertiserId`, `advertiserName` | Google advertiser ID (AR…) and display name |
| `advertiserLegalName`, `advertiserCountry`, `advertiserVerified` | Verified legal name, home country, identity-verified flag |
| `creativeId` | Google creative ID (CR…), unique per ad |
| `format` | `TEXT`, `IMAGE` or `VIDEO` |
| `firstShown`, `lastShown`, `daysShown` | Run dates (YYYY-MM-DD) and number of days served |
| `regions`, `regionCount`, `regionStats` | Countries the ad ran in; per region: first/last shown, impressions, per-platform impressions |
| `platforms` | Google Search, YouTube, Google Shopping, Google Maps, Google Play (where published) |
| `impressionsMin`, `impressionsMax` | Impression range summed across regions (mainly EU/EEA and Türkiye) |
| `headline`, `longHeadline`, `description` | Ad copy read from the preview (best effort) |
| `displayUrl`, `destinationUrl`, `callToAction` | Display URL, landing URL when exposed, CTA label |
| `adTextLines` | Every visible text line of the rendered preview |
| `imageUrl`, `imageUrls` | Main image / archived snapshot and all variation images |
| `videoId`, `videoUrl`, `thumbnailUrl` | YouTube video for video ads |
| `previewUrl`, `previewType`, `variationCount` | Google's preview script, preview kind (Single Ad, Local Ad, Product Listing Ad…), number of variations |
| `targeting` | Demographics / geography / contextual / customer-list targeting with included/excluded flags |
| `transparencyUrl`, `advertiserUrl` | Links back to the Transparency Center |
| `input`, `inputType`, `filterRegion`, `scrapedAt` | Which input produced the row, region filter, timestamp |

The key-value store also gets `ADVERTISERS` (one entry per advertiser: verification, total ads Google reports, ads saved, formats, platforms, regions, date span), `SUMMARY` (totals, filters, field fill rates, request and byte counts) and `ERRORS` (only when something failed). These are free — only ad rows are billed.

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

You pay per ad saved: **$1.20 per 1,000 ads** ($0.0012 per ad), plus Apify's tiny per-run start fee. Advertiser summaries, the run summary and error records are never charged, and duplicate ads (the same creative reached through two inputs) are saved once.

On paid Apify plans the per-result price drops automatically (Bronze and above get volume discounts); the Pricing tab shows your exact rate.

- **Example 1:** all ads a competitor showed in the US in the last 30 days, 300 ads → about $0.36.
- **Example 2:** a weekly monitor on 5 competitor domains that returns ~40 new ads per run → about $0.05 per week.

Set a **maximum charge per run** in Apify Console and the Actor stops exactly at that budget. `maxTotalAds` is a second hard cap.

### How to use Google Ads Transparency Scraper

1. Open the Actor in Apify Console and click **Try for free**.
2. Add one or more **advertiser domains** (e.g. `nike.com`), **advertiser IDs**, **Transparency Center URLs** or **advertiser names**.
3. Optionally choose a **region**, **date range**, **format** and **platform**.
4. Set **Max ads per advertiser** (Google lists the most recently shown ads first).
5. Click **Start**. Download the ads as JSON, CSV, Excel or HTML, or read them through the API.

Tip: for brands, a domain is usually the most complete input — it covers every advertiser account Google links to that website (resellers and agencies included). Advertiser-name search matches account names, not ad copy.

### Input example

```json
{
  "advertiserDomains": ["nike.com"],
  "advertiserIds": ["AR16735076323512287233"],
  "startUrls": ["https://adstransparency.google.com/advertiser/AR16735076323512287233?region=DE&platform=YOUTUBE"],
  "searchTerms": ["Adidas"],
  "maxAdvertisersPerSearchTerm": 2,
  "region": "US",
  "dateFrom": "30 days",
  "format": "ALL",
  "platform": "ALL",
  "maxAdsPerAdvertiser": 200,
  "includeDetails": true,
  "extractAdContent": true,
  "onlyNewAds": false
}
```

### Output example

```json
{
  "advertiserId": "AR10000000000000000001",
  "advertiserName": "Example Running Co.",
  "advertiserLegalName": "Example Running Company Ltd",
  "advertiserCountry": "GB",
  "advertiserVerified": true,
  "creativeId": "CR20000000000000000001",
  "format": "TEXT",
  "firstShown": "2025-11-03",
  "lastShown": "2026-10-25",
  "daysShown": 297,
  "regions": ["DE", "FR", "GB"],
  "regionCount": 3,
  "platforms": ["Google Search", "Google Maps"],
  "impressionsMin": 21000,
  "impressionsMax": 30000,
  "regionStats": [
    {
      "regionCode": "DE",
      "regionName": "Germany",
      "geoId": 2276,
      "firstShown": "2025-11-03",
      "lastShown": "2026-10-25",
      "impressionsMin": 15000,
      "impressionsMax": 20000,
      "platforms": [
        { "platform": "Google Search", "impressionsMin": 14000, "impressionsMax": 18000 },
        { "platform": "Google Maps", "impressionsMin": 1000, "impressionsMax": 2000 }
      ]
    }
  ],
  "headline": "Example Running - Official Store",
  "longHeadline": null,
  "description": "Free delivery over £50. Shop new trail and road running shoes today.",
  "displayUrl": "www.example-running.com/trail",
  "destinationUrl": null,
  "callToAction": null,
  "adTextLines": ["example-running.com", "www.example-running.com/trail", "Example Running - Official Store", "Free delivery over £50. Shop new trail and road running shoes today."],
  "domain": "example-running.com",
  "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/1234567890123456789",
  "imageUrls": ["https://tpc.googlesyndication.com/archive/simgad/1234567890123456789"],
  "videoId": null,
  "videoUrl": null,
  "thumbnailUrl": null,
  "previewUrl": "https://displayads-formats.googleusercontent.com/ads/preview/content.js?client=ads-integrity-transparency&creativeId=...",
  "previewType": "Single Ad",
  "variationCount": 3,
  "targeting": {
    "demographics": { "included": true, "excluded": false },
    "geography": { "included": true, "excluded": true },
    "contextual": { "included": true, "excluded": false },
    "customerLists": null
  },
  "transparencyUrl": "https://adstransparency.google.com/advertiser/AR10000000000000000001/creative/CR20000000000000000001?region=US",
  "advertiserUrl": "https://adstransparency.google.com/advertiser/AR10000000000000000001?region=US",
  "input": "example-running.com",
  "inputType": "domain",
  "filterRegion": "US",
  "scrapedAt": "2026-10-26T09:00:00.000Z"
}
```

### Use with the API

**cURL** — run and get the ads in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/groupoject~google-ads-transparency-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"advertiserDomains": ["nike.com"], "maxAdsPerAdvertiser": 50}'
```

**Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("groupoject/google-ads-transparency-scraper").call(
    run_input={"advertiserDomains": ["nike.com"], "region": "US", "maxAdsPerAdvertiser": 100}
)
for ad in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(ad["format"], ad["lastShown"], ad["headline"], ad["transparencyUrl"])
```

**JavaScript** (`npm install apify-client`):

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('groupoject/google-ads-transparency-scraper').call({
    advertiserIds: ['AR16735076323512287233'],
    platform: 'YOUTUBE',
    maxAdsPerAdvertiser: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((ad) => [ad.videoUrl, ad.headline]));
```

### Use with AI agents / MCP

Connect the Actor to Claude, Cursor or any MCP client through the Apify MCP server:

```
https://mcp.apify.com?tools=groupoject/google-ads-transparency-scraper
```

Example prompt: *"Use google-ads-transparency-scraper to list the YouTube ads competitor.com ran in Germany in the last 30 days and summarise their headlines and calls to action."*

### Integrations

Send results to **Google Sheets**, **Make**, **Zapier**, **n8n**, Slack or your own **webhooks** using Apify integrations. A common setup: schedule a daily run with `onlyNewAds: true` and post each new competitor ad to a Slack channel or append it to a Google Sheet.

### FAQ

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

The Transparency Center is a public library Google publishes so anyone can see who advertises and what they show. This Actor reads only that public data, without logging in, and does not collect personal data about private individuals. You are still responsible for how you use the data; check your local laws and Google's terms for your use case.

#### Why do some ads have no headline or description?

Google archives many text ads only as a rendered image. For those, the copy is inside the image (`imageUrl`) and there is no text to read. Dynamic Search Ads and keyword-insertion ads show placeholders such as `{KeyWord:Running Shoes}` because Google fills the text at serving time. `adTextLines` always holds whatever text the preview contains.

#### Why are impressions and platforms empty for many ads?

Google publishes impression ranges and platform breakdowns mainly for ads shown in the EU/EEA and Türkiye (under the Digital Services Act). For other regions only the regions and dates are public, so those fields stay `null` or empty instead of being guessed.

#### Why did I get fewer ads than the Transparency Center count, or none at all?

Check the filters: a region plus a short date range can legitimately be empty, and Google applies date filters only to roughly the last 12 months. Age-restricted ads are hidden from logged-out visitors, so they are not available. A typo in the domain or ID is reported in the `ERRORS` record. The count Google shows is an estimate (e.g. "~50K").

#### How fast is it, and how many ads can I get?

With details and previews on (default) a run enriches roughly 70–120 ads per minute (in our tests: 347 ads in about 3 minutes). With both switched off it lists up to 100 ads per request — about 1,000 ads per minute in our tests. There is no fixed cap: set `maxAdsPerAdvertiser`, `maxTotalAds` or a maximum charge to stop where you want.

#### Do I need proxies?

No setup needed. The default Apify Proxy (datacenter) is used and each retry gets a new IP. If Google throttles most datacenter requests, the run switches to Apify residential proxy automatically (you can turn that off). No cookies, logins or CAPTCHA solving are used.

#### How do I monitor a competitor's new Google ads?

Turn on **Only new ads**, give the monitor a name, and schedule the Actor (daily or weekly) in Apify Console. The first run records everything it finds; later runs output only creatives not returned before. Pair it with a webhook, Slack or Google Sheets integration to get alerts.

#### Can I scrape a single ad?

Yes. Paste its Transparency Center link (`/advertiser/AR…/creative/CR…`) into Transparency Center URLs.

### Related actors

- [Facebook Ads Library Scraper — Meta Ad Library, No Login](https://apify.com/groupoject/meta-ads-library-scraper-no-login): the same competitor-ad research for Facebook and Instagram.
- [Google AI Overview Tracker](https://apify.com/groupoject/google-ai-overview-tracker): see whether your brand and competitors are cited in Google AI Overviews.
- [Keyword Difficulty Checker](https://apify.com/groupoject/keyword-difficulty-checker): score how hard it is to rank organically for the keywords your competitors bid on.

# Actor input Schema

## `advertiserDomains` (type: `array`):

Websites whose Google ads you want, e.g. "nike.com". Returns ads from every advertiser account Google links to that domain. Protocol, "www." and paths are ignored.

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

Google advertiser IDs (start with "AR", e.g. AR16735076323512287233). Find them in an advertiser's Transparency Center URL or in a previous run's output.

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

Links copied from adstransparency.google.com: an advertiser page (/advertiser/AR...), a single ad (/advertiser/AR.../creative/CR...) or a domain search (?domain=...). Region, platform, format and date filters in the URL override the filters below for that URL.

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

Brand or company names, e.g. "Nike". Each term is matched against the Transparency Center's advertiser search and expands to the best-matching advertiser accounts (see the next field). This searches advertiser names, not ad copy.

## `maxAdvertisersPerSearchTerm` (type: `integer`):

How many matching advertiser accounts to scrape for each search term. Names that contain the term as a whole word rank first, then accounts with more ads.

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

Only ads shown in this country. "Anywhere" returns ads from all regions.

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

Only ads shown on or after this date. Use YYYY-MM-DD or a relative value like "30 days" or "6 months". Google only applies date filters to roughly the last 12 months.

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

Only ads shown on or before this date (YYYY-MM-DD or relative). Defaults to today when "Shown on or after" is set.

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

Only ads of this format.

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

Only ads shown on this Google platform.

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

Maximum ads to return for each domain, advertiser ID, URL or matched advertiser. Google lists the most recently shown ads first.

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

Hard cap for the whole run, across all inputs. 0 = no cap (your maximum charge limit still applies).

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

Opens each ad's detail record: regions where it ran, per-region first/last shown dates, impression ranges by platform (published mainly for EU/Türkiye), audience-targeting categories and the number of variations. Turn off for a faster, lighter run.

## `extractAdContent` (type: `boolean`):

Reads Google's rendered ad preview to pull headline, description, display URL, call to action, YouTube video ID, landing URL (when exposed) and image links. Adds roughly 40 KB of download per ad.

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

Remembers which ads earlier runs already returned and only outputs ads not seen before. The first run returns everything and records it. Ideal for scheduled runs.

## `monitorStateName` (type: `string`):

Optional name for the monitoring memory, so different schedules don't share it. Leave empty to derive it from the inputs and filters.

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

How many ads are enriched in parallel. Higher is faster but more likely to be throttled by Google.

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

Apify Proxy (datacenter) is the default. Every retry uses a new IP, and the run can switch to residential automatically if Google blocks datacenter IPs (see next option).

## `residentialFallback` (type: `boolean`):

If Google throttles most datacenter requests (HTTP 429 / 'unusual traffic'), switch this run to Apify residential proxy so it still finishes. Has no effect when you already selected residential or use your own proxies.

## `debugMode` (type: `boolean`):

Log every request retry and parser decision.

## Actor input object example

```json
{
  "advertiserDomains": [
    "nike.com"
  ],
  "maxAdvertisersPerSearchTerm": 3,
  "region": "anywhere",
  "format": "ALL",
  "platform": "ALL",
  "maxAdsPerAdvertiser": 20,
  "maxTotalAds": 0,
  "includeDetails": true,
  "extractAdContent": true,
  "onlyNewAds": false,
  "maxConcurrency": 6,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "residentialFallback": true,
  "debugMode": false
}
```

# Actor output Schema

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

One row per ad creative.

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

Per advertiser: verification, country, total ads reported by Google, ads saved, formats, platforms, regions and date span.

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

Totals, filters, field fill rates, request and byte counts.

## `errors` (type: `string`):

Inputs that were invalid or could not be scraped (only present when something failed).

# 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 = {
    "advertiserDomains": [
        "nike.com"
    ],
    "maxAdsPerAdvertiser": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

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

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

```

## MCP server setup

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