# Google Ads Transparency Scraper - Competitor Ads, No Login (`benthepythondev/google-ads-transparency-scraper`) Actor

Returns the ads any advertiser runs on Google Search, YouTube, Shopping, Maps and Play, from Google's Ads Transparency Center: format, first and last day shown, picture or YouTube link, ad text where Google publishes it, regions with impression ranges. By domain, brand or advertiser id. No login.

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

## Pricing

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

Returns the ads any advertiser runs on Google Search, YouTube, Shopping, Maps and Play, read from Google's [Ads Transparency Center](https://adstransparency.google.com/) without a login, a cookie or a browser. Enter a domain such as `nike.com`, a brand name or an advertiser id and get one row per ad: advertiser, format, first and last day shown, number of days shown, the picture or the preview link, and the link to the ad. On request each row also carries the regions the ad ran in, Google's impression ranges, every variation, and the ad's text or YouTube link where Google publishes them.

**Price:** $1.50 per 1,000 ads on the Apify Free plan, down to $1.20 from the Gold plan up. Details add $2.00 per 1,000 (down to $1.60). An entry without ads costs nothing. Export to JSON, CSV or Excel, run on a schedule, call via API, or connect to Make, Zapier or n8n.

### 🔎 What is the Google Ads Transparency Scraper?

Google lists the ads of every verified advertiser in its Ads Transparency Center. The site shows them forty at a time in a grid and has no export. This Actor makes the same requests the site's own page makes and returns the result as a table: 5,000 ads in about 35 seconds.

#### What data does it extract?

- **Advertiser:** name as Google verified it, advertiser id (`AR…`), the domain the ad links to
- **Ad:** id (`CR…`), format (text, image or video), first and last day shown, number of days shown
- **Creative:** the picture Google stores for the ad, or the link of the script that draws it
- **Link:** the ad's page in the Transparency Center
- **With details:** each region with first and last day shown, impression ranges overall, per region and per platform (where Google publishes them), all variations, and for ads drawn by a script the headline, description, display address, merchant name or YouTube link

#### How it reads the site

| | This Actor | A scraper that drives a browser |
|---|---|---|
| Memory | 512 MB | 2 to 4 GB |
| How it reads | The site's own data requests, 100 ads each | Scrolls the grid and reads the page |
| Region, format, platform and date filters | Applied by Google in the request | Often applied afterwards, on what was loaded |
| Text of an ad | Taken from Google's preview data where it exists; never guessed | Picture only, or text recognition on the picture |
| A search without ads | No rows, no charge, and the status message says so | Varies |

### ⬇️ Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `queries` | array | | Domains, brand names, advertiser ids or links copied from the Transparency Center. An empty input reads the sample `nike.com` |
| `maxResults` | integer | 20 | Ads to save per domain or advertiser, up to 20,000 |
| `region` | string | empty | Two-letter country code (US, DE, GB): only ads shown there. Empty means anywhere |
| `adFormat` | string | `ALL` | `TEXT`, `IMAGE` or `VIDEO` |
| `platforms` | array | empty | `SEARCH`, `YOUTUBE`, `SHOPPING`, `MAPS`, `PLAY` |
| `startDate`, `endDate` | string | empty | Only ads shown in this period (YYYY-MM-DD) |
| `includeDetails` | boolean | false | Adds regions, impression ranges, variations, ad text and YouTube link. Second charge event |
| `maxAdvertisersPerQuery` | integer | 3 | For a brand name: how many advertiser accounts to read, those with the most ads first |
| `onlyNewAds` | boolean | false | Skip every ad an earlier run with the same monitor name delivered |
| `monitorId` | string | empty | Name of that memory |

A **domain** is the most reliable entry: it returns every ad that links to it, whichever account runs it. A **brand name** is matched through Google's own suggestions, and large brands run one account per country or agency, so a name can miss accounts a domain would catch.

Input names of other Ads Transparency Actors are read as well (`searchQuery`, `domains`, `advertiserIds`, `startUrls`, `maxAdsPerSearch`, `resultsLimit`, `dateFrom`, `dateTo`, `platform`, `detail`), so a saved input keeps working.

#### Example input

Every ad of one domain in Germany since September, with details:

```json
{
  "queries": ["zalando.de"],
  "maxResults": 500,
  "region": "DE",
  "startDate": "2026-09-01",
  "includeDetails": true
}
```

Video ads of three competitors on YouTube:

```json
{
  "queries": ["hellofresh.com", "gousto.co.uk", "marleyspoon.com"],
  "maxResults": 200,
  "adFormat": "VIDEO",
  "platforms": ["YOUTUBE"]
}
```

A brand by name, one advertiser by id and one single ad by its link:

```json
{
  "queries": [
    "adidas",
    "AR14017378248766259201",
    "https://adstransparency.google.com/advertiser/AR11154049584043393025/creative/CR18332474338495692801"
  ],
  "maxResults": 100
}
```

### ⬆️ Output

One row per ad. A row from the default run:

```json
{
  "creativeId": "CR02220147468081823745",
  "advertiserId": "AR18378488041124659201",
  "advertiserName": "Nike Retail BV",
  "domain": "nike.com",
  "format": "TEXT",
  "firstShown": "2025-09-19",
  "lastShown": "2026-10-03",
  "shownForDays": 380,
  "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/13470210608396104477",
  "previewUrl": null,
  "adUrl": "https://adstransparency.google.com/advertiser/AR18378488041124659201/creative/CR02220147468081823745",
  "query": "nike.com",
  "region": "ANYWHERE",
  "position": 1,
  "hasDetails": false,
  "scrapedAt": "2026-10-03T15:20:57.153356+00:00"
}
```

With `includeDetails`, the same columns plus the ad's own record. A video ad found for the brand name "adidas" (two of its 4 regions and one of its 5 variations shown, preview links shortened):

```json
{
  "creativeId": "CR00231634406681346049",
  "advertiserId": "AR14017378248766259201",
  "advertiserName": "Adidas America, Inc",
  "domain": null,
  "format": "VIDEO",
  "firstShown": "2024-11-07",
  "lastShown": "2026-04-01",
  "shownForDays": 511,
  "imageUrl": null,
  "previewUrl": "https://displayads-formats.googleusercontent.com/ads/preview/content.js?client=ads-integrity-transparency&creativeId=720473943737…",
  "adUrl": "https://adstransparency.google.com/advertiser/AR14017378248766259201/creative/CR00231634406681346049",
  "query": "adidas",
  "region": "DE",
  "position": 16,
  "hasDetails": true,
  "youtubeUrl": "https://www.youtube.com/watch?v=EEHNZlxanwY",
  "regions": [
    {
      "region": "NL",
      "firstShown": "2024-11-12",
      "lastShown": "2025-12-01",
      "impressionsMin": null,
      "impressionsMax": 1000,
      "platforms": [
        {"platform": "MAPS", "impressionsMin": null, "impressionsMax": 1000},
        {"platform": "SEARCH", "impressionsMin": null, "impressionsMax": 1000}
      ]
    },
    {
      "region": "US",
      "firstShown": null,
      "lastShown": "2026-04-01",
      "impressionsMin": null,
      "impressionsMax": null,
      "platforms": []
    }
  ],
  "regionCount": 4,
  "impressionsMin": null,
  "impressionsMax": 1000,
  "variations": [
    {"previewUrl": "https://displayads-formats.googleusercontent.com/ads/preview/content.js?client=ads-integrity-transparency&creativeId=720473943737…"}
  ],
  "variationCount": 5,
  "scrapedAt": "2026-10-03T15:22:41.701692+00:00"
}
```

Text fields of a search ad Google draws with a script, from a Booking.com run in the Netherlands:

```json
{
  "headline": "Al Maha Desert Resort Dubai",
  "description": "Kies Uit Een Groot Aantal Verschillende Accommodaties Die Booking.com Aanbiedt Hotels, Huizen, En Alles Ertussenin. Bespaar 10% Met Genius. Geweldige Beschikbaarheid. Onmiddellijke Bevestiging.",
  "displayUrl": "www.booking.com/",
  "adText": [
    "Al Maha Desert Resort Dubai",
    "Kies Uit Een Groot Aantal Verschillende Accommodaties Die Booking.com Aanbiedt Hotels, Huizen, En Alles Ertussenin. Bespaar 10% Met Genius. Geweldige Beschikbaarheid. Onmiddellijke Bevestiging.",
    "Booking.com",
    "Boek Je Vakantie",
    "Boek Voor Morgen",
    "Boek Voor Vanavond",
    "Geweldige Prijzen"
  ]
}
```

`impressionsMin` empty with `impressionsMax` 1000 is Google's lowest range, "0 to 1,000". An empty `impressionsMax` with a filled minimum means "more than". The run also writes a `SUMMARY` record with the entries that returned nothing and the reason a run stopped.

### 💰 What a run costs

| Apify plan | Per 1,000 ads | Per 1,000 ad details (added) |
|---|---|---|
| Free | $1.50 | $2.00 |
| Bronze | $1.40 | $1.90 |
| Silver | $1.30 | $1.80 |
| Gold, Platinum, Diamond | $1.20 | $1.60 |

Apify's standard start event ($0.00005) is the only other charge. Not charged: an entry that has no ads, a brand name without an advertiser, an ad already delivered in only-new mode, and the same ad found a second time in one run. A single ad opened by its link always comes with its details and is charged as one ad plus one detail. Set the run's maximum charge and the Actor stops at it with the rows it has saved.

### ⏱️ Measured on Apify (October 3, 2026)

| Run | Ads | Time |
|---|---|---|
| Default input (`nike.com`, 20 ads) | 20 | 4.6 s |
| `zalando.de`, no filter | 5,000 | 35 s |
| `nike.com`, no filter | 5,398 | 37 s |
| `booking.com` in the Netherlands, with details | 300 | 36 s |
| Only-new watch on `hellofresh.com` (US), second run | 0 new of 940 | 5.5 s |

All of them at 512 MB. An aborted and resumed run of 4,000 ads saved no ad twice.

### 🔔 Watching for new ads

Turn on `onlyNewAds`, give the watch a `monitorId` and put the run on a schedule. The first run delivers what is there (set `maxResults` high enough to take in the existing ads). From the second run on, the Actor reads the ads shown since the last run and delivers only those it has not delivered to you before; a run without news ends with zero rows and "Nothing new". The memory is a key-value store named `google-ads-transparency-monitor` in your own account; delete a record there to start a watch over.

### 🤖 For AI agents

Smallest useful call:

```json
{"queries": ["nike.com"], "maxResults": 50, "region": "US"}
```

Each row is one ad with `advertiserName`, `format`, `firstShown`, `lastShown`, `shownForDays`, `imageUrl` or `previewUrl`, and `adUrl`. Add `"includeDetails": true` for `regions`, impression ranges, `variations`, `headline`, `adText` and `youtubeUrl`. `queries` takes several entries at once. An entry without ads returns no rows; the status message and the `SUMMARY` record name it. No credentials are needed.

### 💡 Use cases

- 🎯 **Competitor research:** every ad a competitor runs in a country, with how long each has been running. Long-running ads are the ones that pay.
- 🎬 **Creative research:** the YouTube links of a category's video ads, ready for a transcript or a view count.
- 🔔 **Launch monitoring:** a daily watch that reports only the ads that appeared since yesterday.
- 🇪🇺 **Reach in the EU:** impression ranges per country and platform for ads shown in the European Union.

### ⚠️ Limits, stated plainly

- **Ad text.** Google stores most text ads as a picture. For those you get the picture, not the words. Text fields are filled only for ads Google draws with a script: in the Booking.com test above that was 2 of 300 text ads. Shopping ads have their product title and merchant.
- **Video links.** In one test 26 of 53 video ads carried their YouTube link. The others are drawn in a way that does not name the video.
- **No landing page and no spend.** Google does not publish them here.
- **Impressions** are ranges and exist only for regions where Google publishes them, mainly the EU.
- **Totals** Google reports are ranges ("100,000 to 200,000 ads"). When a search stops at your limit, the status message quotes that range.
- **20,000 ads per entry** and run is the upper limit. Use dates, a region or a format to split a larger advertiser.
- **One region per run.**
- **Google limits how often one address may ask.** The Actor changes addresses by itself. If Google stops answering in the middle of a search, the rows saved so far stay and the status message says which search was cut.

### ❓ FAQ

**Do I need a Google account, cookies or an API key?** No. The Transparency Center is public and the Actor reads it as a visitor.

**How do I find an advertiser id?** You do not need one: enter the domain. If you want it, it is the `advertiserId` column of any row, or the `AR…` part of an advertiser page's link.

**Why do I get fewer ads than Google's count?** `maxResults` is 20 by default. Raise it. Google's own count is a range, and with filters it becomes smaller.

**Why is `domain` empty in some rows?** Google names the domain only in a domain search. Rows found through an advertiser id or a brand name have the advertiser, not the domain.

**Can it return the text of every ad?** No, see the limits above. Where the text is missing you still get the picture of the ad.

**Does it cover political ads?** Ads of verified election advertisers appear like any other ad. The separate political report with spend is not part of this Actor.

**Can I run it every day?** Yes. Use a schedule with `onlyNewAds` so you pay only for ads you have not received.

**How do I call it from code?** With the Apify API or the Python and JavaScript clients; every run returns a dataset you can fetch as JSON or CSV. It also works as a tool through Apify's MCP server.

**What changed for me if I come from another Ads Transparency Actor?** Your input names are accepted. Output columns use the same names where they mean the same (`creativeId`, `advertiserId`, `advertiserName`, `firstShown`, `lastShown`, `shownForDays`, `adUrl`, `previewUrl`); regions are in `regions` with ISO country codes.

**Is it legal?** The Actor reads what Google publishes for everyone under its transparency rules. Advertiser names can be names of persons; GDPR, CCPA and similar rules apply to how you store and use them, and Google's terms apply to you as well.

### 🔗 You might also like

- [Meta Ad Library Scraper](https://apify.com/benthepythondev/meta-ad-library-scraper): the same question for Facebook and Instagram ads
- [LinkedIn Ad Library Scraper](https://apify.com/benthepythondev/linkedin-ad-library-scraper): and for LinkedIn ads, with landing pages and EU targeting
- [YouTube Video Metadata Scraper](https://apify.com/benthepythondev/youtube-video-metadata-scraper): exact views, likes and date for the YouTube links this Actor returns
- [YouTube Transcript Scraper](https://apify.com/benthepythondev/youtube-transcript-scraper): what a video ad says
- [YouTube Comments Scraper](https://apify.com/benthepythondev/youtube-comments-scraper): how viewers react to it

**Keywords:** google ads transparency center scraper, google ads scraper, google ad library, competitor ads, ad intelligence, google ads api alternative, ads transparency export, youtube ads scraper, google shopping ads, search ads research, ad creative research, ad monitoring, advertiser lookup, DSA ad repository, impressions by country, competitor ad monitoring, marketing research, ppc competitor analysis

# Actor input Schema

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

One entry per search. A domain (nike.com) returns every ad that links to it and is the most reliable choice. A brand name (Nike) is matched to the advertisers with the most ads. An advertiser id (AR16735076323512287233) or a link copied from adstransparency.google.com (advertiser page, single ad or domain search) works too.

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

Ads to save for each domain or advertiser. Google lists up to 100 ads per request; 1,000 ads take about five seconds.

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

Two-letter country code such as US, DE or GB: only ads shown in that country. Leave empty for ads shown anywhere.

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

Keep only text, image or video ads.

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

Keep only ads shown on these Google platforms. Leave empty for all.

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

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

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

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

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

Opens every ad's own record: the regions it ran in with first and last day, impression ranges where Google publishes them (EU), all variations, and the ad's text or YouTube link when Google draws the ad with a script. Charged as a second event per ad. A link to a single ad always returns its details.

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

A brand name can belong to several advertiser accounts (one per country or agency). This many of them are read, those with the most ads first. Not used for domains and ids.

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

For scheduled runs: skips every ad an earlier run with the same monitor name delivered, so you pay only for ads that are new to you. From the second run on, the ads shown since the last run are checked. The memory is a key-value store in your own account.

## `monitorId` (type: `string`):

Name of the memory used by the option above. Give each watch its own name; without a name the search itself (entries, region, format, platforms) is the name.

## Actor input object example

```json
{
  "queries": [
    "nike.com"
  ],
  "maxResults": 20,
  "region": "",
  "adFormat": "ALL",
  "includeDetails": false,
  "maxAdvertisersPerQuery": 3,
  "onlyNewAds": false
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "queries": [
        "nike.com"
    ]
};

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

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

```

## MCP server setup

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