# Google Ads Transparency Scraper | $1/1K Starter | Ad Monitor (`x_guru/google-ads-transparency-monitor`) Actor

Scrape Google Ads Transparency Center by company domain or advertiser. Get ad copy, images, YouTube links and shown dates. Export CSV/JSON, resume batches and monitor competitor creatives. $1/1K on Starter; details included. No Google Ads login needed.

- **URL**: https://apify.com/x_guru/google-ads-transparency-monitor.md
- **Developed by:** [Hundevmode Labs](https://apify.com/x_guru) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 2 monthly users, 96.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 ad saveds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 & Ad Monitor

Scrape Google Ads Transparency Center by company domain, advertiser ID, exact advertiser name or ad URL. Collect available ad copy, images, YouTube links and shown dates, export Google ads to CSV/JSON, and monitor competitor creative changes on a schedule.

**$1 per 1,000 saved ads on Starter.** Available creative details and monitoring are included. No Google Ads account or separate data subscription is needed.

### What you can do

- Research competitor ads across text, image and video formats.
- Collect several companies in one run with one total ad limit.
- Export flat fields to spreadsheets and nested creative variants to JSON.
- Continue unfinished collections without repeating already saved ads.
- Compare completed collections on an Apify schedule and get a separate change report.

### 🚀 Quick start

1. Enter company domains, one per line, such as `nike.com` and `shopify.com`.
2. Choose **Maximum ads in this run**, a search country and an ad format.
3. Leave **Include creative details** enabled and run the Actor.
4. Open **Google ads** to inspect results or **Download flat CSV** to export them. Check **Results and coverage** for completeness.

The form starts with **10 ads** for a quick preview. API requests without `maxResults` default to 100. The limit applies to the whole run, after deduplication, and is subject to your spending and resource limits.

```json
{
  "targets": ["nike.com", "shopify.com"],
  "maxResults": 10,
  "country": "ALL",
  "adFormat": "all",
  "includeDetails": true
}
```

### Choose the right search input

| Input | Best use |
| --- | --- |
| Company domain or website URL, such as `nike.com` | Start a company search without finding an advertiser ID first. Website paths are reduced to the domain. |
| Advertiser ID, such as `AR16735076323512287233` | Collect ads from a specific Google advertiser. |
| Google advertiser URL | Reuse an advertiser selected in the Transparency Center. |
| Google creative URL containing both `AR...` and `CR...` | Look up a specific ad. Use **All countries**. |
| Exact advertiser name | Resolve one exact source match. Ambiguous names return candidates rather than choosing an entity for you. |

Add up to 50 targets. Domain searches may include agencies, resellers or several legal entities. They record Google's search association and do not confirm company ownership. For precise advertiser monitoring, use its ID or advertiser URL.

If a name is ambiguous, open **Results by target** or **Input and source issues**, select the correct advertiser ID, and start a new search. This is advertiser lookup, not a general keyword search of every ad's text.

Copied Transparency Center URLs support `domain`, `region` and `format`. Account-selection (`authuser`) and interface-language (`hl`) parameters are ignored. Unsupported date or platform URL filters produce a clear error; remove those parameters and use the supported form filters. URL country/format filters override the form for that target.

### Country, format and 📅 last-shown filters

Country and ad format are applied by Google's search source. Country is a search scope, not exact audience targeting or reach. Single creative URLs require `country: "ALL"`; use advertiser/domain searches for a country filter.

**Last shown on or after/before** compares the source's last-shown date, inclusively, using UTC calendar dates. This filter is applied after search pages are fetched. It does not reconstruct every impression during a date interval. Narrow windows can take more requests; ads without a usable last-shown date are excluded and counted in the target report.

```json
{
  "targets": ["AR16735076323512287233"],
  "country": "US",
  "adFormat": "image",
  "lastShownFrom": "2026-10-01",
  "maxResults": 25
}
```

### Google Ads output and creative details

**One dataset row is one unique Google creative ID.** Multiple variants do not create extra paid rows. If the same ad appears under several targets, it is saved once and attributed to the first target that delivered it.

| Fields | Meaning |
| --- | --- |
| `adId`, `advertiserId`, `adUrl`, `advertiserUrl` | Source identifiers and links back to Google. |
| `advertiserName`, `advertiserDomain`, `matchStatus` | Available source identity and how the input matched. |
| `adFormat`, `firstShownDate`, `lastShownDate`, `daysShown` | Source format, UTC shown dates and source approximate served-day count. |
| `headline`, `description`, `displayUrl`, `callToAction` | Available copy from the primary extracted variant. |
| `imageUrl`, `videoUrl`, `previewUrl` | Image link, YouTube watch link and source preview resource. |
| `creativeVariants`, `creativeVariantCount`, `extractedVariantCount`, `variantsTruncated` | Nested extracted variants, source count and extraction completeness. |
| `requestedCountry`, `searchTarget`, `observedAt` | Search scope and collection observation. |
| `changeType`, `firstSeenAt` | Monitor status and first observation by this monitor; null in collect mode. |

**Include creative details** is on by default and extracts up to three variants per ad. Change **Creative variants per ad** in Advanced settings if needed. `variantsTruncated` indicates that the source returned more variants than were extracted. Missing facts stay `null`.

Turn details off for faster listing metadata collection. Copy/media extraction is skipped. A direct creative URL still needs a detail request to identify the ad. An advertiser name can be unavailable for that lookup.

Images and YouTube videos are provided as links; files are not downloaded or stored. Image copy is not OCR-transcribed. `displayUrl` is displayed URL text, not a verified final landing page. Source preview resources can contain renderer JavaScript; **open `adUrl` to view an ad on Google**. Links can expire or become unavailable. `mediaStatus: "available"` means a link was extracted, not permanent hosting.

Console views include **Google ads** with image thumbnails, **Creative details**, and **Monitoring status**. The flat CSV includes scalar fields; use JSON for nested variants and region records.

### 🔄 Continue a partial run

The default collection order takes up to five ads per company turn, giving several targets a share of the global limit. Sequential collection is also available in Advanced settings. A source failure for one target does not prevent the others from being processed.

1. Open **Continue: next input** (`PAGINATION`) in the previous run output.
2. If `hasMore` is true, copy `nextInput` into a new run's JSON input.
3. Increase the ad limit or **Maximum cost per run** if necessary. For request/time/transfer limits, adjust the corresponding Advanced settings.
4. Start the next run after the previous one finishes. It skips delivered IDs and uses buffered pages before requesting later pages.

Use the same account and Actor, keeping targets, search filters, detail mode and creative-variant limit unchanged. A failed or aborted run can be continued if its checkpoint and dataset were retained. Continue each predecessor once; concurrent continuations can duplicate work. A new search is needed when you change the search scope.

Check **Results by target** and **Input and source issues** for the reason a search paused. Restricted source requests may remain unavailable on another run; continuation preserves progress but does not guarantee access. Unresolved advertiser names need a new search with a selected ID.

The Actor checks Apify result-budget capacity before fetching chargeable results and before saving them. Budget exhaustion stops collection with `budget_limit` and preserves remaining work. Platform shutdown can also stop a run; retained checkpoints support recovery.

### Monitor competitor Google ads on a schedule

Select **Monitor creative changes**, keep creative details enabled, save an Apify Task and schedule that Task. The Task automatically loads and updates its previous completed snapshot. For direct/API runs, supply a stable **Monitor name** (`monitorKey`). Use different names for independent monitors and run each monitor sequentially.

```json
{
  "targets": ["AR16735076323512287233"],
  "mode": "monitor",
  "monitorKey": "nike-creatives-us",
  "country": "US",
  "includeDetails": true,
  "maxResults": 100
}
```

The first complete collection establishes `BASELINE`. Later rows are `NEW`, `UPDATED` or `UNCHANGED`. **Monitoring changes** (`CHANGES`) contains baseline/new/updated records and `NOT_OBSERVED` records only after a complete search. Not observed does not prove that an ad ended. Temporary preview signatures and source date changes alone are not creative updates.

The monitor compares extracted variants. It does not replace its completed baseline after an incomplete search or a collection containing ads for which only an undecoded preview could be extracted. A partly decoded variant set can still miss changes in the unavailable content. Complete a limited collection through continuation to update its baseline. Overlapping monitor runs are discouraged: changes are checked before committing, but snapshot storage does not provide atomic compare-and-swap guarantees.

All saved ads, including unchanged monitor rows, are paid results. There is no separate monitoring fee. Use the change report to pass useful changes into n8n, Make or your own workflow; the Actor does not send notifications itself.

### Pricing

| Apify plan | Price per 1,000 saved ads |
| --- | ---: |
| Free | $1.50 |
| Starter | $1.00 |
| Scale | $0.90 |
| Business and higher | $0.80 |

Platform usage, available creative details and monitoring are included. There is no separate fee for a detail request, media link, target or page. Apify automatically charges **$0.00005 per start event per GB of allocated memory, minimum one event**. At the default 256 MB allocation, one start event is charged.

For example, 10 saved ads on Starter cost **$0.01005** including one start event; 1,000 saved ads cost **$1.00005**. These are billing examples, not predictions of how many ads a source will return. A zero-result run has no ad charge, but the start event still applies. Errors, summaries, changes and checkpoints in key-value storage are not charged result rows.

Free plans are limited to **100 saved ads across a continuation chain**, with at most 30 source requests, 120 collection seconds and 10 MB of measured transfer per run. Paid plans use their requested ad limit within budget and resource bounds. Plan status is supplied by Apify, not selected in the input. This cap is not a daily account-wide quota.

These are private-pilot rates. The Console pricing panel is the authoritative current tariff.

### Output reports

| Output | What to check |
| --- | --- |
| Google ads / Download flat CSV | Saved ads and export. |
| Results and coverage (`RUN_SUMMARY`) | Saved count, completeness, stop reason and monitor baseline update. |
| Results by target (`TARGET_REPORT`) | Per-company counts, completion and advertiser candidates. |
| Continue: next input (`PAGINATION`) | Remaining work and ready-to-copy next input. |
| Input and source issues (`ERRORS`) | Actionable issues, separate from dataset rows. |
| Monitoring changes (`CHANGES`) | Detected changes; empty in collect mode. |
| Observed snapshot (`SNAPSHOT`) | Current monitor observations and completion; `enabled: false` in collect mode. |

### Frequently asked questions

#### Does this include every ad a company has ever run?

No. It collects the public results returned by Google's Transparency Center within the selected scope and limits. Availability can change; access restrictions, unavailable content and incomplete targets are reported. No spend, conversion data or exact commercial impression counts are promised.

#### Can I enter a large ad limit?

Paid runs accept `maxResults` up to 100,000. That is an input ceiling, not a tested throughput or coverage guarantee. Use a smaller first batch, inspect coverage and continue as needed. Large-volume and long-term stability are not yet established by the private pilot.

#### Why are some headline or advertiser fields empty?

Google does not supply every field for every creative layout. Image copy is not transcribed, and direct creative lookups can lack an advertiser name. Check `creativeContentStatus` and the Google ad URL; unavailable values remain null.

#### How can I automate this with the Apify API?

Send the same JSON input to `POST https://api.apify.com/v2/acts/x_guru~google-ads-transparency-monitor/runs` with your Apify token. Use the returned run's default dataset and key-value store IDs to read ads and reports. For continuation, use `PAGINATION.nextInput`; for scheduled monitoring, run a saved Task. Private-pilot access requires permission to use this Actor.

This independent Actor is not affiliated with Google. It collects Google's public Ads Transparency Center data; source behavior can change.

# Actor input Schema

## `targets` (type: `array`):

Start with company domains such as nike.com, one per line (up to 50). You can also paste an AR advertiser ID, an exact advertiser name or a Google Ads Transparency URL. Domain matches may include agencies and resellers. Ambiguous names return candidates in Results by target; choose an ID for a new search.

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

One total limit across all companies after deduplication. The form starts with 10 ads for a quick preview. Free plans allow up to 100 ads per continuation chain. Paid plans use your chosen limit, subject to budget and resource limits. Continue larger collections with PAGINATION.nextInput.

## `country` (type: `string`):

Country scope applied by Google. All countries is the default. This is not exact targeting or reach data. Single-creative URLs require All countries. URL region/format filters override this form for that target.

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

Choose text, image, video or all formats. Filtering is applied by the source for searches.

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

Recommended: extract available ad copy and image/YouTube links, without a separate detail fee. Turn off for faster metadata-only collection. Some creatives provide previews only; missing fields are null.

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

Collect current search results, or compare creative changes with the previous completed snapshot. Monitoring requires details. All saved ads, including unchanged ones, count toward the result limit and price.

## `lastShownFrom` (type: `string`):

Choose an inclusive UTC calendar date. The filter uses the source last-shown date after fetching pages. Narrow windows can require extra pages.

## `lastShownTo` (type: `string`):

Choose an inclusive UTC calendar date on or after the start date. Leave empty for no upper bound.

## `monitorKey` (type: `string`):

A saved Apify Task automatically uses its own identity and updates the previous completed snapshot. For direct/API monitor runs, enter a stable name such as nike-weekly. Use different names for independent monitors; run each monitor sequentially.

## `resumeFromRunId` (type: `string`):

Prefer copying PAGINATION.nextInput. You may enter a finished run ID from this Actor and your account, keeping the same targets and filters. Saved ads are skipped and buffered pages continue. A restricted source may remain unavailable; retrying is not an access guarantee.

## `collectionStrategy` (type: `string`):

Round robin gives each target up to five ads per turn by default. Sequential finishes earlier targets first. One failed target does not stop other targets.

## `advanced` (type: `object`):

Leave these defaults for a first run. Free plans are capped at 30 source requests, 120 collection seconds and 10 MB per run even if larger values are entered. For paid plans, these fields control the collection limits.

## Actor input object example

```json
{
  "targets": [
    "nike.com",
    "shopify.com"
  ],
  "maxResults": 10,
  "country": "ALL",
  "adFormat": "all",
  "includeDetails": true,
  "mode": "collect",
  "collectionStrategy": "round_robin",
  "advanced": {
    "pageSize": 25,
    "resultsPerTargetTurn": 5,
    "requestTimeoutSeconds": 25,
    "requestDelaySeconds": 0.1,
    "maxRetries": 2,
    "maxRequests": 1000,
    "maxRunSeconds": 600,
    "maxTransferMegabytes": 100,
    "maxNoProgressPages": 3,
    "maxCreativeVariants": 3
  }
}
```

# Actor output Schema

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

One saved row per unique creative. Switch table views or export JSON for nested creative variants.

## `csv` (type: `string`):

All flat ad fields with a UTF-8 BOM for spreadsheet compatibility. Nested regions and creative variants are available in JSON.

## `run_summary` (type: `string`):

Saved counts, completeness, stop reason and whether the monitor snapshot was updated.

## `target_report` (type: `string`):

Counts, completion, stop reasons and advertiser candidates for each input target.

## `pagination` (type: `string`):

When hasMore is true, copy nextInput to continue without repeating saved ads.

## `errors` (type: `string`):

Actionable input/source issues, separate from charged dataset results.

## `changes` (type: `string`):

Monitoring changes and NOT_OBSERVED records; empty in collect mode. Not observed is not proof an ad ended.

## `snapshot` (type: `string`):

Current monitoring observations and completion status; enabled=false in collect mode. Incomplete snapshots do not replace the completed monitor baseline.

# 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 = {
    "targets": [
        "nike.com"
    ],
    "maxResults": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("x_guru/google-ads-transparency-monitor").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 = {
    "targets": ["nike.com"],
    "maxResults": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("x_guru/google-ads-transparency-monitor").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 '{
  "targets": [
    "nike.com"
  ],
  "maxResults": 10
}' |
apify call x_guru/google-ads-transparency-monitor --silent --output-dataset

```

## MCP server setup

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

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/iJJY61OQQ01CCRNsy/builds/tcRFfF1ahUN8Boatd/openapi.json
