# Google Ads Transparency Scraper 🔍 (competitor ad spy) (`tagadanar/ads-transparency-scraper`) Actor

Every ad a competitor runs on Google, YouTube, Shopping, Maps and Play: creative, format, first and last seen, days shown, and the verified legal entity paying. Search by brand, advertiser ID or landing domain. The ad-history slice a SpyFu or Adbeat seat sells, priced per ad.

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

## Pricing

from $1.40 / 1,000 ad creatives

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Google Ads Transparency Scraper 🔍

See every ad a competitor is currently running on Google, and how long each one
has been running.

Google publishes every ad it serves in the Ads Transparency Center, but the site
only lets you scroll one advertiser at a time and gives you nothing to export.
This actor turns that into a dataset: one row per ad creative, with the creative
image, the format, the first and last date it was seen, the number of days it
actually ran, and the verified legal entity paying for it. Search by brand name,
by advertiser ID, or by landing domain.

No API key, no Google Ads account, no login. One flat price per ad with platform
usage included, so what you see in the pricing box is what the run costs.

### What you get

One record per ad creative (`recordType: "ad"`):

| Field | What it is |
| --- | --- |
| `advertiserId` / `advertiserName` | Who is paying for the ad |
| `creativeId` | Google's ID for this creative |
| `adUrl` | Public Transparency Center page for the ad |
| `format` | `text` (search ads), `image` (display and Demand Gen) or `video` (YouTube) |
| `firstShown` / `lastShown` | ISO dates the creative was first and last seen |
| `approxDaysShown` | Days the creative actually ran, as Google counts them. It is not last minus first: a creative first seen 1,350 days ago reported 1,210 days shown |
| `landingDomain` | The site the ad points at (always filled in domain mode) |
| `imageUrl`, `imageWidth`, `imageHeight` | The archived creative image |
| `previewUrl` | Google's rendered preview of the ad, ready to embed in an iframe |
| `googleAdsCustomerId` | The advertiser's obfuscated Google Ads account ID |
| `googleCreativeId`, `googleAdGroupId` | The advertiser's own numeric IDs for the creative and its ad group |
| `variationCount` | How many different renderings this creative has (detail mode) |
| `regionsShown`, `regionCount` | Every country the ad ran in, with a last-seen date per country (detail mode) |

Plus one profile row per advertiser (`recordType: "advertiser"`):

| Field | What it is |
| --- | --- |
| `advertiserLegalName` | The legal entity Google verified before letting them advertise |
| `advertiserCountry` | Where that entity is registered |
| `identityVerified` | Whether Google completed advertiser identity verification |
| `advertiserUrl` | Public advertiser page |

#### Three things you will not find in the other Transparency Center scrapers

**Domain search.** Ask for `nike.com` and you get every advertiser buying ads
that land there, not just Nike itself. On a live check that returned Nike Inc.,
Nike Retail BV, Nike Global Trading Singapore, Nike Japan and a WPP media
agency. That is how you find out who else is bidding on your own brand.

**The Google Ads account ID.** Every ad carries the advertiser's obfuscated
customer ID, its numeric creative ID and its ad group ID, read straight out of
Google's own preview URL. Those are join keys: two advertiser records with the
same customer ID are the same Google Ads account.

**Per-country reach.** Turn on the detail option and each ad tells you every
country it ran in with a last-seen date for each, so you can see a campaign
being tested in one market before it rolls out.

### Who uses it

**Performance marketers and agencies.** Pull a competitor's whole ad library
before a pitch or a quarterly review. `approxDaysShown` is the honest signal for
which creatives are working: an ad nobody pauses after 300 days is an ad that
converts, and a burst of new creatives dated last week is a campaign launch.

**Brand protection.** Run your own domain weekly. Affiliates, resellers and
unauthorised partners bidding on your brand show up as separate advertisers
pointing at your site.

**Competitive intelligence and market research.** Filter by country to see which
markets a company is actually spending in, and by format to separate its search
spend from its YouTube spend.

**Ad creative research.** Filter to `image` or `video` and collect creative URLs
from everyone in a category at once.

### Input examples

Every competitor's ads in the US:

```json
{
  "advertisers": ["Nike", "Adidas", "Puma"],
  "region": "US",
  "maxResults": 500
}
```

Who else is buying ads that land on your site, worldwide:

```json
{
  "domains": ["stripe.com"],
  "region": "ANY",
  "maxResults": 1000
}
```

This quarter's YouTube campaigns only, with the country breakdown:

```json
{
  "advertisers": ["AR16735076323512287233"],
  "platform": "youtube",
  "shownAfter": "2026-07-01",
  "fetchCreativeDetails": true,
  "maxResults": 200
}
```

A brand that advertises through regional entities:

```json
{
  "advertisers": ["Booking.com"],
  "allMatchingAdvertisers": true,
  "region": "GB",
  "maxResults": 2000
}
```

### FAQ

**Do I need a Google Ads account or an API key?**
No. The Ads Transparency Center is public and this actor reads it directly.

**Can I get the ad's headline and description text?**
Not as text. Google archives text ads as a rendered picture of the ad rather
than as fields, so what you get is `imageUrl` (the picture) and `previewUrl`
(Google's live rendering). Nothing that reads the Transparency Center can give
you the headline as a string, including the tools that imply they can.

**Can I get the ad's click-through URL?**
Google does not publish the final URL, only the advertiser and, in domain mode,
the domain the ad lands on. `landingDomain` is as close as the source goes.

**Why do I get several advertisers for one brand name?**
Because the brand really does have several. "Nike" resolves to nine separate
verified advertisers, from Nike, Inc. with about 9,000 ads down to a personal
account with one. By default the actor picks the largest, which is almost always
the one you mean. Set `allMatchingAdvertisers` to true to get all of them.

**How many ads can I pull for one advertiser?**
As many as Google publishes. Large advertisers have thousands, so `maxResults`
is what keeps a run predictable. The log reports the size bracket Google shows
on the page ("about 8,000 to 9,000 ads") before it starts paging.

**How current is the data?**
Live. `lastShown` on an active ad is usually today's date.

**What does the country filter actually do?**
It restricts results to ads served in that country. An advertiser can have
thousands of ads in the US and a hundred in France. Leave it on "Any country"
to see everything at once.

**Does political-ad data come with it?**
Not in this version. The Transparency Center publishes extra spend and
impression ranges for election ads under a separate topic, which this actor does
not query yet.

**What if an advertiser is running nothing?**
The run finishes normally with the advertiser profile row and no ad rows, and
the log says so. You are only billed for what actually comes back.

### Related actors

- eBay Sold Listings Scraper, for what things actually sold for
- Capterra Reviews Scraper, for what a competitor's customers say
- Google Trends Scraper, for whether the category is growing at all

***

Keywords: google ads transparency center scraper, ads transparency api,
competitor ad research, google ads spy tool, ad creative scraper, competitor ad
library, google ads competitor analysis, youtube ads scraper, display ads
scraper, brand protection monitoring, advertiser lookup, ad intelligence.

# Actor input Schema

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

Brand names ("Nike"), Transparency Center advertiser IDs ("AR16735076323512287233") or advertiser page URLs. A brand name is resolved to the verified advertiser behind it before its ads are pulled.

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

Find every ad pointing at a website, across every advertiser buying it (the brand itself, its agencies, its resellers). One domain per line, e.g. nike.com.

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

Only ads shown in this country. Leave on "Any country" to see an advertiser’s worldwide activity.

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

Text ads are the search ads, image ads are display and Demand Gen, video ads are the YouTube ones.

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

Restrict to one Google surface.

## `shownAfter` (type: `string`):

YYYY-MM-DD. Only ads that ran on or after this date.

## `shownBefore` (type: `string`):

YYYY-MM-DD. Only ads that ran on or before this date.

## `maxResults` (type: `integer`):

Stop after this many ad creatives. Big advertisers run thousands of them, so this is what keeps a run predictable.

## `fetchCreativeDetails` (type: `boolean`):

Off by default. When on, each ad gets one extra lookup returning the full list of countries it ran in with a last-seen date per country, plus every creative variation. Billed only for ads that actually come back with details.

## `allMatchingAdvertisers` (type: `boolean`):

By default a brand name resolves to the single biggest advertiser using it. Turn this on to pull all of them, which is what you want for brands that advertise through regional entities or agencies.

## Actor input object example

```json
{
  "advertisers": [
    "Nike",
    "AR16735076323512287233"
  ],
  "domains": [
    "nike.com"
  ],
  "region": "US",
  "adFormat": "any",
  "platform": "any",
  "shownAfter": "2026-01-01",
  "shownBefore": "2026-08-01",
  "maxResults": 500,
  "fetchCreativeDetails": false,
  "allMatchingAdvertisers": false
}
```

# Actor output Schema

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

One item per ad creative, plus one profile row per advertiser, in the default dataset.

# 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"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tagadanar/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"] }

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

```

## MCP server setup

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