# Google Ads Transparency Scraper — $0.80/1K (`meka.im/google-ads-transparency-scraper`) Actor

Scrape Google Ads Transparency Center by keyword, domain, advertiser ID or pasted URL. Filter by country, date, format and platform. Ad creatives or advertiser summaries, image previews, per-country reach and EU impression ranges. $0.80 per 1,000 delivered results, no start fee, no login.

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

## Pricing

Pay per event

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

Find the Google ads behind any brand — across Search, YouTube, Shopping, Maps and Play — without Google
Ads API access. Search by **brand, exact domain, advertiser ID, or a pasted Transparency Center URL**,
then filter by **country, date, format and platform**. Export creative previews, advertiser identity,
first/last shown dates, days active, every creative variation, per-country reach and — for ads served in
the EU — **published impression ranges with a per-platform split**.

**$0.80 per 1,000 delivered results. No start fee.** The common price band for comparable Actors on this
Store was $1–$3 per 1,000 ads when we surveyed it on 2026-09-20. You are billed only for rows that were
parsed and written to the dataset: **no charge for empty searches, failed lookups, invalid inputs, or
duplicates**, and a resumed run never bills the same row twice.

**Built for competitor monitoring, creative research, agency audits and scheduled ad intelligence.**
No login, cookies, browser or Google account required.

### Quick start

1. Open the Actor, paste a brand name or domain into **Brand names or domains**, and click **Start**.
2. Leave **Country / region** at `US` (or set `DE`, `GB`, `ANYWHERE`, …).
3. Watch rows stream into the dataset, then export JSON, CSV, Excel or XML — or pull them over the API.

A first run that costs about 8 cents:

```json
{
  "queries": ["Nike"],
  "domains": ["hellofresh.com"],
  "resultType": "ads",
  "region": "US",
  "maxResults": 100,
  "includeDetails": true
}
```

### Input

Four targeting inputs, freely mixable. They are de-duplicated, and the run processes them in this order:
`queries` → `domains` → `advertiserIds` → `startUrls`.

| Input | What it does |
|---|---|
| `queries` | Brand names (`Nike`) or bare domains (`nike.com`). Brand names go through the Transparency Center's own autocomplete. |
| `domains` | Exact domains. Returns every advertiser account whose ads point at that domain. |
| `advertiserIds` | Advertiser IDs starting with `AR`. |
| `startUrls` | Pasted Transparency Center URLs — advertiser pages, creative pages or domain search pages. |
| `resultType` | `ads` for individual creatives, `advertisers` for one summary row per advertiser. |
| `region` | ISO country code (`US`, `DE`, `GB` …), `ANYWHERE`, or several codes comma-separated. |
| `platforms` | `SEARCH`, `YOUTUBE`, `SHOPPING`, `MAPS`, `PLAY`. |
| `adFormat` | `ALL`, `TEXT`, `IMAGE`, `VIDEO`, or several comma-separated. |
| `startDate` / `endDate` | `YYYY-MM-DD` window. |
| `maxAdsPerSearch` | Cap per target. Default 100. |
| `maxResults` | Hard cap on delivered rows for the whole run — this is what you pay for. Default 1000. |
| `maxAdvertisersPerQuery` | How many advertisers a brand-name query expands to. Default 5. |
| `includeDetails` | **On by default.** Adds variations, per-country reach and EU impressions. Turn it off for a faster list-only run. |
| `detailConcurrency` | Parallel detail batches. Default 2. |

### Output

In `ads` mode each creative is one dataset row:

```json
{
  "creativeId": "CR15180131156851949569",
  "advertiserId": "AR00930880903813529601",
  "advertiserName": "Grocery Delivery E-Services USA Inc.",
  "domain": "hellofresh.com",
  "format": "TEXT",
  "firstShown": "2025-09-29T17:01:00.000Z",
  "lastShown": "2026-09-20T03:42:35.000Z",
  "shownForDays": 351,
  "previewType": "image",
  "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/8397313563983018971",
  "previewUrl": null,
  "width": 348,
  "height": 232,
  "googleCreativeId": null,
  "googleCustomerId": null,
  "adGroupId": null,
  "versionId": null,
  "adUrl": "https://adstransparency.google.com/advertiser/AR00930880903813529601/creative/CR15180131156851949569?region=US",
  "region": "US",
  "variationCount": 1,
  "variations": [
    { "type": "image", "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/8397313563983018971",
      "previewUrl": null, "width": 348, "height": 232,
      "googleCreativeId": null, "googleCustomerId": null, "adGroupId": null, "versionId": null }
  ],
  "regionsShown": [{ "region": "US", "lastShownDate": "2026-09-19" }],
  "euTransparency": {
    "available": true,
    "impressions": { "lowerBound": 3000000, "upperBound": 3500000 },
    "firstShownDate": "2023-07-02",
    "lastShownDate": "2026-09-19",
    "platformDistribution": [
      { "platform": "SEARCH", "impressions": { "lowerBound": 3000000, "upperBound": 3500000 } },
      { "platform": "SHOPPING", "impressions": { "lowerBound": null, "upperBound": 1000 } }
    ]
  }
}
```

Notes on the values:

- `shownForDays` is a strong "this creative is working" signal for competitive analysis.
- `imageUrl` is a direct CDN link and is present for archived image previews; text, video and rich-media
  creatives expose a Google-hosted `previewUrl` instead, which is a render page rather than a raw asset.
- `googleCustomerId` groups creatives from the same ad account; `adGroupId` clusters them by campaign.
  Both are `null` for plain image ads.
- `regionsShown` lists every country the creative ran in, each with that country's own last-shown date.
- `euTransparency.available` is `false` when Google publishes no EU block for that creative. Unknown
  numbers come through as `null`; a `0` in the data is a real zero.
- With `includeDetails` off, `variationCount`, `variations`, `regionsShown` and `euTransparency` are
  omitted rather than returned empty.

In `advertisers` mode each row is an advertiser summary with `advertiserId`, `name`, `countryCode`,
`approxAdCountLow` / `approxAdCountHigh` (Google's own approximate range), `matchedQuery`, `region` and
`advertiserUrl` — a cheap way to check which companies on a list run Google Ads before pulling creatives.

### EU impression data

Advertisers serving in the EU must publish impression ranges under the Digital Services Act, and the
Transparency Center exposes them per creative. This Actor surfaces that block as `euTransparency`,
including the split by Google surface. In a 60-creative sample taken on 2026-09-20, every creative from
German targets carried the block and 18 of those 30 carried impression ranges, while only 2 of 30 US
creatives did. Treat it as a bonus for EU-served ads, not as a field present on every row.

### Pricing

Pay-per-event, **$0.0008 per delivered result — $0.80 per 1,000**. Platform usage is included; there is
no monthly rental and no Actor-start fee.

| Event | Price | When it fires |
|---|---|---|
| `ad-delivered` | $0.0008 | One ad creative written to the dataset in `ads` mode |
| `advertiser-delivered` | $0.0008 | One advertiser summary written in `advertisers` mode |

Not billed: searches that return nothing, invalid inputs, duplicate targets, failed detail lookups, and
rows a resumed run had already delivered. Set **Max results for the run** or the run's
**maximum total charge** for a hard ceiling — the run stops before publishing a row it cannot bill.

### Limits

- **Not available from the public protocol:** ad headline, body copy and CTA text; landing-page URLs;
  video file URLs, video thumbnails and video durations. Video creatives do come back with their
  identity, format, dates and per-country reach, but without playable media.
- **Not inferred:** whether an ad is currently running or has been retired, advertiser verification
  status, and whether a creative is a carousel. The source publishes no field for these, and this Actor
  does not guess.
- Platform filtering covers creatives shown on or after 2023-09-04, which is a limitation of the source.
- Ad format filtering is applied to the returned rows; the upstream protocol has no format filter.
- Upstream pages are capped at 100 rows; the Actor paginates internally, so larger `maxResults` values
  simply take more requests.
- With `includeDetails` on, a creative whose detail lookup keeps failing is not delivered and not billed.

### API and automation

Start runs and pull results over the [Apify API](https://docs.apify.com/api/v2), the
[JavaScript client](https://docs.apify.com/api/client/js/) or the
[Python client](https://docs.apify.com/api/client/python/). Put it on a
[schedule](https://docs.apify.com/platform/schedules) to track a competitor week over week, and use
[webhooks](https://docs.apify.com/platform/integrations/webhooks) to trigger downstream work. The output
is plain JSON, so it also plugs into agents through the
[Apify MCP server](https://docs.apify.com/platform/integrations/mcp).

JavaScript:

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });
const run = await client.actor('google-ads-transparency-scraper').call({
  queries: ['Nike'],
  region: 'US',
  platforms: ['YOUTUBE'],
  adFormat: 'VIDEO',
  maxResults: 200,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, 'creatives');
```

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("MY_APIFY_TOKEN")
run = client.actor("google-ads-transparency-scraper").call(run_input={
    "domains": ["hellofresh.com"],
    "region": "DE",
    "startDate": "2026-01-01",
    "maxResults": 500,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["creativeId"], item["format"], item["shownForDays"])
```

### FAQ

**Do I need a Google account, cookies or a proxy?** No. The Actor reads the public Transparency Center
over anonymous HTTP from data-centre IPs.

**Why is `imageUrl` null on some rows?** Those creatives expose a Google-hosted render page instead of an
archived bitmap. `previewUrl` carries it, and `previewType` tells you which form you got.

**Can I get the ad's text or landing page?** Not from this source. The archived preview is a rendered
bitmap and the render page contains no copy, so this Actor does not claim those fields.

**What happens if I abort a run and start it again on the same dataset?** It resumes. Rows already in the
dataset are skipped, physical order is preserved, and nothing is billed twice.

**How do I keep spend predictable?** Set `maxResults`, and optionally set a maximum total charge on the
run. The run stops before it would publish a row beyond your budget.

**Which Google surfaces are covered?** Search, YouTube, Shopping, Maps and Play. Filter with `platforms`,
or leave it empty for every surface.

### Legal

This Actor is an independent tool. It is not affiliated with, endorsed by, sponsored by or certified by
Google LLC or any of its subsidiaries, and it is not an official Google product. "Google", "Google Ads"
and "Google Ads Transparency Center" are trademarks of their respective owners and are used here only
descriptively, to identify the publicly accessible source this Actor reads. The Actor collects only
information Google publishes publicly. You are responsible for ensuring your use of that information
complies with applicable laws, regulations and the source website's terms.

# Actor input Schema

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

"ads" returns individual ad creatives. "advertisers" returns one summary row per advertiser — a cheap way to check which companies run Google Ads.

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

Free-text brand names (e.g. "Nike") or bare domains (e.g. "nike.com"). Brand names are resolved to advertisers through the Transparency Center's own autocomplete; anything that looks like a domain is used directly.

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

Exact domains to pull ads for. Returns every advertiser account whose ads point at that domain.

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

Specific advertiser IDs starting with "AR", as they appear in an advertiser's Transparency Center URL.

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

Paste Transparency Center URLs: advertiser pages, creative pages, or domain search pages. They are parsed automatically.

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

ISO 3166-1 alpha-2 country code (US, DE, GB …), or ANYWHERE for no country filter. Several codes can be given comma-separated; results are the union.

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

Restrict to ads served on specific Google surfaces. Leave empty for all.

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

Filter by creative format. Several formats can be given comma-separated.

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

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

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

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

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

Maximum ad creatives to collect for each domain or advertiser.

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

Hard cap on delivered rows across all targets. This is what you pay for.

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

When a brand-name query resolves to several advertisers, how many of the top matches to scrape.

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

On by default. Adds every creative variation, the per-country reach with each country's last-shown date, and EU impression ranges. Turn it off for a faster, list-only run.

## `detailConcurrency` (type: `integer`):

How many detail batches to fetch in parallel.

## Actor input object example

```json
{
  "resultType": "ads",
  "queries": [
    "Nike",
    "hellofresh.com"
  ],
  "domains": [
    "nike.com"
  ],
  "advertiserIds": [
    "AR16735076323512287233"
  ],
  "startUrls": [
    {
      "url": "https://adstransparency.google.com/advertiser/AR16735076323512287233?region=US"
    }
  ],
  "region": "US",
  "platforms": [],
  "adFormat": "ALL",
  "startDate": "2026-01-01",
  "endDate": "2026-06-01",
  "maxAdsPerSearch": 100,
  "maxResults": 1000,
  "maxAdvertisersPerQuery": 5,
  "includeDetails": true,
  "detailConcurrency": 2
}
```

# Actor output Schema

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

No description

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

// Run the Actor and wait for it to finish
const run = await client.actor("meka.im/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("meka.im/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 meka.im/google-ads-transparency-scraper --silent --output-dataset

```

## MCP server setup

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