# Google Ads Transparency Scraper — Competitor Ads & Creatives (`tortuga/google-ads-transparency-scraper`) Actor

Scrape Google Ads Transparency Center: all ads of any advertiser or website with format, first/last shown dates, countries, ad text, images and YouTube videos.

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

## Pricing

from $1.50 / 1,000 ad scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 — Competitor Ads & Creatives

Scrape the public **Google Ads Transparency Center** (adstransparency.google.com): every ad a competitor runs on Google Search, YouTube, Display, Shopping, Maps and Play. Search by **advertiser name**, **advertiser ID** (AR…), **website** (all advertisers that run ads for a domain) or paste a **Transparency Center URL**. Filter by **country**, **date range**, **format** (text, image, video) and **platform**.

You get one row per ad creative: creative and advertiser IDs, advertiser name, country and verification, format, first and last shown, number of days shown, the ad image or preview link, and the ad text of classic text and shopping ads. Turn on **Include ad details** for the full picture: headline, description, call to action, destination URL, images or the YouTube video, every variant, and every country where the ad ran with first/last shown dates and impression ranges per platform (plus EU targeting and political ad spend where Google publishes them).

No Google account, no login, no API key.

### What data does Google Ads Transparency Scraper extract?

| Field | Example | Notes |
|---|---|---|
| `creativeId` | `CR01820856573459693569` | Google's ID of the ad creative |
| `advertiserId`, `advertiserName` | `AR16735076323512287233`, `Nike, Inc.` | The verified advertiser |
| `advertiserCountry`, `advertiserLegalName`, `advertiserVerified` | `US`, `Nike, Inc.`, `true` | "Based in", legal name and identity verification |
| `format` | `TEXT`, `IMAGE`, `VIDEO` | Ad format as Google classifies it |
| `firstShown`, `lastShown` | `2023-11-17T01:09:13Z`, `2026-10-11T22:53:25Z` | When Google first and last showed the ad (UTC) |
| `daysShown` | `879` | Number of days the ad was shown |
| `headline`, `description`, `displayUrl`, `sitelinks` | `Nike® Official Site - The Latest Jordan 6` | Text ads. Classic text ads: always; others with **Include ad details** |
| `productTitle`, `productPrice`, `productCurrency`, `productSeller`, `merchant` | `114.99`, `GBP` | Shopping ads |
| `imageUrl`, `imageWidth`, `imageHeight` | `https://tpc.googlesyndication.com/archive/simgad/...` | Image ads, and text ads Google archived as an image |
| `previewUrl`, `previewType` | `https://displayads-formats.googleusercontent.com/ads/preview/content.js?...` | Google's preview of the ad (script / image) |
| `domain` | `nike.com` | The website matched in website searches |
| `impressions`, `spend`, `politicalRegions` | `{"lower": 35000, "upper": 40000}`, `{"currency": "USD", "lower": 700, "upper": 800}` | Political ads |
| `creativeUrl` | `https://adstransparency.google.com/advertiser/AR.../creative/CR...` | The ad's page in the Transparency Center |
| `searchInput`, `region` | `nike.com`, `US` | Which search produced the ad, and the country filter used |

With **Include ad details** (one extra request per ad, separate `details` event):

| Field | Notes |
|---|---|
| `headline`, `description`, `callToAction`, `displayUrl`, `destinationUrl`, `adTexts` | Text from the ad preview: responsive search, display, local and video ads (`adTexts` = all texts of the ad in order) |
| `imageUrls`, `youtubeVideoId`, `youtubeUrl` | Images of display ads; the YouTube video of video ads |
| `variations`, `variationCount` | Every variant of the ad (preview link or image; text of classic variants) |
| `regions` | Each country where the ad ran: `firstShown`, `lastShown`, `impressions` range and `platforms` (Search, YouTube, Shopping, Maps, Play) with their impression ranges, as Google publishes them |
| `regionCodes` | The same countries as a list (`["DE", "PL", "TR"]`) |
| `euImpressions`, `usImpressions` | Totals for the EU (Digital Services Act data) and for US political ads |
| `targeting` | Which targeting the advertiser used (demographics, locations, contextual signals, topics, customer lists: included/excluded); for political ads the targeted and excluded locations by name |
| `payerName`, `categoryId`, `containsSyntheticMedia` | Who paid (EU ads), Google's ad category, AI-generated media flag |

### How to scrape a competitor's Google ads

1. Enter the competitor in **Advertiser names or websites** (`Nike` or `nike.com`), in **Advertiser IDs** (`AR16735076323512287233`, from the advertiser's page URL) or paste a **Transparency Center URL**.
2. Optionally pick **Country**, **Ad format**, **Platforms** and a date range (**Shown from / until**, e.g. `30 days`).
3. Set **Max ads**, turn on **Include ad details** if you need the ad texts, YouTube videos and per-country data, and run. Download the results as JSON, CSV or Excel, or read them through the API.

A website search returns the ads of every advertiser that runs ads for that domain (for nike.com: Nike, Inc., Nike Retail BV, Nike's agencies and resellers). A name is matched to the advertiser with that exact name that has the most ads ("nike" → Nike, Inc., 9,000-10,000 ads); use the AR ID when you want one specific advertiser account.

### Input example

```json
{
  "searchTerms": ["nike.com"],
  "advertiserIds": ["AR16735076323512287233"],
  "startUrls": [
    { "url": "https://adstransparency.google.com/advertiser/AR16735076323512287233?region=US&format=VIDEO&platform=YOUTUBE" }
  ],
  "country": "US",
  "mediaType": "all",
  "dateFrom": "30 days",
  "includeDetails": true,
  "maxItems": 200,
  "maxItemsPerQuery": 100
}
```

### Output example

A Nike search ad found with `"searchTerms": ["nike"]`, country US and **Include ad details** on (run JAYQ0IaEcC2jk8d7l; variants and texts shortened):

```json
{
  "creativeId": "CR08772523512997871617",
  "advertiserId": "AR16735076323512287233",
  "advertiserName": "Nike, Inc.",
  "advertiserVerified": true,
  "advertiserCountry": "US",
  "advertiserLegalName": "Nike, Inc.",
  "format": "TEXT",
  "firstShown": "2023-11-16T22:45:12Z",
  "lastShown": "2026-10-11T23:18:42Z",
  "daysShown": 900,
  "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/9947846129517650742",
  "imageWidth": 348,
  "imageHeight": 322,
  "previewType": "image",
  "headline": "Nike® Official Site",
  "description": "Shop your style with the latest jumpsuits, rompers & bodysuits from Nike®. Gear up now.",
  "displayUrl": "nike.com",
  "adTexts": ["Nike® Official Site", "Shop your style with the latest jumpsuits, rompers & bodysuits from Nike®. Gear up now.", "Nike Factory Store - Kansas City", "1803 Village West Parkway Space M-125"],
  "variationCount": 5,
  "variations": [
    { "previewType": "image", "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/9947846129517650742", "imageWidth": 348, "imageHeight": 322 },
    { "previewType": "image", "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/3041684539231921355", "imageWidth": 364, "imageHeight": 354 }
  ],
  "regions": [{ "country": "US", "lastShown": "2026-09-01" }],
  "regionCodes": ["US"],
  "payerName": "Nike, Inc.",
  "creativeUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR08772523512997871617?region=US",
  "searchInput": "nike",
  "region": "US"
}
```

An EU ad with details carries per-country data like this:

```json
"regions": [
  {
    "country": "DE", "firstShown": "2024-06-12", "lastShown": "2026-10-11",
    "impressions": { "lower": 45000, "upper": 50000 },
    "platforms": [
      { "platform": "SEARCH", "impressions": { "lower": 25000, "upper": 30000 } },
      { "platform": "YOUTUBE", "impressions": { "lower": 15000, "upper": 20000 } }
    ]
  }
],
"targeting": { "demographics": { "included": true, "excluded": false }, "locations": { "included": true, "excluded": true } }
```

### Monitor changes on a schedule

Turn on **Only new or changed items** to track a competitor's new ads: the Actor remembers which ads earlier runs of the same input returned and outputs only ads it has not seen before (with **Also report ads shown again**, also known ads whose last-shown time moved, i.e. ads still running). Ads already seen are dropped before anything is saved, so they are not charged (nor are their details fetched). Save the input as a task, for example a competitor's advertiser ID with country US and **Max ads** 200, then add a Schedule to it in Apify Console (Schedules → Create new, daily) and connect a webhook, Slack or Google Sheets integration to get the new ads. Every output ad carries `changeType` (`new` or `changed`); changed ones carry `previousValues` with the old `lastShown`. The Transparency Center lists the most recently active ads first, so keep **Max ads** above the number of ads the advertiser runs at the same time. Use **Monitoring key** to keep several schedules on the same search separate.

### Does it work without login or an API key?

Yes. The Transparency Center is a public site that anyone can browse without an account, and Google offers no API for it. The Actor reads it the same way the site does, through Apify's ordinary datacenter proxy: no cookies, no CAPTCHA solving, no residential proxy. If a request fails, it is retried on another IP.

### Can I get the text of every ad?

Classic text ads and shopping ads carry their text in the preview link, so you get headline, description, display URL, sitelinks or product data in every row at no extra cost. Responsive search ads, display, local and video ads are assembled by Google's previewer; turn on **Include ad details** and the Actor opens the preview once per ad to read headline, description, call to action, destination URL, images and the YouTube video. Many text ads are archived by Google only as a picture of the ad: for those you get the image URL (`imageUrl`), and details add any variant that has text.

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

You pay per ad saved ($1.50 per 1,000 ads), plus $2.00 per 1,000 ads when **Include ad details** is on, plus the Apify platform usage of your run. Usage is small: one request returns 100 ads (15-75 KB), and one tiny lookup per advertiser fills in its country and legal name. In our tests a run of 100 ads used $0.0008 of platform usage and 13 ads with details $0.0007 (mostly the container start). Details add one small request per ad and, for ads whose text is not in the link, one preview download (50-500 KB).

**Proxy note:** keep the default datacenter proxy. The Unblocker and residential proxies are not needed.

### Legal and data notes

The Actor collects what Google publishes in its public Ads Transparency Center: ads, the verified advertisers that ran them (business names, the country they are based in) and the reach and targeting data Google discloses. It does not log in, does not access anything behind a login, and collects nothing about people who saw the ads. Ad images and videos stay on Google's servers; the dataset holds their links. You are responsible for using the data in line with Google's terms and the laws that apply to you.

# Actor input Schema

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

Advertiser names (e.g. 'Nike') or websites (e.g. nike.com), like the Transparency Center's search box. A name is matched to the advertiser with that name and the most ads; a website returns the ads of every advertiser shown for it.

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

Advertiser IDs (AR followed by digits, e.g. AR16735076323512287233) or advertiser page URLs (https://adstransparency.google.com/advertiser/AR...). The most precise way to watch one advertiser.

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

Websites (e.g. booking.com): all ads Google shows for that domain, from every advertiser that runs them.

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

URLs copied from adstransparency.google.com: an advertiser page, a website search (?domain=...), a political ads page or a single ad (/advertiser/AR.../creative/CR...). The URL's own filters (region, format, platform, dates) are used.

## `country` (type: `string`):

Only ads shown in this country: two-letter code such as US, GB, DE, FR, IN or BR. Leave empty (or ALL) for anywhere.

## `mediaType` (type: `string`):

Only text, image or video ads.

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

Only ads shown on these Google platforms. Leave empty for all.

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

Only ads shown on or after this date: YYYY-MM-DD or a period such as '30 days' (counted back from the run day).

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

Only ads shown on or before this date (YYYY-MM-DD or a period such as '1 day').

## `adType` (type: `string`):

All ads, or only political (election) ads, which carry impression and spend ranges. Political ads with no advertiser or website list every political ad of the chosen country.

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

Open each ad (charged as a separate 'details' event): ad text (headline, description, call to action, destination URL) and images or YouTube video, every variant, and every country where it ran with first/last shown dates, impression ranges per platform, EU/US totals and targeting (shown for EU and political ads).

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

Stop after this many ads in total. Keeps cost predictable.

## `maxItemsPerQuery` (type: `integer`):

Optional cap per name, advertiser, website or URL, so one big advertiser does not use up the whole run.

## `onlyNewOrChanged` (type: `boolean`):

Remember what earlier runs of this search returned and output only new items or items whose price/status changed. Use with a Schedule; unchanged items are not charged. For ads: ads that were not there in earlier runs. Max ads is then the number of ads checked per run (newest activity first).

## `watchLastShown` (type: `boolean`):

With 'Only new or changed items': also output known ads whose 'last shown' time moved since the previous run (i.e. ads that are still running), with the old value in previousValues.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same search stay separate; defaults to a key derived from the search input.

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

Apify Proxy. The default datacenter proxy works: the Transparency Center answers it directly (about 15-25 KB per 100 ads). Residential or Unblocker are not needed.

## Actor input object example

```json
{
  "searchTerms": [
    "nike.com"
  ],
  "mediaType": "all",
  "adType": "all",
  "includeDetails": false,
  "maxItems": 100,
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

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

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

```

## MCP server setup

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