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

Scrapes every Google ad your competitors run — Search, Display, Shopping, YouTube, Maps. Multi-domain batch, multi-region, with optional impressions and spend enrichment. No login required.

- **URL**: https://apify.com/logiover/google-ads-transparency-scraper.md
- **Developed by:** [Logiover](https://apify.com/logiover) (community)
- **Categories:** Developer tools, E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 50.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## 🎯 Google Ads Transparency Center Scraper — Multi-Domain, Multi-Region, Impressions & Spend

**Extract every Google ad your competitors are running — across Search, Display, Shopping, YouTube, and Maps — with impressions ranges, regional breakdowns, ad spend tiers, A/B variant URLs, and targeting categories. No login, no cookies, no Google account required.**

This scraper accesses Google's official Ads Transparency Center directly through its internal RPC API — the same endpoints adstransparency.google.com uses for its public-facing site. **Pure HTTP, no browser overhead.** Search by domain, advertiser ID, or brand name. Batch up to 50 competitors per run. Optional detail enrichment unlocks impressions data, regional spend breakdowns, and political ad payer info that most other scrapers miss entirely. **$0.001 per ad scraped.** Free 50 ads per run.

---

### 🚀 Why this scraper beats the alternatives

| Feature | This actor | Most Apify Google Ads scrapers |
|---|---|---|
| Login required | ❌ No | ❌ No (mostly) |
| Multi-domain batch input | ✅ Yes (50+ domains/run) | ⚠️ Single input only |
| Search by advertiser **name** (auto-resolves to ID) | ✅ Yes | ❌ No (manual ID required) |
| Multi-region simultaneous query | ✅ Yes (per-region breakdown) | ⚠️ Usually one region per run |
| Impressions range (min-max) | ✅ Yes | ⚠️ Some |
| **Per-region impressions breakdown** (33+ regions) | ✅ Yes | ❌ Rare |
| Spend tier breakdown | ✅ Yes | ❌ Rare |
| A/B variant URLs (multiple creatives per ad) | ✅ Yes | ❌ No |
| Targeting category extraction | ✅ Yes | ❌ Rare |
| Payer/funder info (political ads) | ✅ Yes | ⚠️ Some |
| Image URL + dimensions extraction | ✅ Yes | ⚠️ Partial |
| Variation count signal | ✅ Yes | ❌ No |
| Advertiser total ad count | ✅ Yes (e.g., "Nike: 10K-20K total") | ❌ No |
| Pure HTTP (no browser overhead) | ✅ Yes | ⚠️ Some use Playwright |
| Auto-deduplication by ad ID | ✅ Yes | ⚠️ Some |
| Price per 1,000 ads | **$1.00** | $1–$5+ |

**Used by:** B2B SaaS competitive intelligence teams, performance marketing agencies, digital ad researchers, ad creative analysts, Brand-watch alternatives, brand protection teams, M&A due-diligence analysts, journalists tracking political ads, e-commerce competitive monitoring tools, paid media auditors, retail intelligence firms, AI ad-generation training data engineers.

---

### 💎 What makes this scraper special — 4 unique angles

Most Google Ads Transparency scrapers give you a list of ads. This one gives you the **complete competitive intelligence picture**:

#### 1. Multi-domain batch input — scrape your entire competitor set in one run
Pass a list of 5, 10, or 50 competitor domains and the scraper extracts ads from all of them in a single run with auto-deduplication. Perfect for weekly competitive monitoring: drop your competitor list once, schedule it, and get a continuously refreshed dataset of every Google ad your category is running. Other scrapers force you to run once per advertiser — slow, expensive, and impractical for category-wide monitoring.

#### 2. Advertiser name auto-resolution — no manual ID hunting
Don't know an advertiser's `AR12345...` Google ID? Just pass their brand name. The scraper queries Google's autocomplete API behind the scenes, picks the highest-ad-count advertiser matching that name, and starts scraping. `"Spotify"` → automatically resolved to `Spotify USA Inc [AR…]`. Other scrapers require you to manually find AR IDs in URLs — a tedious, error-prone step that this actor eliminates.

#### 3. Detail enrichment — the data competitors hide
With `enrichDetails: true`, every ad is enriched with the data Google returns only on its detail page:

- **Impressions range** (e.g., "100,000-125,000")
- **Per-region impressions breakdown** for up to 33 regions (US, DE, FR, JP, BR, IN, etc.) — see exactly where your competitor concentrates spend
- **Spend tier breakdown** (multiple tiers per ad)
- **Active date range** (precise first-shown / last-shown)
- **A/B variant URLs** — 1 to 5+ creative variations per ad
- **Targeting category** (e.g., "Apparel & Accessories", "Finance", "Health")
- **Payer/funder info** (mandatory for political ads)

This data is the *actual* competitive moat — not the ad creatives themselves. Knowing that competitor X spends 70% of their Google budget in Germany, runs 5 creative variants per ad, and targets the "Athletic Wear" category is **strategically far more valuable** than just having a list of ads. Most scrapers don't extract this. Pricier social-listening tools charge $5K-$25K/year for less detail.

#### 4. Advertiser total ad count signal
Every record includes `advertiserTotalAdsMin` and `advertiserTotalAdsMax` — Google's estimate of how many total ads this advertiser has run. Nike: 10K-20K. A small SaaS startup: 100-200. This single field tells you which competitors are spending big on Google Ads vs. running token campaigns. Combine with `variationCount` (how many sizes/A/B variations per ad) for a complete creative volume picture.

---

### 💡 What you can do with this data

#### 1. **Competitive ad spend monitoring**
Track your top 10 competitors' Google Ads activity weekly. Schedule a daily run with your competitor domain list, and you have a continuously refreshed dataset showing which ads are running, in which regions, with what impressions ranges. Spot when competitors launch new campaigns within hours, not weeks.

#### 2. **Creative swipe file building**
Every ad's `imageUrl`, `imageWidth`, `imageHeight`, and `iframeUrl` give you direct access to the actual creative. Build a category-wide swipe file by scraping your top 20 competitors and downloading all their creatives. Perfect for design teams reverse-engineering winning ad formats and visual themes.

#### 3. **Regional ad strategy intelligence**
With `enrichDetails: true`, see exactly where each ad runs. Is your competitor running heavy ads in Germany but ignoring France? Are they testing campaigns in Brazil before US launch? `impressionsRegions` reveals their regional rollout strategy — invaluable for international expansion planning and market entry timing decisions.

#### 4. **Ad spend share-of-voice analysis**
Use `impressionsRange` + `spendRange` to estimate competitor share-of-voice in your category. Aggregate spend across all of a competitor's ads, compare across competitors, and produce a real share-of-voice report — without paying $50K/year for SimilarWeb or Pathmatics.

#### 5. **Lead generation via active advertisers**
Active Google advertisers are warm B2B leads. They have budget, they're acquiring customers online, and they're sophisticated enough to need optimization help. Scrape advertisers in your category, filter by `advertiserTotalAdsMin > 100` (active, not dormant), and you have a qualified prospect list for your agency, SaaS, or service business — ready to enrich with email/phone via Apollo/ZoomInfo.

#### 6. **Political ad monitoring & journalism**
The `payer` field exposes who's funding political ads (mandated by FEC and EU DSA regulations). Track political committees, PACs, and dark-money campaigns. Run a weekly scrape across known political advertiser IDs and produce real-time accountability reports. Used by journalists at major outlets and academic election researchers.

#### 7. **Ad targeting category research**
The `targetingCategory` field tells you which audience taxonomy Google placed each ad in (Clothing, Finance, Travel, Health, etc.). Research how competitors are categorized, find opportunities where the category leader has under-invested, and inform your own keyword/audience strategy.

#### 8. **Brand protection and trademark enforcement**
Monitor for unauthorized use of your brand name in competitor Google Ads. Schedule a daily scrape with your trademark as a search query, get alerts when new ads matching your brand appear from advertisers other than you. Critical for franchise networks, luxury brands, and direct-to-consumer companies fighting trademark infringement.

#### 9. **AI training data for ad generation models**
Building an AI tool that generates Google ad creatives? This scraper assembles a clean structured corpus: image URLs, dimensions, advertiser metadata, targeting category, format, and engagement signals (variationCount). Perfect for fine-tuning multimodal ad-creative generation models or RAG pipelines focused on performance marketing copy.

#### 10. **M&A due diligence on ad-spend behavior**
Evaluating an acquisition target? Their Google ad activity is a leading indicator of marketing maturity. `advertiserTotalAdsMin/Max` reveals scale, `impressionsRegions` reveals geographic strategy, `variantUrls` reveals creative testing sophistication. Use the scraper to produce diligence reports on private targets in 30 minutes — work that previously cost $5K-15K from market research firms.

---

### 📦 Output fields

Every ad record includes:

#### Core fields (always populated)

| Field | Type | Description | Example |
|-------|------|-------------|---------|
| `adId` | string | Google creative ID | `"CR17123085163681546241"` |
| `advertiserId` | string | Google advertiser ID (AR-prefixed) | `"AR18378488041124659201"` |
| `advertiserName` | string | Advertiser display name | `"Nike Retail BV"` |
| `advertiserDomain` | string | Verified advertiser website | `"nike.com"` |
| `format` | string | Creative format inferred from preview | `"IMAGE"`, `"VIDEO"`, `"DISPLAY"`, `"TEXT"` |
| `surface` | string | Google ad surface (Search/Display/Shopping) | `"SEARCH"`, `"DISPLAY"`, `"SHOPPING"` |
| `imageUrl` | string | Direct CDN image URL (downloadable) | `"https://tpc.googlesyndication.com/archive/simgad/..."` |
| `imageWidth` | integer | Banner width in pixels | `380` |
| `imageHeight` | integer | Banner height in pixels | `283` |
| `imageHtml` | string | Raw HTML img tag from Google | `"<img src=\"...\" height=\"283\" width=\"381\">"` |
| `iframeUrl` | string | Rich-media iframe URL (when applicable) | `"https://displayads-formats.googleusercontent.com/..."` |
| `previewUrl` | string | Best-available preview (image or iframe) | (combined view of imageUrl/iframeUrl) |
| `variationCount` | integer | Number of size/A/B variations Google has cataloged | `1255` |
| `firstShown` | string | First-shown date (ISO YYYY-MM-DD) | `"2025-11-01"` |
| `lastShown` | string | Last-shown date (ISO YYYY-MM-DD) | `"2026-05-07"` |
| `advertiserTotalAdsMin` | string | Lower bound of advertiser's total ad count | `"10000"` |
| `advertiserTotalAdsMax` | string | Upper bound of advertiser's total ad count | `"20000"` |

#### Detail-enrichment fields (populated only when `enrichDetails: true`)

| Field | Type | Description | Example |
|-------|------|-------------|---------|
| `variantUrls` | array | A/B variant iframe URLs (1-5 typical) | `["https://displayads-formats..."]` |
| `targetingCategory` | object | Google's audience taxonomy classification | `{ code: 166, name: "Apparel & Accessories", surface: 1 }` |
| `impressionsRange` | object | Total impressions range | `{ min: "8000", max: "9000" }` |
| `impressionsRegions` | array | Per-region impressions breakdown | `[{ regionCode: 2792, impressionsMin: "15000", impressionsMax: "20000", lastShown: "...", firstShown: "..." }, ...]` |
| `spendRange` | array | Spend tier breakdown | `[{ tier: 4, min: null, max: "1000" }, ...]` |
| `firstShownDetailed` | string | Precise first-shown date from detail | `"2023-03-01"` |
| `lastShownDetailed` | string | Precise last-shown date from detail | `"2026-05-07"` |
| `payer` | string | Funder/payer (political ads, regulated categories) | `"Nike Retail BV"` |
| `detailFormatCode` | integer | Raw format code from detail endpoint | `1` |

#### Search context (always populated)

| Field | Description |
|-------|-------------|
| `searchedDomain` | The domain that produced this record |
| `searchedAdvertiser` | The advertiser ID that produced this record (if any) |
| `searchedRegions` | The numeric region codes used in the search |
| `searchedFormat` | Format filter that produced this record (if any) |
| `scrapedAt` | ISO timestamp when scraped |

---

### ⚙️ Input configuration

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `mode` | string | `"domain"` | Search strategy: `"domain"` (lookup by website), `"advertiser-id"` (direct AR ID), `"advertiser-name"` (text search → auto-resolves to AR ID) |
| `domains` | array | `["nike.com"]` | For `mode="domain"`. List of competitor domains. Pass 1 to 50+ domains in batch. No `www.` or `https://`. |
| `advertiserIds` | array | `[]` | For `mode="advertiser-id"`. List of `AR…` Google advertiser IDs. |
| `advertiserNames` | array | `[]` | For `mode="advertiser-name"`. Brand names — auto-resolved to top-matching AR ID via Google autocomplete. |
| `regions` | array | `["anywhere"]` | ISO 3166-1 alpha-2 country codes (US, GB, DE, FR, TR, BR, IN, JP, etc.). `anywhere` = no regional filter. ~120 countries supported. Multiple regions act as OR filter. |
| `creativeFormats` | array | `[]` | Filter by ad format. Empty = all formats. Pass any combination of `TEXT`, `IMAGE`, `VIDEO`. Multiple formats = separate searches per format, results merged. |
| `maxAdsPerTarget` | integer | `200` | Cap ads PER advertiser/domain. Useful when batch-scraping many competitors — keeps cost predictable. `0` = unlimited per target. |
| `maxAds` | integer | `5000` | Total ad cap across ALL targets. Hard ceiling. `0` = unlimited. |
| `enrichDetails` | boolean | `false` | When `true`, fetches each ad's detail page for impressions ranges, per-region breakdown, spend tiers, variant URLs, targeting category, and payer info. **Doubles cost and run time but unlocks the most valuable competitive intelligence data.** |

---

### 💡 Example inputs

#### Single competitor — quick recon
```json
{
  "mode": "domain",
  "domains": ["nike.com"],
  "regions": ["US"],
  "maxAdsPerTarget": 100
}
````

Returns Nike's top 100 US ads in ~30 seconds. ~$0.10. Fastest sanity check.

#### Batch competitor monitoring — 10 brands at once

```json
{
  "mode": "domain",
  "domains": [
    "nike.com", "adidas.com", "puma.com", "newbalance.com",
    "reebok.com", "underarmour.com", "asics.com", "lululemon.com",
    "alo.com", "vuori.com"
  ],
  "regions": ["US"],
  "maxAdsPerTarget": 50,
  "maxAds": 500
}
```

Captures 500 ads across the entire athletic-wear category in one run. Schedule weekly for ongoing competitive monitoring. ~$0.50.

#### Deep competitive intelligence — full enrichment on key competitor

```json
{
  "mode": "domain",
  "domains": ["spotify.com"],
  "regions": ["US", "DE", "GB", "BR", "JP"],
  "maxAdsPerTarget": 100,
  "enrichDetails": true
}
```

Returns 100 Spotify ads with full enrichment: per-region impressions in 5 markets, spend tiers, variant URLs, targeting categories. Strategic-grade intel. ~$0.20 + extended runtime.

#### Advertiser-name mode — when you don't know the AR ID

```json
{
  "mode": "advertiser-name",
  "advertiserNames": ["Airbnb", "Booking.com", "Expedia", "Kayak"],
  "regions": ["US"],
  "maxAdsPerTarget": 50
}
```

Auto-resolves each brand name to its Google advertiser ID, then scrapes. No manual ID hunting needed.

#### Format-filtered scrape — only video ads

```json
{
  "mode": "domain",
  "domains": ["redbull.com"],
  "regions": ["anywhere"],
  "creativeFormats": ["VIDEO"],
  "maxAdsPerTarget": 200
}
```

Returns only Red Bull's video Google ads (YouTube In-Stream + Discovery). For brand creative research focused on video specifically.

#### Multi-region political ad audit

```json
{
  "mode": "advertiser-id",
  "advertiserIds": [
    "AR12345678901234567890",
    "AR98765432109876543210"
  ],
  "regions": ["US"],
  "maxAdsPerTarget": 500,
  "enrichDetails": true
}
```

Targeted political-ad-payer audit. Captures full advertiser ad inventory with payer info, regional breakdown, and spend ranges. Used by journalism teams.

#### Direct-response e-commerce intelligence

```json
{
  "mode": "domain",
  "domains": [
    "wayfair.com", "ikea.com", "westelm.com", "cb2.com",
    "potterybarn.com", "crateandbarrel.com", "anthropologie.com"
  ],
  "regions": ["US"],
  "creativeFormats": ["IMAGE", "VIDEO"],
  "maxAdsPerTarget": 75,
  "enrichDetails": true
}
```

Home furnishings competitive intelligence with full detail. Spend, regions, creative variations across 7 competitors.

***

### 📊 Output sample

```json
{
  "adId": "CR17123085163681546241",
  "advertiserId": "AR18378488041124659201",
  "advertiserName": "Nike Retail BV",
  "advertiserDomain": "nike.com",
  "format": "IMAGE",
  "surface": "SEARCH",
  "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/2409984125063596607",
  "imageWidth": 381,
  "imageHeight": 283,
  "imageHtml": "<img src=\"https://tpc.googlesyndication.com/archive/simgad/2409984125063596607\" height=\"283\" width=\"381\">",
  "iframeUrl": null,
  "previewUrl": "https://tpc.googlesyndication.com/archive/simgad/2409984125063596607",
  "variationCount": 173,
  "firstShown": "2025-11-01",
  "lastShown": "2026-05-07",
  "variantUrls": [
    "https://displayads-formats.googleusercontent.com/ads/preview/content.js?client=ads-integrity-transparency&obfuscatedCustomerId=..."
  ],
  "targetingCategory": {
    "code": 166,
    "name": "Apparel & Accessories",
    "surface": 1
  },
  "impressionsRange": { "min": "8000", "max": "9000" },
  "impressionsRegions": [
    { "regionCode": 2792, "impressionsMin": "15000", "impressionsMax": "20000", "lastShown": "2026-05-07", "firstShown": "2023-03-01" },
    { "regionCode": 2840, "impressionsMin": null, "impressionsMax": null, "lastShown": "2026-05-06", "firstShown": null },
    { "regionCode": 2276, "impressionsMin": null, "impressionsMax": "1000", "lastShown": "2026-05-05", "firstShown": "2023-03-01" }
  ],
  "spendRange": [
    { "tier": 4, "min": null, "max": "1000" },
    { "tier": 3, "min": "6000", "max": "7000" }
  ],
  "firstShownDetailed": "2023-03-01",
  "lastShownDetailed": "2026-05-07",
  "payer": "Nike Retail BV",
  "advertiserTotalAdsMin": "10000",
  "advertiserTotalAdsMax": "20000",
  "searchedDomain": "nike.com",
  "searchedRegions": [2840],
  "scrapedAt": "2026-05-07T16:13:53.780Z"
}
```

***

### 💰 Pricing

Pay-per-event model. **You pay only for ads actually saved** — deduplicated, filtered, and ready to use.

| Volume | Estimated cost |
|--------|---------------|
| 50 ads | **FREE** (every run) |
| 100 ads | $0.05 |
| 500 ads | $0.45 |
| 1,000 ads | $0.95 |
| 5,000 ads | $4.95 |
| 10,000 ads | $9.95 |
| 50,000 ads | $49.95 |

Detail enrichment (`enrichDetails: true`) doubles the per-ad cost since each ad requires a second API call.

| Subscription tier | Effective price per 1,000 ads |
|---|---|
| Free / Starter | $1.00 |
| Bronze | $0.90 |
| Silver | $0.80 |
| Gold | $0.65 |

**Cost comparison vs alternatives:**

- This scraper at scale: **$50 for 50,000 ads with full enrichment**
- Pathmatics: **$2,000–$8,000/month** for similar competitive ad data
- AdBeat: **$500–$3,000/month** for less-detailed Google ad coverage
- SimilarWeb Ads Intelligence: **$1,500+/month** for category-level data
- Manual research: **80+ hours** of analyst time for one competitor's ad inventory

***

### ⚡ Performance

- **Pure HTTP, no browser** — direct JSON-RPC API calls. 10× faster than Playwright-based scrapers, runs in 256 MB memory.
- **No login or cookies** — Google Ads Transparency Center is a fully public regulatory tool.
- **No proxy required** for most workloads — Apify Datacenter proxy is sufficient. Add Residential for very high-volume runs.
- **40 ads per page** with full advertiser metadata.
- **Throughput**: ~1,500-3,000 ads per minute (without enrichment), ~300-600 with enrichment.
- **Auto-deduplication** by `adId` — same ad appearing across multiple regions or surfaces is counted once.
- **Anti-block**: realistic Chrome desktop browser fingerprint, polite request spacing (500ms between pages, 250ms between detail calls), automatic 429/403 detection with friendly errors.
- **Multi-domain batch input** — process 50+ competitors in a single run with shared session.
- **Stable selectors** — uses Google's stable RPC endpoints, not fragile DOM selectors. Survives UI redesigns.

***

### 🔗 Integrations

Export as **JSON**, **CSV**, **Excel**, or **XML**. Connect via:

- **Zapier / Make / n8n** — auto-add new competitor ads to Slack, Notion, or Airtable
- **Google Sheets** — live competitive ad dashboard, refreshed weekly via Apify Schedules
- **Slack / Discord** — daily digest of new ads in your competitive set
- **REST API** — programmatic access from Python, Node.js, any language
- **Airtable / Notion** — visual creative swipe file for design teams
- **LangChain / LlamaIndex** — feed ad metadata into RAG pipelines for AI ad-generation tools
- **HubSpot / Salesforce** — enrich account records with competitor advertising activity
- **Apollo / Outreach / SalesLoft** — feed active advertisers into B2B prospect sequencer
- **BigQuery / Snowflake / PostgreSQL** — data warehouse for share-of-voice analytics
- **Looker / Tableau / Power BI** — competitive intelligence dashboards
- **Webhooks** — push every new ad to your backend in real time
- **MCP (Model Context Protocol)** — usable by Claude, ChatGPT, and other AI assistants for natural-language competitive research

***

### 🆚 Google Ads Transparency Scraper vs alternatives

#### vs Google Ads Transparency Center (the website)

The native `adstransparency.google.com` interface is great for ad-hoc research but offers no bulk export, no batch competitor input, no scheduled monitoring, no programmatic access. This scraper turns the same public regulatory data into a queryable, exportable, automatable feed — without violating Google's terms.

#### vs Google Ads API

Google's official Ads API only returns YOUR OWN ad data (or your clients' ads if you have manager access). It does not give you competitor ad data — that's specifically what the Transparency Center publishes. This scraper is the only programmatic path to competitor ad intelligence on Google.

#### vs Pathmatics, AdBeat, SimilarWeb Ads Intelligence

Enterprise competitive ad intelligence platforms cost **$1,500-$8,000/month** with annual contracts. They aggregate data from many sources (Facebook, Google, programmatic display), but their Google coverage often lags Google's own Transparency Center by days. This scraper delivers fresher Google data at pay-per-result pricing — typically 30-100× cheaper for Google-specific intelligence.

#### vs SpyFu, SEMrush, iSpionage (PPC keyword tools)

These tools focus on PPC keyword bidding intelligence. They don't extract creative content, image URLs, ad variations, or per-region impressions. Use them for keyword strategy; use this scraper for creative-strategy and spend-pattern intelligence — they're complementary.

#### vs other Apify Google Ads scrapers

There are 10+ Google Ads Transparency scrapers on Apify. Most extract only the basic creative list. **This scraper is the only one that combines:** (1) multi-domain batch input, (2) advertiser-name auto-resolution, (3) detail enrichment with per-region impressions and spend tiers, (4) advertiser total-ad-count signal. Feature comparison from real-world testing:

| Feature | This actor | Most competitors |
|---|---|---|
| Multi-domain batch in one run | ✅ Up to 50+ | ❌ Single input |
| Auto-resolve brand name to AR ID | ✅ Yes | ❌ Manual ID required |
| Per-region impressions breakdown | ✅ 33+ regions | ❌ Total only or none |
| Spend tier breakdown | ✅ Yes | ❌ Rare |
| A/B variant URLs extracted | ✅ Yes | ❌ Single URL |
| Image URL + dimensions | ✅ Yes | ⚠️ Partial |
| Targeting category | ✅ Yes | ❌ Rare |
| Advertiser total ad count signal | ✅ Yes | ❌ No |
| Full README with use cases | ✅ Yes | ⚠️ Often minimal |
| Pure HTTP (256 MB memory) | ✅ Yes | ⚠️ Some use Playwright |

#### vs Facebook Ad Library Scraper

Facebook and Google ad ecosystems are complementary — most brands run on both. This scraper is the **Google equivalent** of Facebook Ad Library scrapers. Pair them for full ad-spend visibility across the two largest digital ad platforms.

***

### ❓ Frequently asked questions

#### Does this require a Google account or login?

**No.** Google Ads Transparency Center is a fully public regulatory transparency tool — no login, cookies, session, or account required. Your Google account is never involved in any way. The scraper accesses pages anyone can view in an incognito browser.

#### Is this legal?

The Google Ads Transparency Center is **mandated by EU Digital Services Act (DSA) and similar regulations** to provide public ad transparency. Google publishes this data explicitly for public, automated, programmatic access by researchers, journalists, and competitive intelligence teams. You are responsible for complying with applicable privacy laws (GDPR, CCPA) when processing the scraped data, but the data itself is regulatory-mandated public information.

#### What ad formats does this support?

All Google ad formats: **Search text ads, Display image banners, Display video, Discovery, YouTube In-Stream, YouTube Bumper, Shopping product ads, Maps Local Search ads, Play Store ads.** Format detection is automatic; you can also filter to specific formats with `creativeFormats`.

#### What's the difference between `format` and `surface`?

- `format` = creative format type (TEXT, IMAGE, VIDEO, DISPLAY)
- `surface` = where the ad is shown (SEARCH, DISPLAY, SHOPPING)

A single Google ad can have an image creative (format=IMAGE) but be shown on Google Search results pages (surface=SEARCH). Both fields are independently useful.

#### What does `advertiserTotalAdsMin/Max` mean?

This is Google's estimate of the advertiser's total active and historical ad inventory in the selected region. Nike Inc returns "10000-20000" — meaning Nike has ~10K-20K ads cataloged in Google's transparency database for that region. A small startup might return "100-200". This single field tells you which competitors are spending big vs. running token campaigns.

#### What does `variationCount` mean?

Field 13 in Google's response — observed values 100-2000+. We believe this represents the count of size/A/B variations Google has cataloged for this creative. A creative with `variationCount: 1255` has been served in 1,255 different size combinations or A/B variants. Higher numbers indicate sophisticated multivariate testing.

#### How accurate is the `impressionsRange` data?

Google reports impressions in **bucketed ranges** (e.g., "10,000-20,000"), not exact numbers. This is intentional — Google obscures exact figures for advertiser privacy while providing useful order-of-magnitude data. The ranges are accurate within their stated bounds.

#### How many regions are supported?

\~120 countries via ISO 3166-1 alpha-2 codes (US, GB, DE, FR, TR, BR, IN, JP, AU, CA, MX, ES, IT, NL, SE, NO, DK, FI, PL, RU, CN, KR, SG, HK, TW, MY, TH, ID, PH, VN, AE, SA, IL, ZA, NG, EG, KE, AR, CL, CO, PE, etc.). Pass `["anywhere"]` for global ads with no regional filter.

#### Why is `targetingCategory` sometimes null?

Google only attaches a targeting category to certain ad formats (most commonly Display and YouTube). Search text ads and Shopping ads typically don't have a category attached. When the field is null, Google didn't return one — not a scraping error.

#### Why is `impressionsRange` sometimes null but `impressionsRegions` is populated?

Some ads don't have aggregate impression data, only per-region data. The detail endpoint's response varies by ad. Always check both fields — `impressionsRegions` is often more granular and useful.

#### Can I get the actual ad creative file (the image/video)?

Yes. `imageUrl` is a direct CDN URL pointing to the actual image (`https://tpc.googlesyndication.com/archive/simgad/...`). You can download these files with a simple HTTP GET in a follow-up step. For video ads, the `iframeUrl` renders the actual video creative when loaded in a browser.

#### Can I monitor ads continuously?

Yes — schedule the scraper via Apify Schedules (every hour/day/week). Use `maxAds` and `maxAdsPerTarget` to control cost. Combine with webhooks to push new ads to Slack/Discord/email instantly when detected.

#### What if Google rate-limits me?

The scraper handles 429 responses gracefully with friendly error messages. For very high-volume runs (10,000+ ads per session with enrichment), enable Apify's Residential proxy. For most users, free Datacenter proxy is sufficient. Built-in 500ms inter-page delay and 250ms inter-detail delay keep you well under Google's anonymous tolerance threshold.

#### Can I integrate with Make / Zapier / n8n?

**Yes.** All three platforms have native Apify integrations. Set up webhooks on run completion or poll the dataset via the Apify API. Common automations: new competitor ads → Slack alert, ads above 10K impressions → Airtable, political ads from new payers → email digest.

#### Is the output AI-ready / RAG-friendly?

**Yes.** Output is clean structured JSON with consistent field types. Each ad is a self-contained document with image URL + advertiser metadata + targeting + spend signals. Ideal for vector databases (Pinecone, Weaviate, Chroma) and RAG pipelines (LangChain, LlamaIndex). Use `imageUrl` for multimodal embedding, `advertiserName` + `targetingCategory` as filter metadata.

#### What's the rate of completeness for fields?

- `adId`, `advertiserId`, `advertiserName`, `advertiserDomain`: 100%
- `format`, `surface`, `firstShown`, `lastShown`: ~99%
- `imageUrl`, `imageWidth`, `imageHeight`: ~70-80% (only for ads with rendered image creatives)
- `iframeUrl`: ~10-20% (only for rich-media display ads)
- `variationCount`, `advertiserTotalAdsMin/Max`: ~99%
- `targetingCategory`: ~30-50% with enrichment (Google attaches selectively)
- `impressionsRange`, `impressionsRegions`: ~85% with enrichment
- `spendRange`: ~70% with enrichment
- `payer`: ~95% for political ads, ~10% for commercial ads (only when Google requires disclosure)

#### Can I use this for political ad accountability research?

**Yes — this is one of the scraper's core use cases.** Google is mandated to disclose payer/funder info for political ads. The `payer` field captures this directly. Use `enrichDetails: true` for full impressions and spend tier data. Used by journalism organizations and academic election researchers.

#### Why does the scraper sometimes return fewer ads than expected?

Google's transparency center has rate-limits per session and may throttle very deep pagination. Most advertisers cap out at a few hundred to a few thousand ads visible per region. If you see fewer ads than expected:

1. Try without region filter (`regions: ["anywhere"]`)
2. Try different surface filters
3. Check `advertiserTotalAdsMax` — if Google says the advertiser has fewer ads than your `maxAdsPerTarget`, you've hit the natural ceiling

#### Can I scrape multiple advertisers concurrently to go faster?

The scraper processes targets sequentially by default to be polite with Google's infrastructure. For very high-volume needs (10+ competitors, 1000+ ads each), contact the actor author for a parallel-processing variant.

#### What payment methods does Apify support?

Credit card, invoicing for enterprise, and platform credits. New users get **$5 free credits** monthly — enough to scrape ~5,000 ads for free. No credit card required to start.

***

### ⚖️ Legal & Compliance

This scraper accesses **only publicly available regulatory transparency data** from Google's Ads Transparency Center — content explicitly published by Google for public discovery, regulatory compliance (EU DSA, FEC), and journalist/researcher access. No private user data is accessed. No login or authentication is performed. No internal Google API is exploited.

**You are responsible** for ensuring your specific use of the scraped data complies with:

- **Google's Terms of Service** for the Transparency Center
- **GDPR** (EU/UK) — lawful basis for processing personal data of EU/UK individuals
- **CCPA** (California) — consumer rights for CA residents
- **Local data protection laws** in any jurisdiction where you operate or where data subjects reside
- **FEC and political-advertising disclosure laws** for any political-ad analysis use case
- **Anti-spam laws** — CAN-SPAM (US), CASL (Canada), GDPR consent (EU) for any outreach use

This scraper is a **general-purpose tool**. The actor author and Apify provide no warranty regarding the legality of any specific use case. When in doubt, consult legal counsel.

**Not affiliated with Google LLC or Alphabet Inc.** Google®, Google Ads®, and YouTube® are registered trademarks of Google LLC. All trademarks belong to their respective owners.

***

### 🛠️ Technical details

- **Endpoints used**:
  - `POST /anji/_/rpc/SearchService/SearchCreatives` — main ad list
  - `POST /anji/_/rpc/SearchService/SearchSuggestions` — advertiser name autocomplete
  - `POST /anji/_/rpc/LookupService/GetCreativeById` — detail enrichment
- **Method**: JSON-RPC over POST with URL-encoded form data; response is compact protobuf-style JSON with numeric keys
- **Authentication**: None. Anonymous public access.
- **Headers**: Realistic Chrome desktop browser fingerprint
- **Pagination**: Cursor-token-based, 40 ads per page
- **Region encoding**: Internal Google numeric codes (`2{ISO 3166-1 numeric}`, e.g., 2840 = US, 2792 = TR, 2826 = GB) — auto-converted by the scraper from user-friendly ISO alpha-2 input
- **Rate limiting**: 500ms inter-page delay, 250ms inter-detail delay — well under Google's anonymous threshold
- **Concurrency**: Sequential by default
- **Memory**: Runs comfortably in 256 MB
- **Tech stack**: Apify SDK v3, Crawlee v3, Node.js 20+, native fetch (no axios/got dependency)

***

### 🚦 Getting started in 30 seconds

1. **Click "Try for free"** on this actor's page
2. **Set `mode: "domain"` and pick a competitor** (e.g., `nike.com`, `airbnb.com`, your own competitor)
3. **Optional**: Add multiple regions (`["US", "GB", "DE"]`) or enable `enrichDetails: true` for the full intelligence picture
4. **Click "Start"**
5. **Wait ~30-60 seconds** for the first 50-200 ads
6. **Download** as JSON / CSV / Excel from the Storage tab

No credit card required. First 50 ads per run are always free. Paid usage starts after that, billed monthly via Apify.

***

### 💬 Support

- **Issues / feature requests**: Open a ticket in the **Issues** tab on this actor's page
- **Custom scraping needs**: Contact the actor author for tailored solutions
- **General Apify support**: [help.apify.com](https://help.apify.com)

***

### 🔍 Search keywords

Google Ads Transparency Center scraper, Google Ads scraper, Google Ad Library scraper, Google ad data extractor, scrape Google ads, Google ad spy tool, Google PPC competitor analysis, Google Display ad scraper, YouTube ad scraper, Google Search ad scraper, Google Shopping ad scraper, Google ad creative library, Google ad spy, Google ad intelligence, Google ad monitoring, Google competitor ad tracker, Google ad transparency API, Google Ads Transparency Center API, Google ad bulk export, Google ad CSV export, Google ad JSON export, Google advertiser scraper, Google AR ID scraper, Google ad creative download, Google ad image extractor, Google video ad scraper, Google ad impressions data, Google ad spend tracker, Google ad spend estimator, Google ad regional data, Google political ad scraper, Google FEC ad scraper, Google EU DSA ad data, Google ad payer info, Google ad funder data, Google ad targeting category, Google ad first shown date, Google ad last shown date, competitive Google ads, B2B Google ad spy, ecommerce Google ad spy, Pathmatics alternative, AdBeat alternative, SpyFu alternative, SimilarWeb Ads Intelligence alternative, Google ad share of voice, Google ad creative swipe file, Google ad benchmarking, Google ad category research, Google ad market research, Google ad competitor analysis tool, Google ad batch scraper, Google ad multi-domain scraper, Google ad multi-region scraper, no login Google ad scraper, anonymous Google ad scraper, Google ad pure HTTP scraper, Google ad RPC API, Google Ads Transparency Center direct API, Google ad data for AI training, Google ad RAG dataset, Google ad LLM corpus.

***

**Ready to map your competitors' Google Ads strategy?** Hit "Try for free" above. First 50 ads on us. No credit card. No login. No risk.

# Actor input Schema

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

How to identify the advertiser(s) to scrape. 'domain' = look up by website domain (most common). 'advertiser-id' = direct AR-prefixed ID input. 'advertiser-name' = text search resolved to ID via Google's autocomplete.

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

For mode='domain'. List of advertiser website domains. The scraper supports BATCH input — pass 1 to 50+ domains in a single run. Example: \['nike.com', 'adidas.com', 'puma.com']. No www. or https://.

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

For mode='advertiser-id'. List of Google advertiser IDs (AR-prefixed). Find them in advertiser detail page URLs: adstransparency.google.com/advertiser/AR12345...

## `advertiserNames` (type: `array`):

For mode='advertiser-name'. List of brand/company names. The scraper resolves each name to its top-matching advertiser ID via Google's autocomplete, then scrapes that advertiser's ads. Useful when you don't know the exact AR ID or domain.

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

ISO 3166-1 alpha-2 country codes (e.g., US, GB, DE, FR, TR, BR, IN, JP). Pass 'anywhere' to skip regional filter and get global ads. Multiple regions act as OR filter. ~120 countries supported.

## `creativeFormats` (type: `array`):

Filter by ad creative format. Empty = all formats. Pass any combination of TEXT, IMAGE, VIDEO. When multiple formats are specified, the scraper runs separate searches per format and merges results.

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

Cap how many ads to return PER advertiser/domain. Useful when batch-scraping many competitors — keeps cost predictable. Set to 0 for unlimited per target.

## `maxAds` (type: `integer`):

Total ad count cap across ALL targets. Hard ceiling — when reached, the run stops regardless of remaining targets. Set to 0 for unlimited.

## `enrichDetails` (type: `boolean`):

When enabled, fetches each ad's detail page for richer fields: impressions range (min-max), regional impression breakdown, targeting category (e.g., 'Clothing & Accessories'), spend tier, A/B variant URLs, payer info (for political ads). Doubles cost and run time but unlocks the most valuable competitive intelligence data.

## Actor input object example

```json
{
  "mode": "domain",
  "domains": [
    "nike.com"
  ],
  "advertiserIds": [],
  "advertiserNames": [],
  "regions": [
    "anywhere"
  ],
  "creativeFormats": [],
  "maxAdsPerTarget": 200,
  "maxAds": 5000,
  "enrichDetails": false
}
```

# Actor output Schema

## `adId` (type: `string`):

No description

## `advertiserId` (type: `string`):

No description

## `advertiserName` (type: `string`):

No description

## `advertiserDomain` (type: `string`):

No description

## `format` (type: `string`):

No description

## `previewUrl` (type: `string`):

No description

## `firstShown` (type: `string`):

No description

## `lastShown` (type: `string`):

No description

## `targetingCategory` (type: `string`):

No description

## `impressionsRange` (type: `string`):

No description

## `spendRange` (type: `string`):

No description

## `payer` (type: `string`):

No description

## `scrapedAt` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("logiover/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 = {}

# Run the Actor and wait for it to finish
run = client.actor("logiover/google-ads-transparency-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call logiover/google-ads-transparency-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=logiover/google-ads-transparency-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Google Ads Transparency Center Scraper",
        "description": "Scrapes every Google ad your competitors run — Search, Display, Shopping, YouTube, Maps. Multi-domain batch, multi-region, with optional impressions and spend enrichment. No login required.",
        "version": "0.0",
        "x-build-id": "CJlDNkm1h1ojIt604"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/logiover~google-ads-transparency-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-logiover-google-ads-transparency-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/logiover~google-ads-transparency-scraper/runs": {
            "post": {
                "operationId": "runs-sync-logiover-google-ads-transparency-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/logiover~google-ads-transparency-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-logiover-google-ads-transparency-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "mode": {
                        "title": "Search Mode",
                        "enum": [
                            "domain",
                            "advertiser-id",
                            "advertiser-name"
                        ],
                        "type": "string",
                        "description": "How to identify the advertiser(s) to scrape. 'domain' = look up by website domain (most common). 'advertiser-id' = direct AR-prefixed ID input. 'advertiser-name' = text search resolved to ID via Google's autocomplete.",
                        "default": "domain"
                    },
                    "domains": {
                        "title": "Advertiser Domains",
                        "type": "array",
                        "description": "For mode='domain'. List of advertiser website domains. The scraper supports BATCH input — pass 1 to 50+ domains in a single run. Example: ['nike.com', 'adidas.com', 'puma.com']. No www. or https://.",
                        "default": [
                            "nike.com"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "advertiserIds": {
                        "title": "Advertiser IDs",
                        "type": "array",
                        "description": "For mode='advertiser-id'. List of Google advertiser IDs (AR-prefixed). Find them in advertiser detail page URLs: adstransparency.google.com/advertiser/AR12345...",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "advertiserNames": {
                        "title": "Advertiser Names",
                        "type": "array",
                        "description": "For mode='advertiser-name'. List of brand/company names. The scraper resolves each name to its top-matching advertiser ID via Google's autocomplete, then scrapes that advertiser's ads. Useful when you don't know the exact AR ID or domain.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "regions": {
                        "title": "Regions",
                        "type": "array",
                        "description": "ISO 3166-1 alpha-2 country codes (e.g., US, GB, DE, FR, TR, BR, IN, JP). Pass 'anywhere' to skip regional filter and get global ads. Multiple regions act as OR filter. ~120 countries supported.",
                        "default": [
                            "anywhere"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "creativeFormats": {
                        "title": "Ad Formats",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Filter by ad creative format. Empty = all formats. Pass any combination of TEXT, IMAGE, VIDEO. When multiple formats are specified, the scraper runs separate searches per format and merges results.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "TEXT",
                                "IMAGE",
                                "VIDEO"
                            ]
                        },
                        "default": []
                    },
                    "maxAdsPerTarget": {
                        "title": "Max Ads Per Target",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Cap how many ads to return PER advertiser/domain. Useful when batch-scraping many competitors — keeps cost predictable. Set to 0 for unlimited per target.",
                        "default": 200
                    },
                    "maxAds": {
                        "title": "Max Ads (Global)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Total ad count cap across ALL targets. Hard ceiling — when reached, the run stops regardless of remaining targets. Set to 0 for unlimited.",
                        "default": 5000
                    },
                    "enrichDetails": {
                        "title": "Enrich With Detail Data",
                        "type": "boolean",
                        "description": "When enabled, fetches each ad's detail page for richer fields: impressions range (min-max), regional impression breakdown, targeting category (e.g., 'Clothing & Accessories'), spend tier, A/B variant URLs, payer info (for political ads). Doubles cost and run time but unlocks the most valuable competitive intelligence data.",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
