# Google Ads Transparency Scraper: Competitor Ads by Domain (`fernandosord/google-ads-transparency-scraper`) Actor

Enter competitor domains (nike.com), advertiser IDs or Ads Transparency Center URLs. Get one row per ad: advertiser, format, first and last shown, headline, image, landing page and YouTube link for video ads. Filter by country, format and dates. No login.

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

## Pricing

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

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

Enter competitor domains such as nike.com, advertiser IDs (AR followed by digits) or Google Ads Transparency Center advertiser URLs, and get every ad Google shows for them as one row per ad: advertiser, format, first and last shown, headline, description, landing page, image and, for video ads, the YouTube link. Filter by country, ad format and dates. No login and no API key.

The data comes from the public [Google Ads Transparency Center](https://adstransparency.google.com/). The Actor calls the same endpoints the website uses, with plain HTTP and no browser, so a run of 10 ads takes about 10 seconds and 1,000 ads about 2 minutes.

### What data you get

One dataset item per ad creative.

| Field | Meaning |
|---|---|
| `input` | The domain, ID or URL you entered that produced this ad |
| `advertiserId`, `advertiserName` | Who paid for the ad, as Google lists them |
| `domain` | The website the ad was matched to (domain searches) |
| `creativeId` | Google's ID for the ad |
| `format` | `text`, `image` or `video` |
| `firstShown`, `lastShown`, `daysShown` | When Google first and last showed the ad, and for how many days |
| `regions` | Country codes where the ad ran. Only filled when you turn on the regions option |
| `headline`, `description`, `callToAction` | Ad copy, for image and video ads |
| `destinationUrl`, `displayUrl` | Landing page and the URL shown in the ad |
| `imageUrl`, `imageWidth`, `imageHeight`, `logoUrl` | Ad picture and logo. For text ads, `imageUrl` is the picture Google shows of the text ad |
| `videoUrl`, `videoThumbnailUrl`, `videoDuration`, `channelName` | YouTube link and details for video ads |
| `previewUrl` | Google's script URL that renders the ad (image and video ads) |
| `creativeUrl`, `advertiserUrl` | Links to the ad and to the advertiser on adstransparency.google.com |
| `scrapedAt` | When the row was collected |

Fields that do not apply to an ad are `null`. A run also writes a `SUMMARY` record to the key-value store with the count per input, inputs that had no ads or failed, and request statistics.

### How to use it

1. Open the Actor and put one or more entries in **Domains, advertiser URLs or advertiser IDs**. You can mix all three kinds.
2. Optional: pick a **Region**, an **Ad format**, and a date range.
3. Set **Max ads per domain or advertiser**. The default in the form is 10. Every ad costs money, so this is also your spending cap per entry.
4. Click Start. Download the dataset as JSON, CSV or Excel, or read it through the API.

A domain such as `nike.com` returns the ads that point to that website, from every advertiser that runs them (Nike itself, its regional entities and agencies). An advertiser ID or URL returns the ads of that one advertiser account.

#### Example input

```json
{
    "advertisers": ["nike.com"],
    "region": "anywhere",
    "format": "any",
    "maxAdsPerAdvertiser": 10,
    "includeCreativeDetails": true,
    "includeRegions": false,
    "proxyConfiguration": { "useApifyProxy": true }
}
```

Filters work together. This returns video ads shown in Germany during the last 60 days:

```json
{
    "advertisers": ["adidas.com"],
    "region": "DE",
    "format": "video",
    "startDate": "60 days",
    "maxAdsPerAdvertiser": 50
}
```

#### Example output

A video ad, shortened, from a real run:

```json
{
    "input": "nike.com",
    "advertiserId": "AR14612997888104464385",
    "advertiserName": "NIKE GLOBAL TRADING B.V. SINGAPORE BRANCH",
    "domain": "nike.com",
    "creativeId": "CR11347522441795600385",
    "format": "video",
    "firstShown": "2026-10-20T12:15:04.000Z",
    "lastShown": "2026-11-02T02:13:54.000Z",
    "daysShown": 13,
    "regions": null,
    "headline": "Zero Pressure",
    "description": "Designed for ultimate lockdown with an innovative mid-foot strap. Now available.",
    "destinationUrl": "https://www.nike.com/ph/w/jayson-tatum-shoes-4t66izy7ok",
    "displayUrl": "nike.com",
    "videoUrl": "https://www.youtube.com/watch?v=Flvk9kZ1Sa0",
    "videoThumbnailUrl": "https://i3.ytimg.com/vi/Flvk9kZ1Sa0/hqdefault.jpg",
    "videoDuration": "0:12",
    "channelName": "Nike",
    "creativeUrl": "https://adstransparency.google.com/advertiser/AR14612997888104464385/creative/CR11347522441795600385?region=anywhere",
    "scrapedAt": "2026-11-02T02:32:17.466Z"
}
```

A text ad from the same run:

```json
{
    "input": "nike.com",
    "advertiserId": "AR16735076323512287233",
    "advertiserName": "Nike, Inc.",
    "domain": "nike.com",
    "creativeId": "CR18059270850321842177",
    "format": "text",
    "firstShown": "2023-11-16T21:52:24.000Z",
    "lastShown": "2026-11-02T02:15:42.000Z",
    "daysShown": 914,
    "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/2576477964533453194",
    "imageWidth": 348,
    "imageHeight": 252,
    "creativeUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR18059270850321842177?region=anywhere"
}
```

### How much does it cost?

You pay per ad in the dataset: **$0.0018 per ad** ($1.80 per 1,000 ads), plus a **$0.0005 start fee** per run.

| Run | Cost |
|---|---|
| 10 ads | about $0.0185 |
| 1,000 ads | about $1.80 |
| 10,000 ads | about $18 |

Inputs that have no ads, inputs that fail, and duplicates (the same ad found through two of your entries) add nothing to the dataset and are not charged.

### Use cases

- Watch which ads a competitor runs on Google Search, Display and YouTube, and how long each one has been live.
- Collect the headlines, descriptions and landing pages of competitor ads for a swipe file.
- Check which countries a rival advertises in by running the same domain with different regions.
- Find every advertiser account that sends traffic to a domain, including agencies.
- Track new ads over time by running on a schedule with a recent start date.

### FAQ

**Do I need a Google account or an API key?** No. The Actor reads the public Transparency Center.

**Why do text ads have no headline?** Google serves text ads in the Transparency Center only as a picture. The Actor gives you that picture in `imageUrl`. It does not run text recognition on it.

**Do image and video ads always have a headline and a video link?** No. The extra fields come from Google's own ad preview and depend on the ad type. In a test run with 40 non-text ads, 33 had a headline or a video link. Shopping ads give the product title and picture; app install ads often give only a store link. Rows are still returned, with `previewUrl` and `creativeUrl`.

**How far back do date filters go?** The filter returns what Google returns. In testing, date ranges in early 2025 and in 2022 returned no ads even for advertisers whose ads had been running since 2022, so plan on about the last year. If you set only one of the two dates, the other is filled in (today, or 1 January 2020).

**How many ads can one run return?** There is no limit set by the Actor. I tested one run of 1,200 ads across two inputs (about 2 minutes, 92 MB of memory). Google reports roughly 700,000 ads for a very large advertiser such as hotels.com. I did not test paging that deep.

**Why is the number of ads different from what the website shows?** Google rotates and retires ads continuously, and a domain search also depends on how Google matched the ad to the site. Each result is a snapshot of the moment you run it.

**What about Google blocking?** Google answers with a captcha page when one IP asks too fast. The Actor spaces its requests, and on a block it waits, switches to a new proxy IP and retries up to 8 times. By default it uses Apify datacenter proxy for this. If an input still fails, the run goes on with the others, and the failure is listed in `SUMMARY`. If every input fails, the run is marked as failed.

**What does the regions option cost in time?** It adds one request per ad, spaced out, about 2 seconds each. Leave it off for large runs.

**Can I search by advertiser name?** Not directly. Use the advertiser's website domain, or find the advertiser ID in the URL of its page on adstransparency.google.com.

### Other Actors by this developer

- [Website Tech Stack Detector](https://apify.com/fernandosord/website-tech-stack-detector): see which tools a competitor's site runs.
- [Domain Profile: WHOIS and DNS](https://apify.com/fernandosord/domain-profile-whois-dns): registration and DNS details for a domain.
- [SEO Site Audit](https://apify.com/fernandosord/seo-site-audit): audit the landing pages the ads point to.
- [Google Trends API](https://apify.com/fernandosord/google-trends-reliable): check how interest in a brand or keyword moves.
- [Shopify Products Scraper](https://apify.com/fernandosord/shopify-products-scraper): pull the product catalogue of a store that advertises.

# Actor input Schema

## `advertisers` (type: `array`):

Any mix of: a domain (nike.com), an Ads Transparency Center advertiser URL (https://adstransparency.google.com/advertiser/AR16735076323512287233) or an advertiser ID (AR16735076323512287233). A domain returns every ad that points to that website, whoever paid for it. An advertiser ID or URL returns the ads of that one advertiser account.

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

Only ads that were shown in this country. Leave on Anywhere to get ads from all countries.

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

Text ads are returned as the image Google shows for them. Image covers display and responsive ads. Video ads come with the YouTube link.

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

Optional. Only ads that were shown on or after this date. Use a date (2026-01-31) or a relative period (30 days, 3 months). Google keeps roughly the last year of data for date filters.

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

Optional. Only ads that were shown on or before this date. Same formats as Shown from. If you set only one of the two dates, the other one is filled in for you (today, or 1 January 2020).

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

The Actor stops after this many ads for each domain, advertiser URL or advertiser ID. Newest first. Every ad in the dataset is billed, so this is also your cost cap per input.

## `includeCreativeDetails` (type: `boolean`):

For image and video ads, opens Google's ad preview to read the headline, description, call to action, landing page URL, image and the YouTube link of video ads. Costs one extra request per ad and makes the run slower. Turn off for a fast list of ads with dates only.

## `includeRegions` (type: `boolean`):

Adds the list of country codes per ad. Needs one extra request to Google per ad, spaced out to avoid blocks, so large runs get much slower. Off by default.

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

Google blocks an IP address that asks too fast. Apify datacenter proxy rotates the address when that happens. Keep it on unless you have a reason not to.

## Actor input object example

```json
{
  "advertisers": [
    "nike.com"
  ],
  "region": "anywhere",
  "format": "any",
  "maxAdsPerAdvertiser": 10,
  "includeCreativeDetails": true,
  "includeRegions": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One item per ad creative, newest first for each input.

# 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 = {
    "advertisers": [
        "nike.com"
    ],
    "region": "anywhere",
    "format": "any",
    "maxAdsPerAdvertiser": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("fernandosord/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 = {
    "advertisers": ["nike.com"],
    "region": "anywhere",
    "format": "any",
    "maxAdsPerAdvertiser": 10,
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

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