# Google Ads Transparency Scraper - Competitor Ads

> Scrape Google Ads Transparency Center creatives by advertiser name, AR ID, domain or URL: ad text (headline/description), images, YouTube videos, regions, impression ranges, platforms and first/last shown dates. Monitoring mode detects new and stopped ads. Fast HTTP, no browser.

- Category: Domain & website intelligence
- Price: $1.50 per 1,000 × ad result, billed per result by Apify (no subscription); any other billed events are listed on the Store page. Cap any run with `maxTotalChargeUsd`.
- Store page: https://apify.com/wrenfield-data/google-ads-transparency-scraper
- Human page: https://wrenfielddata.com/tools/google-ads-transparency-scraper/
- OpenAPI 3 spec: https://api.apify.com/v2/acts/wrenfield-data~google-ads-transparency-scraper/builds/default/openapi.json
- MCP tool: https://mcp.apify.com?tools=wrenfield-data/google-ads-transparency-scraper (appears as `wrenfield-data--google-ads-transparency-scraper`)

## Call it

Synchronous run that returns the dataset rows as JSON (use `/runs` for long jobs and poll; see the OpenAPI spec):

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/wrenfield-data~google-ads-transparency-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"targets": ["Nike"], "maxAdsPerTarget": 5, "region": "anywhere", "includeDetails": true, "extractAdText": true, "ocrTextAds": true, "ocrLanguage": "auto", "advertiserSummary": true, "maxAdvertisersPerName": 1, "monitorMode": false, "monitorStoreName": "google-ads-transparency-monitor", "activeWithinDays": 7, "emitBaselineOnFirstRun": true, "proxyConfiguration": {"useApifyProxy": true}, "residentialFallback": true, "maxConcurrency": 8, "dataForSeoFallback": false}'
```

## Input

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `targets` | array | yes | `["Nike"]` | One per line. Accepts: an advertiser name (Nike), an advertiser ID (AR16735076323512287233), a website domain (grammarly.com - returns every advertiser running ads for that site), or any Ads Transparency Center URL (advertiser page, single creative page, or a domain search; filters in the URL such as region, platform, format and dates are respected). |
| `maxAdsPerTarget` | integer |  | `50` | How many ad creatives to return for each target, newest (most recently shown) first. Big brands have thousands of ads. |
| `region` | string |  | `"anywhere"` | Only ads shown in this country. Anywhere = all regions. |
| `lastDays` | integer |  |  | Only ads shown at least once in the last N days (e.g. 30). Overrides the date range below. |
| `dateFrom` | string |  |  | Only ads shown on or after this date (YYYY-MM-DD). Data starts in 2018. |
| `dateTo` | string |  |  | Only ads shown on or before this date (YYYY-MM-DD). Default: today. |
| `formats` | array |  |  | Leave empty for all formats. |
| `platforms` | array |  |  | Leave empty for all platforms (this also includes Display-network ads, which have no separate filter in the Transparency Center). |
| `includeDetails` | boolean |  | `true` | Open each ad's detail record: every region it ran in with first/last shown dates, impression ranges and per-platform breakdown (impressions and platforms are published for EU/EEA regions), topic and targeting categories. Turn off for a faster list-only scrape. |
| `extractAdText` | boolean |  | `true` | Read headline, description, call to action, display/landing URL, YouTube video ID and image URLs from the ad previews. |
| `ocrTextAds` | boolean |  | `true` | Google archives most Search text ads only as a rendered image. With this on, the Actor reads the headline, description, display URL and sitelinks from that image with OCR (marked textSource: "ocr"). |
| `ocrLanguage` | string |  | `"auto"` | Language model used to read text ads archived as images. Automatic picks the language of the selected region, of the countries the ad ran in, or of the domain (e.g. zalando.de -> German), and English otherwise. Latin-script models read English text too. |
| `advertiserSummary` | boolean |  | `true` | One extra row per advertiser (type: "summary") with active ad count, total ads estimate, format and platform mix and top regions. Summary rows are free. |
| `maxAdvertisersPerName` | integer |  | `1` | A name can match several advertiser accounts (e.g. regional subsidiaries). How many of the best matches to scrape. |
| `monitorMode` | boolean |  | `false` | Compares each target with the previous run (state kept in a named key-value store) and outputs only ads that are NEW since the last run or have STOPPED running (changeType field). Schedule the Actor daily or weekly for competitor-ad alerts. |
| `monitorStoreName` | string |  | `"google-ads-transparency-monitor"` | Named key-value store that keeps the last-seen ads per target. Use different names to keep independent watch lists. |
| `activeWithinDays` | integer |  | `7` | An ad whose last-shown date is older than this is treated as inactive (isActive: false) and, in monitoring mode, reported as STOPPED. |
| `emitBaselineOnFirstRun` | boolean |  | `true` | On the first run for a target there is nothing to compare with, so every current ad is reported as NEW. Turn off to silently store the baseline and only report changes from the second run on. |
| `proxyConfiguration` | object |  | `{"useApifyProxy": true}` | Apify Proxy is used by default (datacenter first, automatic residential fallback if Google throttles). |
| `residentialFallback` | boolean |  | `true` | If datacenter IPs are throttled, retry through Apify residential proxy automatically. |
| `maxConcurrency` | integer |  | `8` | Parallel requests to the Transparency Center. |
| `dataForSeoFallback` | boolean |  | `false` | Only for self-hosted copies with DATAFORSEO_LOGIN / DATAFORSEO_PASSWORD environment variables: if the Transparency Center request fails, fetch the ad list from DataForSEO instead (list data only). |

## Example input

```json
{
  "targets": [
    "Nike"
  ],
  "maxAdsPerTarget": 5,
  "region": "anywhere",
  "includeDetails": true,
  "extractAdText": true,
  "ocrTextAds": true,
  "ocrLanguage": "auto",
  "advertiserSummary": true,
  "maxAdvertisersPerName": 1,
  "monitorMode": false,
  "monitorStoreName": "google-ads-transparency-monitor",
  "activeWithinDays": 7,
  "emitBaselineOnFirstRun": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "residentialFallback": true,
  "maxConcurrency": 8,
  "dataForSeoFallback": false
}
```

## Output fields

One flat row per result:

| Field | Type | Description |
|---|---|---|
| `type` | string | Row type: ad, summary or error (summary and error rows are free) |
| `changeType` | string | Monitoring mode: NEW (first seen), STOPPED (no longer running or removed) or RESUMED (stopped before, running again) |
| `previewImageUrl` | string | Rendered preview image of the ad (text ads are archived as images) |
| `advertiserName` | string | Advertiser name as shown in the Transparency Center |
| `advertiserId` | string | Advertiser ID (AR...) |
| `advertiserVerified` | boolean | Advertiser identity verified by Google |
| `advertiserCountry` | string | Advertiser country (ISO code) |
| `advertiserLegalName` | string | Advertiser legal name |
| `creativeId` | string | Ad creative ID (CR...) |
| `format` | string | TEXT, IMAGE or VIDEO |
| `headline` | string | Ad headline |
| `description` | string | Ad description / body text |
| `longHeadline` | string | Long headline (responsive display / video ads) |
| `callToAction` | string | Call-to-action text |
| `displayUrl` | string | Display URL shown in the ad |
| `businessName` | string | Business / brand name shown in the ad |
| `sitelinks` | array | Sitelink texts (text ads, OCR) |
| `productTitle` | string | Product title (Shopping ads) |
| `merchant` | string | Merchant (Shopping ads) |
| `textSource` | string | Where the ad text came from: preview (structured) or ocr (read from the ad image) |
| `ocrConfidence` | number | Average OCR confidence 0-100 |
| `ocrLanguage` | string | OCR language model used (tesseract code, e.g. eng, deu, jpn) |
| `landingUrl` | string | Final/destination URL when the preview exposes it |
| `landingDomain` | string | Domain the ad points to |
| `imageUrls` | array | Image asset URLs |
| `videoId` | string | YouTube video ID (video ads) |
| `videoUrl` | string | YouTube video URL |
| `videoTitle` | string | YouTube video title (video ads) |
| `videoThumbnailUrl` | string | YouTube thumbnail |
| `youtubeChannel` | string | YouTube channel name |
| `videoDuration` | string | Video duration |
| `firstShown` | string | First time the ad was shown (UTC) |
| `lastShown` | string | Last time the ad was shown (UTC) |
| `daysShown` | integer | Number of days the ad was shown |
| `isActive` | boolean | Shown within the last activeWithinDays days |
| `regionCodes` | array | Countries where the ad was shown |
| `regions` | array | Per region: first/last shown, impression range and per-platform impressions (impressions published for EU/EEA) |
| `impressionsMin` | integer | Total impressions, lower bound (EU/EEA) |
| `impressionsMax` | integer | Total impressions, upper bound (EU/EEA) |
| `platforms` | array | Platforms the ad ran on (GOOGLE_SEARCH, YOUTUBE, GOOGLE_SHOPPING, GOOGLE_MAPS, GOOGLE_PLAY) |
| `topic` | string | Ad topic / vertical |
| `targeting` | object | Targeting criteria used (EU/EEA disclosure): demographics, locations, contextual signals, customer lists, topics of interest |
| `variationsCount` | integer | Number of ad variations |
| `adUrl` | string | Ad page in the Google Ads Transparency Center |
| `detailsError` | string | Why details could not be loaded (row still returned) |
| `adsInThisRun` | integer | Summary: ads returned for this advertiser |
| `activeAdCount` | integer | Summary: ads shown within activeWithinDays |
| `newThisRun` | integer | Summary (monitoring): new ads this run |
| `stoppedThisRun` | integer | Summary (monitoring): stopped ads this run |
| `totalAdsMin` | integer | Summary: total ads Google reports for the target and filters (lower bound; the same for every advertiser of a domain target) |
| `totalAdsMax` | integer | Summary: total ads Google reports for the target and filters (upper bound) |
| `formatsMix` | object | Summary: ads per format |
| `platformsMix` | object | Summary: ads per platform |
| `topRegions` | object | Summary: ads per region |
| `adsWithText` | integer | Summary: ads with extracted text |
| `matchedBy` | string | Summary: how a name input was matched (exact-name, domain-suggestion, ...) |
| `advertiserUrl` | string | Summary: advertiser page in the Transparency Center |
| `input` | string | Error rows: the input that failed |
| `error` | string | Error rows: reason |
| `target` | object | Input target and filters this row came from |
| `scrapedAt` | string | Scrape time (UTC) |
| `newestAdFirstShown` | string | Summary: most recent first-shown date among the ads |
| `latestShown` | string | Summary: most recent last-shown date |
| `allAdsFetched` | boolean | Summary: true when all ads of the target were fetched (not capped by maxAdsPerTarget) |
| `firstMonitoringRun` | boolean | Summary (monitoring): true on the first (baseline) run |
| `monitoringRun` | integer | Summary (monitoring): run number for this target |
| `note` | string | Summary: note, e.g. why no ads were found |
| `source` | string | Data source: Transparency Center (default) or dataforseo (optional fallback) |

## Notes

- Auth: an Apify API token as `Authorization: Bearer <token>`; the MCP server also supports OAuth sign-in.
- Failed or empty results are not charged on most tools; check the pricing on the Store page.
- Questions: hello@wrenfielddata.com
