# Google Ads Transparency Scraper — Copy, Regions, Impressions (`foxlabs/google-ads-transparency-scraper`) Actor

Get the ads a domain, brand or advertiser runs on Google from the Ads Transparency Center (Google's ad library): ad text, with OCR for image-only ads, image, YouTube ID, first/last shown, per-country impressions (EEA/TR), platforms, targeting, topic, Shopping price and legal name.

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

## Pricing

from $1.00 / 1,000 ads

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 Scraper — Copy, Regions, Impressions

Get the ads a website, brand or advertiser runs on Google — Search, YouTube, Maps, Play and Shopping — straight from the public [Google Ads Transparency Center](https://adstransparency.google.com/). One row per ad with the **ad text — read from the ad's picture (OCR) when Google keeps only a picture — image or preview, Shopping price, YouTube video ID, first and last shown date, per-country impressions and platform breakdown (EEA and Turkey), audience-targeting approach, topic** and the **advertiser's legal name**.

No Google account, no API key, no browser.

### Quick start (API)

```bash
curl -X POST "https://api.apify.com/v2/acts/foxlabs~google-ads-transparency-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"queries": ["nike.com"], "maxAdsPerQuery": 20}'
```

### What you get

| Group | Fields |
|---|---|
| Advertiser | `advertiserName`, `advertiserLegalName`, `advertiserId`, `advertiserCountry`, `advertiserDunsNumber` (where Google publishes it) |
| Ad | `creativeId`, `format` (TEXT / IMAGE / VIDEO), `firstShown`, `lastShown`, `daysShown`, `imageUrl`, `previewUrl`, `transparencyUrl` |
| Ad copy | `adTexts` (text lines in order), `callToAction`, `displayUrl`, `landingUrl`, `landingDomain`, `youtubeVideoId`, `isShoppingAd`, `productTitle`, `price`, `merchantName`, `shoppingService`, `app` (ID, name, store, category, developer of app-install ads) |
| Reach (EEA + Turkey) | `impressionsEeaTrLow` / `High`, `surfacesEeaTr` (impressions per platform), `regions[]` (per country: first / last shown, impression range, platform breakdown) |
| Targeting | `targeting.demographics`, `geoLocation`, `contextualSignals`, `customerLists`, `topicsOfInterest` — each `INCLUDED`, `EXCLUDED`, `INCLUDED_AND_EXCLUDED` or `UNUSED` |
| Classification | `topic` (Google's ad topic), `productCategory` (some Shopping ads), `variationCount` |
| Status | `detailStatus`, `adCopyStatus` (`ok` from the preview, `ocr` read from the picture, `image-placeholder`, …), `ocrConfidence` (0–100), `query`, `queryType`, `regionFilter`, `scrapedAt`, `error`; `isNew` in monitoring mode |

#### Sample output

A real row (trimmed) from a run on 2026-09-23, query `Decathlon`, region France:

```json
{
  "advertiserName": "Decathlon France SASU",
  "advertiserLegalName": "Decathlon France SASU",
  "advertiserId": "AR15666691663760195585",
  "advertiserCountry": "FR",
  "creativeId": "CR18395479902410244097",
  "format": "TEXT",
  "firstShown": "2026-01-21T16:26:15.000Z",
  "lastShown": "2026-09-23T14:37:34.000Z",
  "daysShown": 233,
  "adTexts": ["DECATHLON - SUPPORT DE CADENAS DE CADRE DE VELO RING-LOCK - antivol - velo voyage - Decathlon"],
  "displayUrl": "Decathlon.fr",
  "isShoppingAd": true,
  "productTitle": "DECATHLON - SUPPORT DE CADENAS DE CADRE DE VELO RING-LOCK - antivol - velo voyage - Decathlon",
  "shoppingService": "Yteo",
  "transparencyUrl": "https://adstransparency.google.com/advertiser/AR15666691663760195585/creative/CR18395479902410244097?region=FR",
  "targeting": {
    "demographics": "UNUSED",
    "geoLocation": "INCLUDED_AND_EXCLUDED",
    "contextualSignals": "INCLUDED_AND_EXCLUDED",
    "customerLists": "UNUSED",
    "topicsOfInterest": "UNUSED"
  },
  "impressionsEeaTrLow": 6000,
  "impressionsEeaTrHigh": 7000,
  "surfacesEeaTr": [
    { "surface": "YOUTUBE", "impressionsLow": 0, "impressionsHigh": 1000 },
    { "surface": "SHOPPING", "impressionsLow": 0, "impressionsHigh": 1000 },
    { "surface": "SEARCH", "impressionsLow": 6000, "impressionsHigh": 7000 }
  ],
  "regions": [
    { "countryCode": "FR", "countryName": "France", "firstShown": "2026-01-21", "lastShown": "2026-09-23", "impressionsLow": 6000, "impressionsHigh": 7000 }
  ],
  "variationCount": 3,
  "detailStatus": "ok",
  "adCopyStatus": "ok"
}
```

### Input & filters

| Input | What it does | Default |
|---|---|---|
| `queries` | Domains (`nike.com`), brand names (`Nike`), advertiser IDs (`AR…`) or Transparency Center URLs. The same advertiser given twice in one run (its ID and its URL) is run once | — |
| `region` | Only ads shown in this country (243 countries) | anywhere |
| `adFormat` | `all`, `text` (includes Shopping product ads), `image`, `video` | all |
| `platform` | `all`, `search`, `youtube`, `maps`, `play`, `shopping` | all |
| `datePreset` | Ads shown during `any`, `last7`, `last30`, `last90`, `last365` or `custom`. `dateFrom` / `dateTo` (YYYY-MM-DD) also work on their own; a fixed period takes precedence over them | any |
| `maxAdsPerQuery` | Stop after this many ads per query (up to 100,000). The Console form starts at 10 for a quick first run (12–132 s in four test runs) | 100 |
| `maxAdvertisersPerQuery` | Brand names only: how many of the brand's advertiser entities to include | 1 |
| `includeDetails` | Regions, impressions, platforms, targeting, topic (one extra request per ad) | on |
| `includeAdCopy` | Text lines, CTA, display URL, YouTube ID, Shopping title, price and merchant (one extra request per ad) | on |
| `ocrImageAds` | Read the text of ads Google keeps only as a picture (OCR; English, German, French, Spanish, Portuguese, Italian, Dutch, Polish, Turkish) | on |
| `includeAdvertiserDetails` | Legal name, country, D-U-N-S number | on |
| `onlyNewAds` + `monitorName` | Monitoring: only ads this monitor has not returned before | off |
| `proxyConfiguration`, `autoProxyFallback` | Proxy is not needed; the Actor switches to Apify residential proxy by itself if Google rate-limits it | off / on |

Region, format, platform and dates are applied by Google itself, so a filtered run does not download ads it then throws away. Invalid input (no query, a date not in YYYY-MM-DD form, `dateFrom` after `dateTo`) stops the run at once with the reason in its status message.

### Example inputs (copy & paste)

A competitor's YouTube video ads from the last 30 days (ads this new have no impression ranges yet, see Data quality):

```json
{ "queries": ["nike.com"], "adFormat": "video", "platform": "youtube", "datePreset": "last30", "maxAdsPerQuery": 200 }
```

A brand's ads in France with per-country reach:

```json
{ "queries": ["Decathlon"], "region": "FR", "maxAdsPerQuery": 100 }
```

Weekly monitor of new ads from several competitors (schedule it weekly):

```json
{ "queries": ["hubspot.com", "salesforce.com"], "onlyNewAds": true, "monitorName": "crm-competitors", "datePreset": "last7", "maxAdsPerQuery": 2000 }
```

Several entities of a brand, fast (no ad copy). `maxAdsPerQuery` is shared by all matched entities, and the biggest one usually fills most of it:

```json
{ "queries": ["Decathlon"], "maxAdvertisersPerQuery": 10, "includeAdCopy": false, "maxAdsPerQuery": 1000 }
```

### Use cases

- **Competitor creative research:** see which messages, offers and formats a competitor keeps running, with the image or preview of every ad and its text, read from the picture when Google keeps only a picture. `daysShown` and `lastShown` separate long-running ads from tests.
- **Shopping and offer tracking:** product titles, prices and merchants of Shopping ads, and the display URLs and text of search ads, show what is being pushed.
- **EU reach analysis:** impression ranges per country and per platform for ads that have run in the EEA or Turkey for about three months or more.
- **New ad alerts:** schedule `onlyNewAds` daily or weekly and connect the dataset to Slack, email or a sheet. New ads arrive without impression ranges; Google adds those later.
- **Prospecting:** find which companies advertise and on which platforms, with their legal name, to qualify marketing and agency leads.

### Performance & throughput

Measured on the Apify platform (details and ad copy on; 512 MB memory without OCR, 1 GB with OCR):

| Run | Ads | Time |
|---|---|---|
| `nike.com` (2026-09-23) | 40 | 24 s |
| `nike.com`, YouTube video ads, last 30 days (2026-09-23) | 50 | 29 s |
| `nike.com` + `Decathlon` (Wednesday 2026-09-23) | 600 | 8 min (74 ads per minute) |
| Same input three days later (Saturday 2026-09-26) | 600 | 6.6 min (91 ads per minute) |
| `hubspot.com` + `salesforce.com` search ads, OCR on (2026-09-26) | 40, 24 of them pictures | 111 s |
| `nike.com` + `hubspot.com`, OCR on (2026-09-26) | 80, 44 of them pictures | 3.6 min |
| `nike.com`, the form's starting input, OCR on (2026-09-27, four runs) | 10, 3–7 of them pictures | 12–132 s |
| `nike.com`, OCR on (2026-09-27) | 100, 60 of them pictures | 4.5 min |

Listing needs one request per 40 ads; details and ad copy need one request per ad each. Reading an ad's picture (OCR) takes 0.6–7.5 s per picture at the default 1 GB memory, depending on how busy the platform's server is, so advertisers whose ads are mostly pictures run at roughly 20 ads per minute (100 `nike.com` ads, 60 of them pictures, in 4.5 min) and slower when the server is busy; more memory gives the run more CPU, and turning `ocrImageAds` off brings the speed back to the rows above. The Actor needs at least 512 MB: with OCR, memory use peaked at about 240–340 MB in these runs, and a run at 256 MB was stopped for lack of memory. Requests are spaced to stay under Google's rate limit. In some runs Google limited the platform's IP within the first 25–50 requests; the run then continues through Apify residential proxy by itself. With the default one-hour timeout and details and ad copy on, a run delivers roughly 4,000–5,000 ads; turn those options off or raise the timeout for more.

### Integrations

Use the dataset from the API, export CSV / Excel / JSON from the console, or connect it to Make, Zapier, n8n, Google Sheets or Slack with Apify integrations. Schedule the Actor for monitoring.

### Data quality

Share of ads with the field filled, measured on the Apify platform: the same 600 ads of `nike.com` and `Decathlon` on 2026-09-23 and 2026-09-26, 1,200 ads of `hubspot.com`, `nike.com` and `Decathlon`, and 50 YouTube video ads of `nike.com`. Several fields depend a lot on the advertiser, so the notes under the table matter.

| Field | Filled |
|---|---|
| Advertiser name and ID, creative ID, format, first / last shown, days shown, countries | 100% |
| Advertiser legal name | 99–100%; 16% in the YouTube sample, where 40 of 50 ads ran through a media agency's account |
| Impressions and platforms per country (EEA and Turkey) | 70–82% (ads running there for about three months or more: 99%; newer ads: 0%) |
| Targeting approach | 77–86% |
| Topic | 38–55% |
| Ad text lines, OCR on | hubspot.com + salesforce.com search ads 85% (34 of 40; the other 6 pictures are empty archive placeholders), nike.com + hubspot.com 99% (79 of 80), hubspot.com 100 of 100 |
| Ad text lines, OCR off | Decathlon 78–86%, nike.com 34–37%, hubspot.com 3.5% |
| Display URL · Shopping product title | 49–52% · 36–45% (nike.com + Decathlon) |
| YouTube video ID — YouTube video ads | 88% |
| Landing page URL · call to action | under 1% in the mixed runs, 6% of the YouTube video ads (only previews that carry a click URL: video, app and some local ads) |
| Shopping product category | 6–9% of Shopping ads |
| D-U-N-S number | 7–14% |

Every test run returned unique ads (no duplicate `creativeId` per query in 3,100 ads checked). The five targeting categories and the Shopping and YouTube platform codes were cross-checked, ad by ad, against Google's BigQuery dataset.

What to expect, by design:

- **Many ads are archived as pictures, and their text is read by OCR.** Google keeps a large share of search ads, and most image ads, only as a picture of the ad (hubspot.com: 12 of 12 text ads in one test). With `ocrImageAds` on (the default), the Actor reads the text in the picture: those rows have `adCopyStatus: "ocr"`, the text lines in `adTexts`, the display URL in `displayUrl` and `ocrConfidence` (0–100). In a review of 20 such ads, the headline and description came out right in all 10 search ads (near word-for-word) and in 8 of 9 display ads; text drawn inside the ad's graphic is sometimes missing or jumbled, and typical OCR slips appear ("AI" read as "Al", a lost accent). Some pictures in Google's archive hold no ad at all, only "Collapsed ad on mobile / Expanded ad" labels: those rows get `adCopyStatus: "image-placeholder"` and no text (6 of 40 hubspot.com / salesforce.com search ads). OCR covers Latin-script languages; other scripts come out empty or garbled.
- **Impressions appear about three months after an ad starts.** Google publishes impression ranges only for the EEA and Turkey, and only for ads that have run there for roughly 90 days: none of 98 ads first shown in the EEA in the last 90 days had them, against 99% of 1,828 older ads. Other countries never have impression ranges; their rows list the country and its last-shown date with `impressionsLow` / `impressionsHigh` set to `null`.
- **A domain query returns the ads that lead to that domain, whoever runs them.** For hubspot.com, 120 of 400 ads came from 74 other advertisers (partners, resellers, individuals). Query the `AR…` advertiser ID to get one account only.
- **The advertiser is the paying account,** often an agency: 40 of 50 nike.com YouTube ads ran through "Mediabrands Netherlands B.V.", which has no published legal name.
- **Shopping fields.** `price` is the price line as shown ("149,99 €"). `merchantName` is the store line; a retailer's own listings (Decathlon) have none, the store is in `displayUrl`.
- **Details are almost always there.** Every one of the 3,400+ ads listed in our test runs came back with details. A creative opened directly by URL for which Google serves none leaves one free row with `error: "empty: Google shows no details for this creative."` Rows of creative-URL queries have no `daysShown`.
- **Previews Google cannot draw** are marked `adCopyStatus: "preview-unavailable"` (8 of 600 ads in the latest run).
- **Template tokens are removed, keyword insertion is kept.** Placeholders such as `[Price]` or `<Rating (Reviews)>` are not values and are dropped. Dynamic keyword insertion such as `{Keyword: Housse}` is what the advertiser wrote and is kept.
- **D-U-N-S numbers** come from the mapping Google publishes in the Transparency Center. It covers about 6,500 advertiser accounts, so the field is empty for most advertisers.

### Pricing

Pay per event: `ad` for every delivered ad, plus `ad-detail` when details were returned and `ad-copy` when text or other copy fields were read, from the preview or from the ad's picture (OCR). Pictures with no readable text are not charged as ad copy. Queries that return no ads, and error rows, are not charged. An advertiser given twice in one run is run once, so its ads are not charged twice. See the Pricing tab for the prices.

### FAQ

**Do I need a Google account or an API key?** No. The Actor reads the same public data as the Ads Transparency Center website.

**Why are impressions empty?** Google publishes impression ranges only for ads shown in the EEA and Turkey, and only once an ad has run there for about three months. US-only ads and new ads have none.

**Why do some ads have no text?** Google archives many ads only as a picture. With `ocrImageAds` on, their text is read from the picture (`adCopyStatus: "ocr"`). Rows still without text are pictures that hold no ad (`image-placeholder`), pictures without readable text (`image-no-text`), or ads in non-Latin scripts.

**What does `daysShown` mean?** The number of days Google reports the ad as shown.

**How fresh is the data?** It is read live from the Transparency Center when the run starts.

**Can I get only new ads?** Yes. Turn on `onlyNewAds` and give the monitor a name. Each run returns only ads this monitor has not returned before and remembers them, also when a run is aborted. A run checks up to 10,000 listed ads per query (listing is cheap; details and ad copy are fetched only for new ads) and delivers at most `maxAdsPerQuery` new ones. Pair it with a `datePreset` such as `last7` so the check covers everything shown in that period. A query with no new ads leaves one free row with `error: "empty: No ads that were not already seen in earlier runs."`; filter out rows with an `error` before you forward the dataset to Slack or a sheet.

**What if a brand has several advertiser accounts?** Brands often advertise through several legal entities. Raise `maxAdvertisersPerQuery`, or query the domain instead of the name (a domain also brings ads of other advertisers that link to it).

### Troubleshooting

- **"No advertiser matches":** try the website domain or the `AR…` advertiser ID from the Transparency Center URL. Brand names are matched the way Google's own search box matches them, accents included; when no advertiser carries the exact name, the log and the `SOURCE_REPORT` record say that the closest match was used.
- **A query returned nothing:** the dataset has a row with `error` explaining why, and the `SOURCE_REPORT` record in the key-value store lists every query's outcome.
- **Slow run:** turn off `includeDetails` / `includeAdCopy` for large lists, or narrow the date range.

### Notes, limits & legal

- This Actor is not affiliated with Google. It reads the public Ads Transparency Center, whose web interface can change.
- Impressions are ranges, as published by Google.
- Targeting: all five categories were cross-checked, ad by ad, against Google's public BigQuery dataset of the Transparency Center (`bigquery-public-data.google_ads_transparency_center`).
- The data describes advertisers and their ads. It contains no personal data about people who saw the ads. Advertiser names are published by Google and can be the names of individuals (sole traders); treat those as personal data where GDPR or similar laws apply.
- You are responsible for how you use the data.

### Support

Open an issue on the Issues tab with the run ID and the query.

### Changelog

#### 0.1.14 — 2026-09-27

The Console form starts at 10 ads per query (API calls without `maxAdsPerQuery` still get 100), so a first run is quick (12–132 s in four test runs); minimum memory is 512 MB, because OCR does not fit in 256 MB. 0.1.15 corrects the measured speeds in this README. See CHANGELOG.md.

#### 0.1.13 — 2026-09-26

Text of image-only ads: Google keeps many ads only as a picture, and the Actor now reads the text in the picture (OCR, on by default, `ocrImageAds`). Such rows have `adCopyStatus: "ocr"` and `ocrConfidence`; pictures that hold no ad are marked `image-placeholder`. hubspot.com ads with text went from 3.5% to 100 of 100 in a test run. See CHANGELOG.md.

#### 0.1.9 — 2026-09-26

Fixes from the pre-publication checks: monitoring now finds new ads among still-running ones and remembers delivered ads when a run is aborted; `dateFrom` / `dateTo` work without choosing "Custom dates"; invalid input stops the run with a clear status message; Shopping ads get a `price` field and `merchantName` no longer holds prices; the same advertiser given twice is run once; creative URLs keep the YouTube ID; icons and invisible characters are no longer reported as ad content. See CHANGELOG.md for the full list.

#### 0.1 — 2026-09-23

First version. See CHANGELOG.md for the full list.

# Changelog

This Actor's version history is a separate document: https://apify.com/foxlabs/google-ads-transparency-scraper/changelog.md

# Actor input Schema

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

One per line. A website domain (nike.com) finds the ads that lead to it, whoever runs them. A brand name (Nike) is matched to the advertiser with that name, or the closest one. An advertiser ID (AR…) or an Ads Transparency Center advertiser/creative URL is used as is.

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

Only ads shown in this country. "Anywhere" returns ads from every region. Impression counts are published by Google for the EEA and Turkey only.

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

Text ads include Shopping product ads. Image ads carry their text inside the picture.

## `platform` (type: `string`):

Where the ad was shown.

## `datePreset` (type: `string`):

Only ads that were shown at some point in this period (filter applied by Google).

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

Start date, format YYYY-MM-DD. Used when "Shown during" is "Custom dates below" or "Any time"; a fixed period such as "Last 30 days" takes precedence.

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

End date, format YYYY-MM-DD. Used when "Shown during" is "Custom dates below" or "Any time"; a fixed period such as "Last 30 days" takes precedence.

## `maxAdsPerQuery` (type: `integer`):

Stop after this many ads for each query. Large advertisers have tens of thousands. The form starts at 10 for a quick first run; an API call without this field gets 100.

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

For brand-name queries only: how many matching advertiser accounts to include (best match first). A brand often runs ads from several legal entities.

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

One extra request per ad. Adds first/last shown per country, impression ranges and platform breakdown (EEA and Turkey), audience-targeting approach, topic and variation count.

## `includeAdCopy` (type: `boolean`):

Reads the ad preview: text lines, call to action, display URL, YouTube video ID, Shopping product title, price and merchant, and the landing URL when the preview has one. Ads that Google keeps only as a picture (most image ads and many search ads) are read by the option below.

## `ocrImageAds` (type: `boolean`):

Google keeps many ads only as a picture. With this on, the text in the picture is read (OCR) into the text fields, with adCopyStatus "ocr" and an ocrConfidence score. Latin-script languages: English, German, French, Spanish, Portuguese, Italian, Dutch, Polish, Turkish. Needs "Ad copy" on; counted as ad copy.

## `includeAdvertiserDetails` (type: `boolean`):

Adds the advertiser's legal name, billing country and, where Google publishes it, the D-U-N-S number.

## `onlyNewAds` (type: `boolean`):

Monitoring mode for scheduled runs: returns only ads this monitor has not returned before. A run sees at most "Max ads per query" ads, so combine it with a "Shown during" period (e.g. last 7 days) that the first run can fully cover.

## `monitorName` (type: `string`):

Keeps separate memories for separate monitors (for example one per client). Stored in your own key-value store.

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

Not needed for most runs. Leave off and the Actor switches to Apify residential proxy by itself if Google rate-limits it.

## `autoProxyFallback` (type: `boolean`):

When Google answers "too many requests", continue through Apify residential proxy instead of failing.

## Actor input object example

```json
{
  "queries": [
    "nike.com"
  ],
  "region": "anywhere",
  "adFormat": "all",
  "platform": "all",
  "datePreset": "any",
  "maxAdsPerQuery": 10,
  "maxAdvertisersPerQuery": 1,
  "includeDetails": true,
  "includeAdCopy": true,
  "ocrImageAds": true,
  "includeAdvertiserDetails": true,
  "onlyNewAds": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "autoProxyFallback": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

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

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "queries": [
        "nike.com"
    ],
    "maxAdsPerQuery": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("foxlabs/google-ads-transparency-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "queries": ["nike.com"],
    "maxAdsPerQuery": 10,
}

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

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

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

```

## CLI example

```bash
echo '{
  "queries": [
    "nike.com"
  ],
  "maxAdsPerQuery": 10
}' |
apify call foxlabs/google-ads-transparency-scraper --silent --output-dataset

```

## MCP server setup

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

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/c0UKjstJqf8MdTINk/builds/sADcxAvaSDsDDOtwq/openapi.json
