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

Scrapes the Google Ads Transparency Center — every ad an advertiser or website runs, with format, dates, images, and optional per-country reach, targeting and video links.

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

## Pricing

from $0.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

### What does Google Ads Transparency Scraper do?

**Google Ads Transparency Scraper** collects ads from the
[Google Ads Transparency Center](https://adstransparency.google.com), Google's
public library of every ad shown on **Search, YouTube, Maps, Play, Shopping and
the Display network**. Paste an advertiser page, a website search or a single ad,
and get each ad's **advertiser, format, first and last shown dates, image and
preview links** as a clean table. Turn on details to add **per-country reach,
impression ranges, targeting and YouTube video links**.

Try it with the two prefilled links: click **Start**, and 80 ads are ready in a
few seconds. Because it runs on the Apify platform, you also get API access,
scheduled runs, integrations (Google Sheets, Make, Zapier, webhooks), run
monitoring and proxy rotation when it is needed.

### Why scrape the Google Ads Transparency Center?

- **Competitor ad research**: see every ad a rival runs, which formats they
  use and how long each ad has been live.
- **Creative inspiration**: collect the image and video ads of a whole market
  in one table, with links to each one.
- **Brand protection**: search your own domain to find advertisers who run
  ads pointing at it.
- **Political ad monitoring**: track political ads in a country with their
  impression and spend ranges, ages and genders targeted.
- **EU reach analysis**: for ads shown in the EU, get impression ranges per
  country and per platform, as published under the Digital Services Act.
- **Ongoing tracking**: schedule a run to log which ads start and stop each week.

### How to scrape Google Ads Transparency Center data

1. Open [adstransparency.google.com](https://adstransparency.google.com) and
   search for an advertiser or a website.
2. Set the site's own filters if you want them: region, format, platform, date
   range, or the political topic.
3. Copy the address from your browser's address bar.
4. Paste it into **Transparency Center links**. Add more links, one per line.
5. Click **Start**, then download the results when the run finishes.

Four kinds of link work:

| Link | Example | What you get |
|---|---|---|
| Advertiser page | `https://adstransparency.google.com/advertiser/AR16735076323512287233?region=US` | The advertiser's ads |
| Website search | `https://adstransparency.google.com/?region=GB&domain=booking.com` | Ads that point to that website, from any advertiser |
| Single ad | `https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR11071274990039990273` | That one ad |
| Political ads | `https://adstransparency.google.com/political?region=US` | Political ads shown in that region |

No link at hand? Type an advertiser name (`Nike`) or a website (`nike.com`)
into **Advertiser names or website domains** instead. A name picks the matching
advertiser with the most ads, and the run log says which one it picked.

### Input

Everything is set on the Input tab. In JSON, the input looks like this:

```json
{
    "startUrls": [
        "https://adstransparency.google.com/advertiser/AR16735076323512287233?region=US",
        "https://adstransparency.google.com/?region=GB&domain=booking.com"
    ],
    "searchTerms": ["nike.com"],
    "maxAdsPerUrl": 40,
    "includeDetails": false
}
```

| Field | What it does |
|---|---|
| `startUrls` | Transparency Center links, one per line. Every filter in the link is applied: `region`, `format` (text, image, video), `platform` (Search, YouTube, Maps, Play, Shopping), `start-date`/`end-date` or a date preset, and `topic=political`. |
| `searchTerms` | Advertiser names or website domains, searched across all regions. Use a link instead when you need filters. |
| `maxAdsPerUrl` | Stops after this many ads for each link or term. Default: 100. |
| `includeDetails` | Opens each ad's own page for per-country dates and reach, every variation, targeting and the YouTube link. Off by default; billed as an extra event per ad. |
| `proxyConfiguration` | Optional; leave it off. The Actor connects directly and only retries refused requests through residential proxies. |

### Output

Each ad becomes one row. A real example from the prefilled run:

```json
{
    "advertiserId": "AR16735076323512287233",
    "advertiserName": "Nike, Inc.",
    "advertiserCountry": "US",
    "creativeId": "CR11433158858407673857",
    "creativeUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR11433158858407673857?region=US",
    "format": "TEXT",
    "firstShown": "2023-11-16",
    "lastShown": "2026-10-01",
    "daysShown": 897,
    "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/6820231750467904850",
    "previewUrl": null,
    "domain": null,
    "impressionsMin": null,
    "impressionsMax": null,
    "spendMin": null,
    "spendMax": null,
    "spendCurrency": null,
    "region": "US",
    "input": "https://adstransparency.google.com/advertiser/AR16735076323512287233?region=US"
}
```

With **Include ad details** on, a political video ad looks like this (preview
links shortened):

```json
{
    "advertiserName": "A MORE AFFORDABLE NEVADA",
    "advertiserCountry": "US",
    "creativeId": "CR03689025381370691585",
    "format": "VIDEO",
    "firstShown": "2026-09-29",
    "lastShown": "2026-10-01",
    "impressionsMin": 150000,
    "impressionsMax": 175000,
    "spendMin": 6000,
    "spendMax": 7000,
    "spendCurrency": "USD",
    "regions": [
        { "country": "US", "firstShown": "2026-09-29", "lastShown": "2026-10-01",
          "impressionsMin": 150000, "impressionsMax": 175000, "platforms": [] }
    ],
    "variationCount": 2,
    "previewUrls": ["https://displayads-formats.googleusercontent.com/ads/preview/content.js?..."],
    "targetedAges": ["18-24", "25-34", "35-44", "45-54", "55-64", "65+"],
    "targetedGenders": ["male", "female"],
    "youtubeVideoId": "DpFuyGWcPJ8",
    "youtubeUrl": "https://www.youtube.com/watch?v=DpFuyGWcPJ8"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or
Excel.

### Data fields

| Field | Description |
|---|---|
| `advertiserId` | The advertiser's Transparency Center ID (`AR…`). |
| `advertiserName` | The advertiser's name as the Transparency Center shows it. |
| `advertiserCountry` | The country the advertiser is based in. |
| `creativeId` | The ad's ID (`CR…`). |
| `creativeUrl` | The ad's page on the Transparency Center. |
| `format` | `TEXT`, `IMAGE` or `VIDEO`. |
| `firstShown`, `lastShown` | First and last day the ad was shown **anywhere in the world**, as `YYYY-MM-DD` in US Pacific time, as the site counts days. A region in the link chooses which ads are listed, not these dates: turn on **Include ad details** for each country's own dates in `regions`. `firstShown` can be empty for single-ad links. |
| `daysShown` | Number of days the ad has been shown, worldwide. Can be empty for single-ad links. |
| `imageUrl` | Image of the ad, where Google archives one: text ads and some image ads. Most image and video ads are served only through `previewUrl`, so this is empty for them. |
| `previewUrl` | The ad's preview script, for ads that render live (most image and video ads). |
| `domain` | The website matched, on website searches. |
| `impressionsMin`, `impressionsMax` | Impression range. Published for political ads. A minimum with an empty maximum is an open range, such as Google's "Over 10M". |
| `spendMin`, `spendMax`, `spendCurrency` | Spend range and its currency. Published for political ads. |
| `region` | The region filter of the search, or `anywhere`. |
| `input` | The link or search term the ad came from. |
| `regions` | With details: each country the ad ran in, with first and last shown dates, and impression ranges overall and per platform where Google publishes them (the EU, and political ads). |
| `euImpressionsMin`, `euImpressionsMax` | With details: the ad's impression range across the EU. |
| `variationCount`, `imageUrls`, `previewUrls` | With details: every variation of the ad and their links. |
| `targetingCriteria`, `targetingExclusions` | With details: the kinds of targeting used to include or exclude people (demographics, location, contextual, topics of interest, customer lists). |
| `targetedAges`, `targetedGenders` | With details: the age ranges and genders targeted, where published. |
| `youtubeVideoId`, `youtubeUrl` | With details: the YouTube video behind a video ad. |

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

The Actor uses **pay-per-event** pricing, so you pay only for results:

- **$0.0008 per ad** saved to the dataset, which is **$0.80 per 1,000 ads**.
- **$0.002 per ad with details**, charged on top only when **Include ad
  details** is on.

For example, 1,000 ads cost $0.80, or $2.80 with details. Apify's free plan
includes $5 of monthly credit, which covers over 6,000 ads. Inputs that return
nothing are never charged. If you set a maximum cost for a run, the Actor
stops as soon as it is reached.

### Tips

- **Filter on the site first.** Region, format, platform and date filters in
  the link shrink the results before the Actor sees them, which saves money.
- **Leave details off for big pulls.** The ad list alone is fast (thousands of
  ads a minute). Turn details on for the ads you want to study.
- **Impressions and targeting are published only for some ads**: ads shown in
  the EU, and political ads. Elsewhere those fields stay empty.
- **Schedule runs** to track when a competitor's ads start and stop.
- Ads that repeat across pages are removed, so each ad appears once per input.

### FAQ, disclaimers and support

**Why are some fields empty?** Google publishes different data for different
ads. Impressions, spend and targeting appear only where the Transparency Center
shows them, mainly for EU and political ads.

**What happens to inputs that return nothing?** They are not saved as rows, so
you are not charged for them. Each one is listed with its reason in the
`FAILED_INPUTS` record of the run's key-value store, and the run's status
message gives the counts. A run fails only when the site refuses every input.

**Does it download the ad images or videos?** No. It returns links to the ads
as Google hosts them.

**Is it legal to scrape the Google Ads Transparency Center?** Google publishes
this data so the public can see who is advertising, and the EU's Digital
Services Act requires an ad repository of this kind. The Actor collects only
ad information and each advertiser's name and country. You are still
responsible for making sure your use complies with Google's Terms of Service
and the laws that apply to you. If in doubt, ask a lawyer.

**Found a problem or need a custom solution?** Open an issue on the
**Issues** tab and we will look into it. Custom scrapers and data feeds are
available on request.

# Actor input Schema

## `startUrls` (type: `array`):

Links copied from adstransparency.google.com, one per line: an advertiser page, a single ad's page, a website (domain) search or the political ads page. Set any filters on the site first — region, format, platform, dates, political topic — then copy the address bar; every filter in the link is applied.

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

A quicker way in, without filters: type a website (nike.com) to get every ad pointing to it, or an advertiser name (Nike) to get the ads of the matching advertiser with the most ads. These search all regions; for a region or other filters, paste a link above instead.

## `maxAdsPerUrl` (type: `integer`):

Stops after this many ads for each link or search term. A big advertiser can have tens of thousands of ads.

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

Opens each ad's own page for more: first and last shown dates and impression ranges per country and platform (impressions are published for ads shown in the EU and for political ads), every variation's image and preview link, targeting used (demographics, location, contextual and more) and the YouTube link of video ads. Charged as an extra event per ad.

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

Leave this off: the Actor connects directly, and only if a request is refused does it retry through residential proxies, from a new address each time. Set a proxy here only to send every request through it.

## Actor input object example

```json
{
  "startUrls": [
    "https://adstransparency.google.com/advertiser/AR16735076323512287233?region=US",
    "https://adstransparency.google.com/?region=GB&domain=booking.com"
  ],
  "searchTerms": [],
  "maxAdsPerUrl": 40,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "startUrls": [
        "https://adstransparency.google.com/advertiser/AR16735076323512287233?region=US",
        "https://adstransparency.google.com/?region=GB&domain=booking.com"
    ],
    "maxAdsPerUrl": 40
};

// Run the Actor and wait for it to finish
const run = await client.actor("mina_safwat/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 = {
    "startUrls": [
        "https://adstransparency.google.com/advertiser/AR16735076323512287233?region=US",
        "https://adstransparency.google.com/?region=GB&domain=booking.com",
    ],
    "maxAdsPerUrl": 40,
}

# Run the Actor and wait for it to finish
run = client.actor("mina_safwat/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 '{
  "startUrls": [
    "https://adstransparency.google.com/advertiser/AR16735076323512287233?region=US",
    "https://adstransparency.google.com/?region=GB&domain=booking.com"
  ],
  "maxAdsPerUrl": 40
}' |
apify call mina_safwat/google-ads-transparency-scraper --silent --output-dataset

```

## MCP server setup

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