# Google Ads Transparency Center Scraper: Any Advertiser's Ads (`everyotherfriday/google-ads-transparency`) Actor

Competitive ad intelligence without a login: resolve an advertiser by name or domain, then pull their creatives with preview images, ad text, YouTube video IDs, formats, regions and run dates. Filter by format, platform and date. Built for ad-spy research, agencies and sales prospecting.

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

## Pricing

from $2.00 / 1,000 creative returneds

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

## Google Ads Transparency Center Scraper

Export public advertisers and advertising creatives from Google Ads Transparency Center using anonymous HTTP requests. This actor uses Python 3.12, the Apify SDK, httpx, and Beautiful Soup. It does not launch a browser or require a Google account. Its internal RPC adapter was checked against real responses on September 26, 2026. These endpoints are undocumented and can change without notice. Review VALIDATION.md before deployment, especially the unsupported Display platform filter.

### Quick start

Create a Python 3.12 virtual environment inside this directory and install `requirements.txt`. Run `python -m unittest discover -s tests -v` for offline checks. Run `apify validate-schema .actor/input_schema.json` to validate the Console input form. To exercise the actual SDK entry point with isolated local storage, run `powershell -File validation/run_live.ps1 -Python .venv/Scripts/python.exe`. The harness stops a hung subprocess after 115 seconds and saves results under validation. It excludes inherited Apify credentials from the child environment.

The supplied INPUT.json searches `nike.com` and `Shopify`, restricts serving evidence to the United States, and caps output at 40 creatives per input. It explicitly disables Apify Proxy so the daily smoke test needs no keys. The measured default run took approximately 23 seconds and returned 80 creatives. Normal hosted inputs default to Apify Proxy enabled; configure proxy access in the hosting account before using that default.

### Inputs and matching

`advertisers` accepts AR identifiers, advertiser names, and domains. AR identifiers receive an advertiser lookup. Names use SearchSuggestions and select the matching suggestion with the largest estimated creative count. This is a documented heuristic, not proof of company identity: inspect the returned advertiser name and ID, then use an explicit ID for repeatable monitoring. Domain searches can match several regional legal entities. They return a separate advertiser row for every resolved ID encountered among matching creatives.

`region` accepts a supported ISO alpha-2 country code or `anywhere`, the default. The checked-in country mapping comes from Google's public frontend configuration. `formats` is a multiselect of text, image, and video; all three are enabled by default. `platforms` optionally selects YouTube, Search, Maps, or Shopping. The current RPC enum has no Display value. Selecting Display produces an uncharged warning and skips that selection; selecting only Display performs no searches. An unfiltered search can still return image creatives.

`dateFrom` and `dateTo` accept inclusive YYYY-MM-DD boundaries on the creative's last-shown date in UTC. Filtering happens locally against returned timestamps; records without usable dates are excluded when a date filter is present. `maxCreativesPerAdvertiser` defaults to 200 and is applied as a combined cap per submitted input, including domain searches spanning multiple advertiser IDs. Duplicate advertiser and creative records are suppressed across the entire run. Sparse filtered searches also have a finite page budget and report truncation with a summary row.

`includeCreativeDetails`, default false, fetches each selected creative's detail endpoint and extracts rendering variations and available country/date information. `timeoutSecs` bounds each HTTP operation. `proxyConfiguration` accepts the standard Apify proxy object. No credentials belong in this repository or input examples.

### Dataset contents

Advertiser rows contain rowType, original input, advertiserId, advertiserName, verified, region, domains, creativeCountEstimate, url, and source. Verification inverts Google's unverified flag. Domain lists contain observed input domains, not an exhaustive advertiser portfolio. Estimates are source ranges or null; they are not exact inventory counts.

Creative rows contain advertiserId, advertiserName, creativeId, format, platforms, regions, firstShown, lastShown, previewUrl, landingDomain, text, youtubeVideoId, url, and source. Optional details add variations. Missing information stays null or empty. Platforms and regions represent known evidence, not exhaustive coverage: without a platform filter the platform list is empty, and overlapping filtered discoveries retain the first observation. Preview URLs are rendered image URLs or identified YouTube thumbnails, never renderer JavaScript links. Some formats supply neither. Text extraction uses visible renderer markup; image OCR is outside this actor's scope. Preview links may expire.

### Reliability and pricing

Requests retry twice with one- and two-second backoff for HTTP 429, server errors, or transport failures. Proxy sessions rotate every eight requests. A redirect to `/sorry` retries through up to three new proxy sessions, then stops with an uncharged warning. Without a proxy, a block stops immediately. No CAPTCHA solving or signed-in session access is attempted.

Each unique successful advertiser row requests one `advertiser-lookup` event at $0.01. Each creative row requests one `creative-returned` event at $0.002. Summary and error rows are free. Local non-PPE runs do not bill. Configure both events from `.actor/pay_per_event.json` and disable synthetic events before publication. Charging precedes persistence to respect charge limits; a storage failure after charging cannot be rolled back atomically. This project has not been pushed or published.

### Platform validation update

The earlier local-only and no-push statements above describe the original build. Claude's 2026-09-26 platform handoff in the project MESSAGES.md records an immediate /sorry block without proxy: one summary, zero creatives. Apify datacenter proxy returned four advertisers and 80 creatives in 30 seconds. This actor needs Apify datacenter proxy on the platform; it is now on by default, including INPUT.json. The earlier statement that supplied INPUT disables proxy is historical. This observed success does not guarantee future access.

### Example output

One recorded dataset row, trimmed by omitting fields only. Values are the saved snapshot, not current measurements. Source: [validation/results-default.json](validation/results-default.json), first row in the rows array.

```json
{
  "rowType": "advertiser",
  "advertiserId": "AR18378488041124659201",
  "advertiserName": "Nike Retail BV",
  "verified": true,
  "region": "NL",
  "domains": [
    "nike.com"
  ],
  "creativeCountEstimate": null
}
```

### Use cases

- A paid media agency can collect competitor creatives by explicit advertiser ID and assemble a dated review board of available previews.
- A brand team can resolve a domain to regional advertiser entities and manually confirm identities before repeating creative monitoring.
- A creative strategist can filter video or image records and inspect available text and links when preparing a campaign research workshop.
- A market analyst can compare creatives returned under different region filters while retaining each run as a separate evidence snapshot.

### Pricing example

Hypothetical batch, calculated from [`.actor/pay_per_event.json`](.actor/pay_per_event.json):

| Event | Count | USD per event | Subtotal |
| --- | ---: | ---: | ---: |
| `creative-returned` | 1,000 | $0.002 | $2.0000 |
| `advertiser-lookup` | 10 | $0.01 | $0.1000 |

Total declared event charges: **$2.10**. These counts are a budgeting example, not a promised yield or an actual bill. Any applicable platform or proxy costs are outside this calculation.

### Limitations

Display-specific filtering is unavailable. Returned creatives do not establish spend, conversions, or effectiveness. Null previews and incomplete platform evidence do not prove that advertising is absent.

# Actor input Schema

## `advertisers` (type: `array`):

Advertiser IDs, names or domains. Names select the largest matching suggestion; domains can resolve multiple advertisers.

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

ISO alpha-2 country code, or anywhere.

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

formats

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

Optional platforms. Display has no current RPC enum and returns an uncharged warning; use no filter for all surfaces.

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

Inclusive YYYY-MM-DD filter on lastShown; missing dates excluded when filtering.

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

Inclusive YYYY-MM-DD filter on lastShown; missing dates excluded when filtering.

## `maxCreativesPerAdvertiser` (type: `integer`):

maxCreativesPerAdvertiser

## `includeCreativeDetails` (type: `boolean`):

includeCreativeDetails

## `timeoutSecs` (type: `integer`):

timeoutSecs

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

Keep Apify Proxy on: Google blocks direct datacenter traffic to the Transparency Center with a /sorry page. Standard datacenter proxy groups work; sessions rotate automatically.

## Actor input object example

```json
{
  "advertisers": [
    "nike.com",
    "Shopify"
  ],
  "region": "anywhere",
  "formats": [
    "text",
    "image",
    "video"
  ],
  "maxCreativesPerAdvertiser": 10,
  "includeCreativeDetails": false,
  "timeoutSecs": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `rows` (type: `string`):

No description

## `summary` (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 = {
    "advertisers": [
        "nike.com",
        "Shopify"
    ],
    "maxCreativesPerAdvertiser": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("everyotherfriday/google-ads-transparency").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 = {
    "advertisers": [
        "nike.com",
        "Shopify",
    ],
    "maxCreativesPerAdvertiser": 10,
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

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

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/Mi4KbYMmePcOyMmEE/builds/9HZe1zppXe3NbETdR/openapi.json
