# Google Ads Transparency Scraper: Ad Copy, Creatives & New Ads (`datasmithlab/google-ads-transparency-scraper`) Actor

Search Google Ads Transparency Center by advertiser or domain. Export copy and media where available, filter by region/platform/date and monitor unseen ads. Coverage depends on limits and source access.

- **URL**: https://apify.com/datasmithlab/google-ads-transparency-scraper.md
- **Developed by:** [Datasmithlab](https://apify.com/datasmithlab) (community)
- **Categories:** SEO tools
- **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: Ad Copy, Creatives & New Ads

Export ads from the [Google Ads Transparency Center](https://adstransparency.google.com) with structured copy and media when Google provides them. Headlines, descriptions, sitelinks, CTA, Shopping product titles and YouTube IDs depend on the creative; image-rendered previews may have no copy fields.

Search by advertiser, domain or ID and filter by region, platform, format and date. Limits and source access determine coverage; this is not a guaranteed complete ad archive.

### Quick start

Start with one domain, monitoring off and a small limit. Check TARGETS and HEALTH for access, pages and copy availability. Monitoring identifies previously unseen IDs, not necessarily newly published ads. Older ads missed by a limited first run can appear as new later.

```json
{
  "queries": [
    "nike.com"
  ],
  "region": "US",
  "resultType": "ads",
  "includeAdContent": true,
  "includeDetails": false,
  "onlyNewAds": false,
  "maxAdsPerTarget": 10,
  "maxItems": 10
}
```

### Track competitor ads in Google Sheets with n8n

Keep a daily creative log without duplicating saved ad IDs. Use the **Sheets-only n8n starter** with your own Apify and Google accounts; no Slack account is required.

**[Download the n8n starter ZIP](https://github.com/Datasmith-lab/datasmithlab-google-ads-n8n/releases/latest/download/google-ads-to-sheets-starter.zip)** · **[View the walkthrough](https://datasmith-lab.github.io/datasmithlab-google-ads-n8n/)** · **[Read the setup guide](https://github.com/Datasmith-lab/datasmithlab-google-ads-n8n#setup)**

1. Import the inactive workflow and create an **Ads** tab using the supplied headers.
2. Set your competitor domain and spreadsheet ID, then select your Apify Header Auth and Google Sheets credentials.
3. Run a small manual baseline and repeat test; then enable the daily schedule if the results are correct.

The starter launches one Actor run per execution, validates HEALTH/TARGETS and merges rows using scope + advertiser ID + ad ID. Defaults are a 20-ad snapshot, copy on, details off, Actor-side `onlyNewAds=false` and `maxTotalChargeUsd=0.10`. First-seen IDs are not verified newly published ads; older ads can appear later. This is not a complete inventory or a total-invoice guarantee. Self-hosted n8n must stay running, and executions should not overlap.

Fresh scraping, live Sheets delivery and actual scheduled execution were tested on local n8n 2.26.4. The final read-back contained 34 unique saved keys and zero duplicates. The walkthrough uses synthetic examples. The GitHub starter is not an approved n8n template-directory listing.

### What you get

- **Ad copy as fields.** Search ads: `headline`, `description`, `displayUrl`, `businessName` and `sitelinks` (title + description). Image and video ads: `headline`, `description`, `longHeadline`, `callToAction`, `displayUrl`. Google Maps ads: `headline`, `address`. Shopping ads: `productTitle`, `merchant`, `productImageUrl`. YouTube ads: `youtubeVideoId`.
- **Core fields on returned ads (where available):** advertiser name and ID, landing domain, format (TEXT / IMAGE / VIDEO), first and last shown dates, Google's *days shown* count, image or preview URL and a link to the ad on the Transparency Center. The `adTemplate` field says which kind of ad it is (`search_text`, `local`, `shopping`, `rich_media`, `youtube`, `image`).
- **Regions and variations** (optional): the countries an ad was shown in with the last date, plus every variation of the creative.
- **Filters:** country (or anywhere), platform (YouTube, Google Maps), format (text, image, video), shown-from / shown-until dates.
- **Only new ads.** Turn on *Only new ads since last run* and schedule the Actor daily to get a feed of your competitors' new creatives. Make the first run large enough to cover the advertiser's current ads; anything the first run did not reach still counts as new later.
- **Advertisers mode.** One row per domain: is it advertising, how many ads Google reports and under which advertiser names. Or one row per advertiser matching a name, with country and ad count. Useful for lead lists and market maps.
- **Reports** in the run's key-value store: `TARGETS` (status, pages and Google's total ad count per advertiser/domain) and `HEALTH` (requests, Google blocks, IP changes, ad types found, empty-field ratios).

### How to search

| You want | Set |
|---|---|
| Ads landing on a site within your limits | **Advertiser names, domains or IDs** `hubspot.com` |
| A brand's ads | `Nike` (matched to the advertisers Google suggests; the ones with the most ads are used first) |
| One exact advertiser | Its ID, e.g. `AR16735076323512287233`, or paste its Transparency Center page |
| Only YouTube video ads in the UK | **Platforms** YouTube, **Ad format** Video, **Region** GB |
| Ads shown last month | **Shown from** / **Shown until** |
| Which of 500 domains advertise | Put them in **Domains**, set **What to return** to *Advertisers* |

### Output example

```json
{
  "adId": "CR01858916718210973697",
  "advertiserId": "AR16735076323512287233",
  "advertiserName": "Nike, Inc.",
  "domain": "nike.com",
  "format": "TEXT",
  "firstShown": "2023-11-17T03:30:48Z",
  "lastShown": "2026-10-07T07:45:42Z",
  "daysShown": 799,
  "adTemplate": "search_text",
  "headline": "The Latest Fleece Sweatpants - Browse Men's Bottoms",
  "displayUrl": "www.nike.com/shop/fleece-sweats",
  "description": "Be comfortable and confident in whatever you wear. Fleece sweats made to move with you. ...",
  "businessName": "Nike",
  "adUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR01858916718210973697?region=US",
  "region": "US"
}
```

### Good to know

- **Ad copy is available when Google publishes a preview.** For many text ads Google only publishes a ready-made image of the ad, with no text behind it. Those rows come with `imageUrl` and no copy fields, and they are charged at the lower *Ad* price. How many ads have copy depends a lot on the advertiser: in our tests it ranged from about 5% (brands running mostly image-rendered search ads) to over 90% (Shopping-heavy retailers). The `HEALTH` report shows the split for every run.
- **Shopping prices are not available.** Google shows `[Price]` placeholders in its own previews, so no tool can read prices from the Transparency Center. Product title, merchant and product image are returned.
- **Text is returned as Google shows it**, including dynamic keyword placeholders such as `{__PLACEHOLDER__}` and descriptions Google already cut with `...`.
- **A proxy is required.** Google shows a CAPTCHA to any single IP after a few dozen requests. The Actor uses Apify's residential proxy by default and, when that happens, waits a few seconds and switches to a new IP. It never solves CAPTCHAs; if Google keeps blocking after 5 IP changes, the run stops, keeps everything already collected (row charges apply to returned rows; start and applicable run costs still apply), and reports the target as `blocked`. Datacenter proxies are cheaper but get blocked quickly on this site; keep the default unless you know your proxy works.
- **Advertiser names are published by Google.** Google verifies advertisers and lists their legal names, which for some small advertisers is a person's name. The Actor returns ad data as Google publishes it; it is not a people-search tool and collects no contact details.
- **Pasted URLs:** only the advertiser or domain is taken from a Transparency Center URL. Use the Region, Platforms and date fields for filters.

### Pricing

FREE-tier event rates checked on 11 October 2026 (FREE is the tier name, not a free run):

- `apify-actor-start`: $0.001 per event.
- `ad`: $0.0015 per event.
- `ad-with-content`: $0.0025 per event.
- `advertiser`: $0.002 per event.

Start event count depends on memory: one per GB, minimum one. Zero output can still incur start and applicable run costs. Row prices do not guarantee the total invoice. Store pricing is authoritative; rates and tier discounts may change.

The content event replaces the basic ad event for that row; they are not added together.

Pay per row, plus a small start fee per run:

- **Ad**: an ad without extracted copy (for example an image-only ad).
- **Ad with copy or details**: an ad where real copy (headline, description, address, product title, CTA, sitelinks or YouTube ID) or regions/variations were found. A merchant name or URL alone does not count.
- **Advertiser or domain check**: one row in *Advertisers* mode.

Turn off *Extract ad copy* if you only need IDs, dates and images.

### Feedback

Missing a field, a filter or an ad type? Open an issue on this Actor's page. We read every one and reply.

*Not affiliated with or endorsed by Google. Google Ads is a trademark of Google LLC.*

# Actor input Schema

## `queries` (type: `array`):

Advertiser names (Nike), domains (nike.com) or advertiser IDs (AR16735076323512287233). A name is matched to the advertisers Google suggests for it.

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

Optional. Ads whose landing page is on these domains, e.g. hubspot.com.

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

Optional. IDs from the advertiser's Transparency Center page (AR…).

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

Optional. Paste advertiser pages (adstransparency.google.com/advertiser/AR…) or domain searches (?domain=…). Only the advertiser or domain is taken from the URL; use the Region, Platforms and date fields below for filters.

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

Advertisers mode is a cheap check: total ad count and advertiser names for each domain, or the advertisers that match each name.

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

Country where the ads were shown, or 'anywhere'.

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

Leave empty for all platforms. YouTube and Google Maps for now; more platforms are added once each filter is verified.

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

Leave empty for all.

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

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

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

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

## `includeAdContent` (type: `boolean`):

Read each ad's preview and return its text: headline, description, display URL, sitelinks, CTA, Shopping product title, YouTube video ID. Ads where text is found are charged as 'ad with content'.

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

One extra request per ad: the countries it was shown in (with last shown date) and all its variations.

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

Return only ads not seen in a previous run with the same search. Schedule it daily to monitor competitors. Make the first run large enough to see all current ads (a small first run leaves older ads 'new'). Up to 10 extra pages of already seen ads are checked per advertiser/domain.

## `maxAdsPerTarget` (type: `integer`):

Per domain, per advertiser ID, and per advertiser matched by a name. Google returns 40 ads per page. With 'Only new ads', already seen ads do not count.

## `maxAdvertisersPerQuery` (type: `integer`):

A name like 'Nike' matches several advertisers; the ones with the most ads are used first.

## `maxItems` (type: `integer`):

Hard stop: you are never charged for more rows than this.

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

Google limits each IP to a few dozen requests. Residential proxy (default) is the most reliable; datacenter IPs get blocked quickly.

## Actor input object example

```json
{
  "queries": [
    "nike.com"
  ],
  "resultType": "ads",
  "region": "US",
  "includeAdContent": true,
  "includeDetails": false,
  "onlyNewAds": false,
  "maxAdsPerTarget": 10,
  "maxAdvertisersPerQuery": 3,
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Table view (JSON/CSV/Excel export).

## `allFields` (type: `string`):

Every field, including sitelinks, regions and variations.

## `targets` (type: `string`):

For each advertiser/domain: status, pages, ads seen and written, Google's total.

## `health` (type: `string`):

Requests, Google blocks, IP changes, ad types found, empty-field ratios.

# 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 = {
    "queries": [
        "nike.com"
    ],
    "resultType": "ads",
    "region": "US",
    "includeAdContent": true,
    "includeDetails": false,
    "onlyNewAds": false,
    "maxAdsPerTarget": 10,
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("datasmithlab/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 = {
    "queries": ["nike.com"],
    "resultType": "ads",
    "region": "US",
    "includeAdContent": True,
    "includeDetails": False,
    "onlyNewAds": False,
    "maxAdsPerTarget": 10,
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("datasmithlab/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 '{
  "queries": [
    "nike.com"
  ],
  "resultType": "ads",
  "region": "US",
  "includeAdContent": true,
  "includeDetails": false,
  "onlyNewAds": false,
  "maxAdsPerTarget": 10,
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call datasmithlab/google-ads-transparency-scraper --silent --output-dataset

```

## MCP server setup

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