# Google Ads Transparency Center Scraper with Ad Copy (`sinolens/google-ads-transparency-scraper`) Actor

Scrape ads from the Google Ads Transparency Center by website, advertiser name or ID. Get the ad text (headlines, descriptions), YouTube links of video ads, landing pages, where and when each ad ran, and EU reach and audience data. No login.

- **URL**: https://apify.com/sinolens/google-ads-transparency-scraper.md
- **Developed by:** [SinoLens](https://apify.com/sinolens) (community)
- **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

Scrape the **Google Ads Transparency Center** (Google's ad library) and get every ad a company runs on Google Search, YouTube, Shopping, Maps and Play, **with the actual ad copy**: headlines, descriptions, display URLs, calls to action and landing pages. Search by website, advertiser name, advertiser ID or a Transparency Center link, filter by country, platform, format and date, and export the results as JSON, CSV or Excel, or through the API.

Google publishes most text ads only as a picture. This Actor **reads the text out of the picture**, so you get searchable, comparable ad copy instead of screenshots. Video ads come with their **YouTube link**, headline, description and button text. For ads shown in the EU you also get **how many times each ad was shown, by country and platform**, and **how its audience was chosen**.

No Google account, no cookies, no browser.

### What does this Google Ads Transparency scraper do?

- 🔎 **Find any advertiser's ads**: by website (`nike.com`), advertiser name (`Nike`), advertiser ID (`AR16735076323512287233`) or a link from adstransparency.google.com.
- ✍️ **Ad copy as text**: headline, description, display URL and business name of text ads, read from Google's preview or from the ad's picture.
- 🎬 **Video ads**: YouTube video ID and link, thumbnail, duration, channel, headline, long headline, description, call to action and landing page.
- 🛍️ **Shopping ads**: product title, price, merchant and product picture.
- 📅 **When and where**: first and last shown dates, days shown, and every country the ad ran in with its own first and last dates.
- 🇪🇺 **EU reach and targeting** (Digital Services Act data): times shown (ranges) in total, per country and per platform, and whether demographics, locations, contextual signals, customer lists or interests were used to pick the audience.
- 🏷️ **Google's topic** for the ad (Apparel, Finance, Travel & Tourism ...) and all of the ad's **variations**.
- 🏢 **Advertisers mode**: the advertisers behind a website, or every advertiser whose name contains a word, with country, verification status, legal name and number of ads.
- 🎛️ **Filters**: country, platform (Search, YouTube, Shopping, Maps, Play), format (text, image, video) and date range.
- 💸 **Pay per result**, nothing for duplicates, and the run stops at your maximum cost.

### Who uses Google Ads Transparency Center data?

- **Marketers and agencies**: see what competitors advertise, which messages they test, and which ads they keep running for months (a strong hint that an ad works).
- **Copywriters**: collect real headlines and descriptions from a whole category.
- **Brand protection**: find advertisers that use your brand or point ads to your domain.
- **Lead generation**: list the companies that advertise on Google in a niche.
- **Researchers and journalists**: track advertising by topic, country and time, with EU reach data.

### How to scrape the Google Ads Transparency Center

1. Click **Try for free**.
2. Enter websites, advertiser names, advertiser IDs or Transparency Center links, one per line.
3. Pick a country, and optionally a platform, format and date range.
4. Click **Start**, then download the results or connect them to your tools through the [Apify API](https://docs.apify.com/api/v2).

### Input

```json
{
    "searchTerms": ["hubspot.com", "Salesforce", "AR16735076323512287233"],
    "region": "US",
    "platform": "all",
    "adFormat": "all",
    "dateFrom": "90 days",
    "maxAdsPerSearch": 200,
    "includeDetails": true
}
```

| Field | What it does |
| --- | --- |
| `searchTerms` | Websites, advertiser names, advertiser IDs (`AR…`) or adstransparency.google.com links. |
| `resultType` | `ads` (default) or `advertisers`. |
| `region` | Two-letter country code (`US`, `DE`, `GB` …) or `anywhere`. |
| `platform` | `all`, `SEARCH`, `YOUTUBE`, `SHOPPING`, `MAPS` or `PLAY`. |
| `adFormat` | `all`, `TEXT`, `IMAGE` or `VIDEO`. |
| `dateFrom`, `dateTo` | A date (`2026-01-01`) or a period (`30 days`, `6 months`). |
| `maxAdsPerSearch` | Maximum ads for each search term. |
| `maxAdvertisersPerName` | For names: how many matching advertisers to include, most ads first. |
| `includeDetails` | Ad text, video data, variations, countries, topic and EU reach (charged per ad). |
| `readAdText` | Read text ads from their pictures (no extra charge). |
| `deduplicate` | Save each ad once per run. |
| `proxyConfiguration` | Apify Proxy for large runs. |

### Output

One row per ad. Switch between the **Ads**, **Ad copy**, **Reach (EU)** and **Advertisers** views, or export everything.

```json
{
    "adId": "CR07916612096559677441",
    "adUrl": "https://adstransparency.google.com/advertiser/AR10072600183532683265/creative/CR07916612096559677441?region=US",
    "advertiserId": "AR10072600183532683265",
    "advertiserName": "Hubspot, Inc.",
    "advertiserCountry": "US",
    "advertiserVerified": true,
    "domain": "hubspot.com",
    "format": "video",
    "firstShown": "2026-02-17T21:32:29Z",
    "lastShown": "2026-10-07T14:24:42Z",
    "daysShown": 233,
    "headline": "HubSpot Smart CRM",
    "longHeadline": "HubSpot Smart CRM gives your whole team one source of truth. Get started free.",
    "description": "See all your customer interactions in one place — and know exactly what to do next.",
    "callToAction": "Sign up",
    "landingPageUrl": "https://www.hubspot.com/crm/e010a",
    "adTextSource": "preview",
    "youtubeVideoId": "FbntBiBmDk4",
    "youtubeUrl": "https://www.youtube.com/watch?v=FbntBiBmDk4",
    "videoDuration": "0:23",
    "youtubeChannelName": "HubSpot Ads",
    "thumbnailUrl": "https://i.ytimg.com/vi/FbntBiBmDk4/hqdefault.jpg",
    "variationCount": 4,
    "topic": null,
    "regions": [
        { "region": "US", "regionName": "United States", "firstShown": null, "lastShown": "2026-10-07" },
        { "region": "CA", "regionName": "Canada", "firstShown": null, "lastShown": "2026-10-07" }
    ],
    "regionCount": 2,
    "searchTerm": "hubspot.com",
    "searchType": "website",
    "region": "US",
    "rank": 2,
    "scrapedAt": "2026-10-08T09:00:00Z"
}
```

A text ad read from its picture has `"adTextSource": "ocr"`. For an ad shown in the EU, `impressionsMin` / `impressionsMax` give the total times shown (Google publishes ranges such as 7,000–8,000), each entry of `regions` carries its own range and platform split, and `audienceSelection` looks like this:

```json
{
    "demographics": "included",
    "locations": "included",
    "contextualSignals": "included",
    "customerLists": "not used",
    "topicsOfInterest": "not used"
}
```

Each run also saves a `RUN_SUMMARY` record in the key-value store: ads saved, how many got details and ad text, the number of ads Google reports for each search term, and any search terms that failed.

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

Pay-per-event pricing: you pay only for results.

| Event | Price |
| --- | --- |
| Ad saved (advertiser, format, dates, days shown, picture or preview link) | $0.0015 |
| Ad details (ad text, video data, variations, countries, topic, EU reach and audience) | $0.0025 per ad |
| Advertiser saved (advertisers mode) | $0.002 |

**1,000 ads with details and ad text cost $4.00**; without details, $1.50. Reading text ads from their pictures costs nothing extra. Duplicates are skipped and not charged, details are charged only when they were loaded, and the run stops exactly at your **Maximum cost per run**. The prices on the **Pricing** tab are the ones that apply.

### Tips

- **Websites are the most reliable search term.** Advertiser names are matched as whole words (`Nike` finds "Nike, Inc." and "NIKE SRL", not "Nikesh") and the advertisers with the most ads are used first.
- **Pick a country.** Google publishes ads per country; `anywhere` mixes them. EU countries add reach and audience data.
- **Use the date filter** to get only recent ads, for example `30 days`.
- **Large runs**: keep Apify Proxy on. The Actor connects directly first; when Google starts limiting requests it switches to the proxy, slows down, changes IP addresses and, if needed, pauses detail lookups for a while, but it still reads the text of every ad. For full details on thousands of ads, choose **Residential** proxies in Proxy configuration.

### Google Ads Transparency Center API alternative

Google offers no official API for the Ads Transparency Center. Run this Actor through the [Apify API](https://docs.apify.com/api/v2), the [Python](https://docs.apify.com/api/client/python) or [JavaScript](https://docs.apify.com/api/client/js) client, schedule it to track competitors every week, or connect it to Make, Zapier, Google Sheets, Slack and more with Apify integrations.

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("sinolens/google-ads-transparency-scraper").call(
    run_input={"searchTerms": ["hubspot.com"], "region": "US", "maxAdsPerSearch": 100}
)
for ad in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(ad["headline"], ad["daysShown"], ad["adUrl"])
```

### FAQ

#### Is it legal to scrape the Google Ads Transparency Center?

The Actor reads only the data Google publishes for everyone on adstransparency.google.com, without logging in. Whether your use is allowed depends on your jurisdiction, Google's terms and what you do with the data, so ask a lawyer if you are unsure. Read more in Apify's post on [the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

#### How accurate is the ad text?

When Google's preview contains the text (video, Discover, Shopping and many local ads), it is exact (`"adTextSource": "preview"`). For text ads that Google publishes only as a picture, the text is read with OCR (`"adTextSource": "ocr"`). These pictures are clean renders, so the result is usually exact, but expect an occasional misread character. `adText` always has every line that was read, including sitelinks and other extensions.

#### Why do some ads have no text?

Some ads have no text of their own (image banners, HTML5 ads), and some previews are not public. Their pictures (`imageUrl`) and variations are still included. Text is not read from banner images.

#### Why are reach and audience data empty for some ads?

Google publishes them only for ads shown in the EU and EEA, under the Digital Services Act.

#### Why do some ads have no countries or EU reach?

These come from a separate lookup per ad that Google limits per IP address. When Google throttles it, the Actor saves the ad with its text and dates but without countries and reach, and tells you so in the log. A residential proxy avoids this on large runs.

#### Why did I get fewer ads than I asked for?

The advertiser may have fewer ads with your filters, duplicates are skipped, and the run stops at your maximum cost. `RUN_SUMMARY` shows how many ads Google reports for each search term.

#### Can you add a feature?

Open an issue on the **Issues** tab. Requests for new fields or filters are welcome.

### Changelog

- **0.1**: First release: search by website, name, ID or link; country, platform, format and date filters; ad text (preview and OCR); YouTube data; EU reach and audience; advertisers mode.

# Actor input Schema

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

One per line. Each can be:<br>• a <b>website</b> (<code>nike.com</code>): ads of every advertiser that points to it;<br>• an <b>advertiser name</b> (<code>Nike</code>): the advertisers with that name, most ads first;<br>• an <b>advertiser ID</b> (<code>AR16735076323512287233</code>);<br>• a <b>link</b> from adstransparency.google.com (an advertiser page, one ad, or a website search).

## `resultType` (type: `string`):

<b>Ads</b>: one row per ad. <b>Advertisers</b>: one row per advertiser (name, country, verification, number of ads), for example to find the companies behind a website or every advertiser with a word in its name.

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

Only ads shown in this country. The ads Google publishes differ by country; for the EU, Google also publishes how often each ad was shown and how its audience was chosen.

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

Only ads shown on this Google service. Google applies this filter only to ads shown since 4 September 2023.

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

Only text, image or video ads.

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

Only ads shown on or after this date (Pacific Time), for example <code>2026-01-01</code>, or a period such as <code>30 days</code>. Empty: any time since May 2018.

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

Only ads shown on or before this date. Empty: today.

## `maxAdsPerSearch` (type: `integer`):

Stop after this many ads for each website, name or ID. Large advertisers have tens of thousands of ads.

## `maxAdvertisersPerName` (type: `integer`):

For advertiser names: how many matching advertisers to include (most ads first). Many brands have several accounts, for example one per region. In <b>Advertisers</b> mode, this is how many advertisers to return per search term (up to 100).

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

For each ad: the ad text (headline, description, display URL, call to action, landing page), YouTube link and video data, all variations, the countries where it ran with first and last dates, Google's topic, and for the EU the number of times shown and the audience selection. Charged per ad that gets details.

## `readAdText` (type: `boolean`):

Google publishes most text ads only as a picture. With this on, the picture is read (OCR) to get the headline, description and display URL. Slower; no extra charge.

## `deduplicate` (type: `boolean`):

Save each ad only once per run, even if several search terms find it.

## `maxConcurrency` (type: `integer`):

How many requests to Google at the same time. Lower it if the log shows throttling.

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

Google limits how many requests one IP address can make. The Actor connects directly first and switches to this proxy when Google starts limiting it. For thousands of ads with details, residential proxies work best.

## Actor input object example

```json
{
  "searchTerms": [
    "nike.com",
    "HubSpot",
    "AR16735076323512287233"
  ],
  "resultType": "ads",
  "region": "US",
  "platform": "all",
  "adFormat": "all",
  "maxAdsPerSearch": 10,
  "maxAdvertisersPerName": 3,
  "includeDetails": true,
  "readAdText": true,
  "deduplicate": true,
  "maxConcurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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 = {
    "searchTerms": [
        "nike.com"
    ],
    "region": "US",
    "maxAdsPerSearch": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

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

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

```

## MCP server setup

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