# Google Ads Transparency Scraper (`coregent/google-ads-transparency-scraper`) Actor

Scrape Google Ads Transparency Center ads by advertiser, domain or ad URL: format, first and last shown, image or preview, with optional regions, ad text and advertiser details. Region, format and date filters. No login, no proxy, no start fee.

- **URL**: https://apify.com/coregent/google-ads-transparency-scraper.md
- **Developed by:** [Delowar Munna](https://apify.com/coregent) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

## Google Ads Transparency Scraper

![Google Ads Transparency Scraper](https://raw.githubusercontent.com/coregentdevspace/google-ads-transparency-scraper-assets/main/thumbnail-google-ads-transparency-scraper.png)

Scrape public ads from **Google's Ads Transparency Center** by **advertiser, domain or ad URL**, all into one dataset
with one schema. Every ad row has the advertiser, the ad format (text, image or video), the website it points to, when
it was first and last shown, how many days it ran, and the ad itself as an image or a preview link.

Filter by **region**, **format** and **date range**. Optional extras, each off by default and charged only when you
turn it on:

- **Ad details**: the countries each ad ran in, with first and last shown dates per country.
- **Ad text**: for text ads, the headline, description and display URL, plus sitelinks or store locations, where
  Google provides the ad's text. Google shows most text ads only as an image, so this covers some text ads, not all;
  you pay only for ads whose text was found.
- **Advertiser details**: legal name, country and verification.

No Google account, login, cookies, browser or proxy needed, and **no start fee**: you pay only for data delivered.

### What you can scrape

| Input | Example | What you get |
|---|---|---|
| **Advertisers** | `Nike, Inc.`, `AR16735076323512287233`, or `https://adstransparency.google.com/advertiser/AR…` | That advertiser's ads |
| **Domains** | `nike.com` or `https://www.nike.com/` | Every ad that points to that website, from any advertiser |
| **Ad URLs** | `https://adstransparency.google.com/advertiser/AR…/creative/CR…` | One row per ad, always with its ad details |

Mix them freely in one run. An ad found by several sources is delivered (and charged) once. One run takes up to 100
advertisers, 100 domains and 1,000 ad URLs; split bigger lists across runs.

**Advertiser names:** Google lists many advertisers with similar names (searching "nike" returns a one-ad "Nike"
account in Kenya before Nike, Inc.). A name is matched to the advertiser **with the most ads whose name contains
it**, and the log and run summary say which one was used. For an exact match, give the advertiser ID (the `AR…` in
its Transparency Center URL) or the domain.

### How many results

**Max ads (whole run)** is the total for the run, split evenly across your sources unless you set **Max ads per
source**.

Run it with no input and it does a short demo: 10 ads for `nike.com`.

### Input examples

**Image ads for nike.com shown in the UK**

```json
{
    "domains": ["nike.com"],
    "maxAds": 100,
    "region": "GB",
    "format": "image"
}
```

**An advertiser's ads with their text**

```json
{
    "advertisers": ["AR16735076323512287233"],
    "maxAds": 50,
    "includeAdText": true
}
```

**Where specific ads ran, with the advertiser's details**

```json
{
    "adUrls": ["https://adstransparency.google.com/advertiser/<AR-id>/creative/<CR-id>"],
    "includeAdvertiserDetails": true
}
```

**An advertiser and a domain, every extra on** (the input behind the sample output below)

```json
{
    "advertisers": ["AR16735076323512287233"],
    "domains": ["booking.com"],
    "maxAds": 20,
    "includeAdDetails": true,
    "includeAdText": true,
    "includeAdvertiserDetails": true
}
```

**Ads shown this year, every extra on**

```json
{
    "domains": ["nike.com"],
    "maxAds": 20,
    "shownFrom": "2026-01-01",
    "includeAdDetails": true,
    "includeAdText": true,
    "includeAdvertiserDetails": true
}
```

### Output

One row per ad. The run's output has four tabs:

- **Ads**: one row per ad, with its image.
- **Ad text**: headline, description and display URL (with **Include ad text** on).
- **Ad regions**: one row per ad and country it ran in (with **Include ad details** on, and for ad URLs).
- **Advertisers**: the advertiser columns (with **Include advertiser details** on).

#### All fields

![All fields](https://raw.githubusercontent.com/coregentdevspace/google-ads-transparency-scraper-assets/main/google-ads-transparency-scraper-output-all-fields-table-view.png)

#### Sample ad row

One row from the run above: a Nike, Inc. text ad with every extra on. The preview URL is shortened here; the real
output has it in full.

```json
{
    "adId": "CR05391377373272735745",
    "advertiserId": "AR16735076323512287233",
    "advertiserName": "Nike, Inc.",
    "adUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR05391377373272735745",
    "format": "text",
    "domain": null,
    "firstShownAt": "2023-11-16T22:18:40.000Z",
    "lastShownAt": "2026-11-07T01:48:51.000Z",
    "daysShown": 920,
    "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/7873886143592880939",
    "previewUrl": "https://displayads-formats.googleusercontent.com/ads/preview/content.js?client=ads-integrity-transparency&…",
    "headline": "Nike® Official Site",
    "description": "Built on defiance, tradition, and a legacy larger than game. Shop Nike® Jordan shoes.",
    "displayUrl": "nike.com",
    "adText": {
        "headlines": [
            "Nike® Official Site"
        ],
        "descriptions": [
            "Built on defiance, tradition, and a legacy larger than game. Shop Nike® Jordan shoes."
        ],
        "displayUrl": "nike.com",
        "sitelinks": [],
        "locations": [
            {
                "name": "Nike Factory Store - Aurora Farms",
                "street": "549 South Chillicothe Road #321",
                "city": "Aurora",
                "postalCode": "44202",
                "country": "US"
            }
        ]
    },
    "regions": [
        {
            "country": "US",
            "firstShownDate": null,
            "lastShownDate": "2026-11-06"
        }
    ],
    "advertiser": {
        "id": "AR16735076323512287233",
        "name": "Nike, Inc.",
        "legalName": "Nike, Inc.",
        "country": "US",
        "verified": true
    },
    "source": {
        "type": "advertiser",
        "value": "AR16735076323512287233",
        "position": 4,
        "region": "anywhere"
    },
    "scrapedAt": "2026-11-07T02:38:53.679Z"
}
```

In the **Ad regions** tab, each entry of `regions` becomes its own row next to the ad's advertiser and link. A
booking.com ad in the same run ran in 13 countries.

#### Ad fields

| Field | Description |
|---|---|
| `adId`, `advertiserId`, `advertiserName` | The ad (`CR…`) and its advertiser (`AR…`) |
| `adUrl` | The ad's page on the Transparency Center |
| `format` | `text`, `image` or `video` |
| `domain` | The website the ad points to. Google gives it on domain searches only, so it is empty on rows from advertisers and ad URLs |
| `firstShownAt`, `lastShownAt` | When the ad was first and last shown |
| `daysShown` | How many days it was shown (not on ads given by URL) |
| `imageUrl` | An image of the ad, when Google shows one (text ads often come as a rendered image too) |
| `previewUrl` | Google's preview of the ad, when Google shows one instead of an image |
| `headline`, `description`, `displayUrl` | Text ads, with **Include ad text** |
| `adText` | With **Include ad text**: all `headlines` and `descriptions`, `displayUrl`, `sitelinks`, store `locations` |
| `regions` | With ad details: `[{ country, firstShownDate, lastShownDate }]` (two-letter country codes; Google often gives only the last-shown date per country) |
| `advertiser` | With advertiser details: `{ id, name, legalName, country, verified }` |
| `source` | Which input found the ad: `{ type, value, position, region }` |

Fields an option didn't fill are `null`, never guessed.

#### Inputs that couldn't be scraped

They are never dataset rows: each is logged, and listed with its reason in the `RUN_SUMMARY` record in the run's
key-value store (`errors`), along with counts, the advertiser chosen for each name, and request statistics. They are
never charged.

### Pricing

Pay per event: you pay for each **ad** delivered, plus each extra you turn on: **ad details** per ad (always for ads
given by URL), **ad text** per text ad whose text was decoded, and **advertiser details** once per advertiser per
run. Inputs that couldn't be scraped and duplicates are free, and there is **no start fee**. See the **Pricing** tab
for current rates. This README deliberately doesn't quote figures.

If you set a spending limit on a run, the Actor stops when it is reached and keeps everything already paid for.

#### 🚦 Proxy policy

**No proxy is needed** for Google Ads Transparency searches at this Actor's conservative request rate. If Google
starts limiting a run, the Actor switches to the **Apify Datacenter** proxy by itself. You can also choose Apify
Datacenter yourself.

**Apify Residential proxy is not supported.** The Actor will fail at startup if `apifyProxyGroups` includes
`RESIDENTIAL`. Reason: in pay-per-event Actors, residential bandwidth is billed per GB to the developer, not the run
user, so a single bandwidth-heavy run could exceed the per-result event revenue.

If you genuinely need residential routing, supply your own residential provider via the proxy editor's **Custom proxy
URLs** field. That traffic goes through your provider, not Apify, and is unaffected:

```
http://user:pass@proxy.iproyal.com:12321
http://user:pass@proxy.brightdata.com:22225
http://user:pass@proxy.oxylabs.io:7777
```

### FAQ

**Why is the total a range?**
Google reports how many ads a source has as a range (for example 50,000–60,000), not an exact number. It's in the
run summary's `sourceReports`.

**What is `{KeyWord:…}` in ad text?**
Keyword insertion: the ad shows the searcher's keyword in that place. The text after the colon is what everyone else
sees.

**Why do most text ads have no text?**
The text is decoded from Google's ad preview. Google shows most text ads only as an image of the ad: in testing,
89–100% of an advertiser's text ads, depending on the advertiser. For those, the text stays `null` and you aren't
charged for it; the image (`imageUrl`) still shows the ad. The Actor doesn't read text out of images.

**Why does a headline say "<dynamically generated based on landing page content>"?**
That's a Dynamic Search Ad: Google writes the headline from the advertiser's landing page for each search, and the
Transparency Center shows this placeholder instead. The Actor returns Google's text as it is.

**Can I download the videos?**
No. Video ads come with their preview link. The Actor doesn't download creatives.

**Do the image links last?**
They are Google-hosted and have stayed available in testing, but Google can change them. Save what you need.

### Related Actors

Researching a competitor's ads across platforms? Many advertisers run on all three.

- [Facebook Ads Library Scraper](https://apify.com/coregent/facebook-ads-library-scraper): ads from Meta's Ad
  Library (Facebook and Instagram) by keyword, advertiser Page or Ad Library URL, with country, status and date
  filters.
- [TikTok Ads Library Creative Center Scraper](https://apify.com/coregent/tiktok-ads-library-creative-center-scraper):
  TikTok's Ads Library (Europe, with DSA targeting and reach) and Creative Center top ads, with landing pages.

### Data and privacy

This Actor collects only what Google's Ads Transparency Center shows publicly, which Google publishes so the public
can see who advertises. Most advertisers are businesses, but some are individuals, so advertiser names can be personal
data. You are responsible for having a lawful basis to process them and for following the laws that apply to you,
including the GDPR where relevant, and Google's terms. Ad creatives belong to their advertisers.

This Actor is not affiliated with, endorsed by or sponsored by Google.

# Actor input Schema

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

Advertiser names (e.g. Nike, Inc.), advertiser IDs (AR followed by digits) or Transparency Center advertiser URLs (https://adstransparency.google.com/advertiser/AR…). A name is matched to the advertiser with the most ads whose name contains it; an ID or URL is exact. Each advertiser is one source. If you give no advertiser, domain or ad URL at all, the Actor runs a short demo for nike.com. Up to 100 per run.

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

Websites the ads point to (e.g. nike.com or https://www.nike.com/). Returns ads from every advertiser that advertises that domain. Each domain is one source. Up to 100 per run.

## `adUrls` (type: `array`):

Transparency Center ad URLs (https://adstransparency.google.com/advertiser/AR…/creative/CR…). Each ad comes with its ad details (regions). Up to 1,000 per run.

## `maxAds` (type: `integer`):

The total number of ad rows for the whole run, across all sources. Split evenly across sources unless you set a per-source limit.

## `maxAdsPerSource` (type: `integer`):

Optional. The most ads from any one advertiser or domain. Leave empty to split the run's limit evenly across sources.

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

Only ads shown in this country. "Anywhere" returns ads from every region.

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

Only ads of this format.

## `shownFrom` (type: `string`):

Optional. Only ads shown on or after this date (YYYY-MM-DD, or e.g. "30 days").

## `shownTo` (type: `string`):

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

## `includeAdDetails` (type: `boolean`):

Add the countries each ad ran in, with first and last shown dates per country. One extra request per ad, charged per ad. Ads given by URL always include them.

## `includeAdText` (type: `boolean`):

For text ads: the headline, description, display URL, and sitelinks or store locations, decoded from the ad's preview where Google provides one. Google shows most text ads only as an image, so many text ads get no text. Charged only per text ad whose text was decoded.

## `includeAdvertiserDetails` (type: `boolean`):

Add each advertiser's legal name, country and verification. Fetched and charged once per advertiser per run.

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

Optional. No proxy is needed: the Actor reads Google's public Transparency Center directly, and switches to the Apify datacenter proxy by itself if Google starts limiting requests. Apify residential proxy is not supported (the run fails at start); use your own provider via Custom proxy URLs instead.

## Actor input object example

```json
{
  "domains": [
    "nike.com"
  ],
  "maxAds": 10,
  "region": "anywhere",
  "format": "any",
  "includeAdDetails": false,
  "includeAdText": false,
  "includeAdvertiserDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `regions` (type: `string`):

No description

## `runSummary` (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 = {
    "domains": [
        "nike.com"
    ],
    "maxAds": 10,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("coregent/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 = {
    "domains": ["nike.com"],
    "maxAds": 10,
    "proxyConfiguration": { "useApifyProxy": False },
}

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

```

## MCP server setup

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