# Google Ads Transparency Scraper: EU Reach & Ads (`olliolli/google-ads-transparency-eu`) Actor

Google ads by domain, advertiser or Google Maps list, with EU reach per country and audience criteria. Check which companies advertise. Monitor new ads. Not affiliated with Google.

- **URL**: https://apify.com/olliolli/google-ads-transparency-eu.md
- **Developed by:** [Tom J](https://apify.com/olliolli) (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

> **Independent tool.** Not affiliated with, endorsed by or sponsored by Google. The data comes from Google's public Ads Transparency Center.

Scrape **Google Ads Transparency Center** data by company domain, advertiser ID, Transparency Center link or a whole **Google Maps list**, and get every ad a company runs on Google, with **EU reach per country, audience criteria and topic** included. A cheaper **advertiser check** answers one question per company: *does this business advertise on Google, and under which advertiser?* No login, no API key. From **$1.50 per 1,000 ads**. Failed requests and filtered ads are not charged.

### What you can do with it

- **Research competitor ads**: see which Google ads a competitor runs (Search, YouTube, Shopping, Maps, Play), when each ad was first and last shown and for how many days.
- **See EU reach and targeting**: for ads shown in the EU, get times shown per country (as Google's range), the ad topic and which audience criteria the advertiser used (demographics, location, contextual signals, customer lists, interests).
- **Qualify leads at scale**: run an advertiser check on a Google Maps list of 200 local businesses and find out which ones spend on Google Ads, a strong signal for agencies selling marketing services.
- **Monitor new ads**: watch a list of competitors and receive only the ads that are new since your previous run.
- **Feed reports and dashboards**: export to JSON, CSV or Excel, or push the results to Google Sheets, Make, Zapier or n8n.

### How to use the Google Ads Transparency scraper in 3 steps

1. **Add what you want to look up**: company domains (e.g. `example.be`), Google advertiser IDs, Ads Transparency Center links, or pick a Google Maps scraper dataset in **Google Maps results (dataset)**.
2. **Choose a mode**: `ads` (all ads with details), `advertiserCheck` (yes/no per company) or `monitor` (only new ads). Pick the country in **Countries**; EU details are fetched for the first country in the list.
3. **Click Start.** Each ad (or each checked company) becomes one row in the dataset.

### Modes

| Mode | What you get | Charged per |
|---|---|---|
| `ads` | Every ad of each domain or advertiser, up to **Max ads per domain or advertiser**, with optional EU details | ad, plus ad with EU details |
| `advertiserCheck` | One row per company: advertises on Google yes/no, and the advertiser behind it | check (a "no" is an answer too) |
| `monitor` | The first run with a store name saves the current ads and returns them; later runs return only ads not returned before and first shown on or after the previous run | new ad, plus EU details |

Use one monitor store name per watch list.

### Input

| Field | Meaning | Example |
|---|---|---|
| Domains / advertiser IDs / links | What to look up | `vandenborre.be` |
| Google Maps results (dataset) | A dataset from your own Google Maps scraper run | dataset ID |
| Mode | `ads`, `advertiserCheck`, `monitor` | `ads` |
| Countries | Country for EU details (first one is used) | `BE` |
| Max ads per domain or advertiser | Upper limit per input | `50` |
| `formats`, `shownAfter`, `shownBefore` | Filters (ads removed by a filter are not charged) | `TEXT`, `2026-09-01` |
| Allow residential proxy | Fallback when other connections are refused | on |

Chaining after a Google Maps scraper:

```json
{ "datasetId": "{{resource.defaultDatasetId}}", "mode": "advertiserCheck" }
```

### Output (mode `ads`)

```json
{
  "input": { "type": "domain", "value": "vandenborre.be" },
  "advertiserId": "AR…",
  "advertiserName": "…",
  "domain": "vandenborre.be",
  "creativeId": "CR…",
  "format": "TEXT",
  "firstShown": "2026-03-04",
  "lastShown": "2026-10-21",
  "shownForDays": 232,
  "transparencyUrl": "https://adstransparency.google.com/…",
  "euDetailsRegion": "BE",
  "euDetails": {
    "topic": { "id": 10007, "name": "Internet & Telecom" },
    "regionStats": [{ "region": "BE", "timesShownLowerBound": 6000, "timesShownUpperBound": 7000, "firstShown": "2026-03-04", "lastShown": "2026-10-21" }],
    "audienceSelection": {
      "demographicInfo": "CRITERIA_INCLUDED",
      "geoLocation": "CRITERIA_INCLUDED_AND_EXCLUDED",
      "contextualSignals": "…",
      "customerLists": "CRITERIA_UNUSED",
      "topicsOfInterest": "…"
    }
  }
}
```

EU field names follow Google's own transparency data descriptions. Images and videos are not copied: you get Google's own links to the ad and its preview. The run summary (`OUTPUT`) shows the connection used (`proxyTier`) and how many rows carry the residential surcharge (`residentialItems`). Export as JSON, CSV, Excel or XML.

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

Pay per event, no monthly rental.

| Event | Price |
|---|---|
| Ad | $0.0015 |
| EU details for an ad | $0.001 |
| Advertiser check (per company) | $0.002 |
| Residential proxy (per row collected over residential) | $0.0005 |
| Actor start | $0.00005 |

**Examples:** 500 ads with EU details = 500 × ($0.0015 + $0.001) = **$1.25**. An advertiser check on a Google Maps list of 1,000 companies = **$2.00**. The Pricing tab is authoritative.

#### What you are not charged for

- Ads removed by `formats`, `shownAfter` or `shownBefore`.
- Ads already returned in an earlier monitor run.
- Google Maps rows without an own website.
- Errors.

### Use it after a Google Maps scraper

1. Run a Google Maps scraper in your own Apify account.
2. Choose that dataset in **Google Maps results (dataset)**, pick mode **Advertiser check** and start; or
3. On the Maps scraper, open **Integrations → Add integration**, choose this Actor and use the input above.

Only the `website`, `name`, `city`, `country` and place ID of each Maps row are read. Each company website is checked once.

### Automate & schedule

Create a **Schedule** (e.g. every Monday) in `monitor` mode to receive only new ads of your competitors. Add Apify's **Send email** integration or a webhook to get notified.

### Integrate with any app

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("olliolli/google-ads-transparency-eu").call(
    run_input={"domains": ["example.be"], "mode": "ads", "countries": ["BE"]}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["advertiserName"], item["firstShown"], item["shownForDays"])
```

JavaScript:

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('olliolli/google-ads-transparency-eu').call({ domains: ['example.be'], mode: 'advertiserCheck' });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

*Check the exact input field names in the **Input** tab (JSON view).* The Actor also works from **Make, Zapier, n8n** and **Google Sheets** through Apify's integrations.

### Use with AI assistants (MCP)

Through Apify's MCP server, assistants such as Claude or ChatGPT can call this Actor as a tool: "Which of these 50 companies advertise on Google?"

### Connection and the residential proxy surcharge

The Actor tries a direct connection first, then the Apify datacenter proxy, and only then the residential proxy for the rest of the run. Turn off **Allow residential proxy** to stop instead. It sends few requests at a time, waits between them, never solves captchas, and stops instead of pushing harder when Google refuses requests.

### Good to know

- **Times shown is a range and lags behind**: Google updates these numbers with a delay of weeks.
- EU details exist only for ads shown in the EU/EEA, and are fetched for the first country in **Countries**. Run once per country.
- Spend is not published by Google; the Actor does not estimate it.

### FAQ

**Is this the same as the Google Ads Library?** Google calls it the **Ads Transparency Center**. It is the public library of ads served by verified advertisers. This Actor reads it in bulk.

**Can I see how much a competitor spends on Google Ads?** No. Google does not publish spend. You get ad counts, formats, dates, days active and, for EU ads, a range of times shown per country.

**Which countries have reach and audience data?** Ads shown in the EU/EEA. Elsewhere you still get the ads, dates and formats.

**Can I monitor a competitor's new ads every week?** Yes: `monitor` mode plus a weekly schedule returns only ads you have not seen before.

**Can I check which of my Google Maps leads advertise?** Yes, with `advertiserCheck` on a Maps dataset. Each company website is checked once.

**Is it allowed to scrape the Ads Transparency Center?** The data is public, but Google's terms apply to your use of it. This is an independent tool; you are responsible for complying with those terms and the law that applies to you.

**Why are some ads missing?** Google lists ads per advertiser and region with delays, and your limits and filters reduce the set. Raise **Max ads per domain or advertiser** or remove filters.

### Disclaimer

Independent tool, **not affiliated with, endorsed by or sponsored by Google**. Users are responsible for complying with the Ads Transparency Center terms and the law that applies to their use of the data.

### Need help?

Open an issue on the **Issues** tab. Feature requests are welcome.

# Actor input Schema

## `mode` (type: `string`):

Ads: every ad with its EU details. Advertiser check: one cheap row per domain. Monitor: like Ads, but only new ads since the previous run with the same monitor store name.

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

For example coolblue.be. A full URL works too; only the domain is used.

## `advertiserIds` (type: `array`):

Google advertiser IDs (AR…), from an Ads Transparency Center link.

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

Links from adstransparency.google.com (advertiser, ad, or a search by domain). A link to one ad returns all ads of its advertiser.

## `datasetId` (type: `string`):

A dataset with company websites, for example your own Google Maps scraper run. Only the website, name, city, country and place ID of each row are read; rows without an own website are skipped and not charged. Chain it: add an integration on your Maps scraper with {"datasetId": "{{resource.defaultDatasetId}}"}. You are responsible for how you obtained the listing data.

## `regions` (type: `array`):

Countries to search. EU details (times shown, audience) are fetched for the first country in the list.

## `includeEuDetails` (type: `boolean`):

Times shown (range) per country and platform, audience selection and topic. Charged per ad that has details (EU countries).

## `maxAdsPerTarget` (type: `integer`):

Stops per domain or advertiser after this many ads (in the order Google lists them).

## `formats` (type: `array`):

Leave empty for all. Filtered ads are not charged.

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

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

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

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

## `monitorStoreName` (type: `string`):

Monitor mode remembers the ads it returned in a named key-value store in your account. Use one name per watch list.

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

Kept low on purpose: the Actor is polite to Google's servers.

## `allowResidentialProxy` (type: `boolean`):

Google sometimes shows its "unusual traffic" check to cloud servers. The Actor then switches by itself: first to Apify's datacenter proxy, then to Apify's residential proxy. Only rows collected over the residential proxy carry the extra "Residential proxy" charge (see Pricing). Switch off to never use it; the run then stops when Google refuses the datacenter proxy too.

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

Usually not needed: the Actor picks a connection by itself (see above). A proxy you choose here is tried first.

## `failIfEmpty` (type: `boolean`):

For a daily health check with domains that always advertise.

## Actor input object example

```json
{
  "mode": "ads",
  "domains": [
    "vandenborre.be"
  ],
  "regions": [
    "BE"
  ],
  "includeEuDetails": true,
  "maxAdsPerTarget": 10,
  "monitorStoreName": "google-ads-monitor",
  "maxConcurrency": 3,
  "allowResidentialProxy": true,
  "failIfEmpty": false
}
```

# Actor output Schema

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

Ads (with EU details) or one advertiser check per company.

## `summary` (type: `string`):

Counts, filtered and skipped ads, stop reason (OUTPUT).

# 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": [
        "vandenborre.be"
    ],
    "regions": [
        "BE"
    ],
    "maxAdsPerTarget": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("olliolli/google-ads-transparency-eu").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": ["vandenborre.be"],
    "regions": ["BE"],
    "maxAdsPerTarget": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("olliolli/google-ads-transparency-eu").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": [
    "vandenborre.be"
  ],
  "regions": [
    "BE"
  ],
  "maxAdsPerTarget": 10
}' |
apify call olliolli/google-ads-transparency-eu --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,olliolli/google-ads-transparency-eu"
        }
    }
}
```

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/kXjr3YUavxghM4QJt/builds/lwO7eJCcuzAJKO3Yx/openapi.json
