# Google Ads Transparency Scraper (`otterfetch/google-ads-transparency`) Actor

Every ad a company runs on Google, from the Ads Transparency Center: headline, description, regions, dates and payer. Reads text ads shown only as images (OCR). Or check if ads point to a domain. $0.001 per ad, no start fee, no caps. AI-agent friendly: summary rows come first.

- **URL**: https://apify.com/otterfetch/google-ads-transparency.md
- **Developed by:** [Otter Fetch](https://apify.com/otterfetch) (community)
- **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

See every ad a company runs on Google, or check whether any Google ads point to a website. The Actor reads the public Google Ads Transparency Center for you and gives you clean rows you can sort, filter and export. Not affiliated with Google.

You pay per ad returned (and a small add-on when it reads text out of an image). You never pay for empty results in ads mode.

### Why this one

- **Clean ad copy.** Headline and description as separate fields, read from the image when Google only shows a picture (87 to 89 of 100 Nike ads had a clean headline in our tests). Keyword-insertion templates are filled in. In our tests, 92% of Search text ads show their copy only as an image. The Actor reads that text (OCR) by default.
- **Region filters that work.** Other scrapers often return 0 ads for the United States (see the FAQ).
- **No 35/100/1,000 ad caps.** You set your own limit with `maxAdsPerTarget`. Use 0 for no limit.
- **Plain statuses.** When a target has no ads, you get a free row that says why and what to try.
- **Two modes in one Actor.** Get every ad for a company, or get a yes or no for each website.
- **Speed.** 100 ads in about 2 minutes 15 seconds with text reading on, about 90 seconds without, under 15 seconds with `listingOnly`.

### Quick start

1. Pick **Mode**: **Ads** or **Domain check**.
2. Type your **Targets**, one per line: a website (`nike.com`), an advertiser ID (`AR16735076323512287233`), a Transparency Center link, or a brand name. Or paste a CSV or Google Sheets link in **Import targets from a link**.
3. Set a **Region**, **Date range** and **Max ads per target** if you want. The default is 100; the form is prefilled with 20 for a small first run.
4. Click **Start**. When it ends, open the **Overview** view, or export the dataset as CSV.

Google blocks most cloud servers, so the Actor uses residential connections. They go through Apify residential proxies. Proxy costs are included in the price.

### What you get

Real rows from cloud runs (2026-10-22 for the first four):

| advertiser | format | headline | days running | text_source |
|---|---|---|---|---|
| Nike, Inc. | text | Nike® Official Site | 140 | ocr |
| Nike Retail BV | text | Le site officiel de Nike | 1824 | structured |
| Hubspot, Inc. | text | HubSpot CRM Platform | 31 | ocr |
| Canva, Pty Ltd | video | Start designing with Canva today | 45 | structured |
| Cebu Air Inc. | text | Cebu Pacific Air - Flights to Boracay | 1531 | ocr |

A domain check row for nike.com: `ads_point_here` true, 80,000 to 90,000 ads, active in the last 30 days, top advertiser Nike Retail BV.

See Advanced for full rows.

### Pricing

Pay per event. You pay for results, not for time.

| Event | Price | Charged when |
|---|---|---|
| `ad` | $0.001 | One ad row was returned. Summary, status, blocked and failed rows are free. With `listingOnly` on this is the only event. |
| `ad-text-ocr` | $0.001 | Ads mode only, on top of `ad`: the text of that ad was read from its image. Never charged when `listingOnly` is on. Not charged when `readImageText` is off, no text was found, or the text was unreadable (for example Thai or Korean ad images). |
| `domain-check` | $0.001 | One domain was checked: every verdict, yes or no, is billed. Domains that could not be checked (invalid, blocked or skipped) are not. |

Prices shown are the current list prices; Apify shows the live price on the Actor page.

What a run costs: 100 ads with text reading on cost about $0.13 ($0.10 for the ads, plus $0.001 for each ad whose text was read; at most $0.20). 1,000 domain checks cost $1.

#### What 1 ad actually costs

An ad costs **$0.001**. If its text was read from an image, add **$0.001**, so **$0.002** at most. That add-on is **+$0.001 per ad where text was read**. Nothing is charged when no text was read. Turn `readImageText` off and ads cost $0.001 each.

With `listingOnly` on, every ad costs $0.001 and `ad-text-ocr` is never charged, even if `readImageText` is on. The maximum cost per run also counts each ad as $0.001 in that case.

So 1,000 ads cost between $1 and $2, depending on how many were text ads read with OCR.

You never pay for empty results in ads mode. In ads mode these are free: status rows, summaries, blocked lookups and the start-up check that makes sure Google is answering normally. In domain check, a "no ads point here" answer is a real answer, so it is billed like a "yes".

Other facts:

- No start fee, no per-GB fee and no fee for time spent.
- `maxAdsPerTarget` is a hard limit: the run never fetches or bills more ads than that for a target.
- The Actor respects your maximum cost per run. It works out how many results the budget covers before it starts and lists the rest as skipped (`skipped_budget`).

### What it does

- **Ads mode.** For each target, returns one `ad` row per ad and one `target_summary` row (the verdict, how many ads, which advertisers). Ad rows include the format (text, image or video), headline, description, landing page, first and last shown dates, days running, the countries it ran in with impression ranges, and the payer name.
- **Domain check mode.** For each website, returns one `domain` row that answers: do any Google ads point to this site? It also says whether any ran in the last 30 days.
- **Filters.** Region (country), date range, ad format and a limit per target.
- **Free explanation rows.** A target with no ads, a skipped target or a blocked target gets a `status` row in plain English. It is never billed.

### Who it is for

#### Marketers

See what a competitor is running, how long each ad has been live, and which landing pages they send people to. Long-running ads are usually the ones that work.

#### Agencies

Run a list of client or prospect domains in one go and export a spreadsheet. Use Domain check to find out which prospects advertise at all before you pitch them.

#### Lead generation

Check a long list of domains for "is this company spending on Google ads?" and keep only the ones that are. Use the `advertiser_match` column to see if an advertiser name looks like the site (it compares names only and is a hint, not proof, see the FAQ).

#### AI agents

One clear input, one row type per question, and a plain `status` and `reason` on every non-result. You are billed only for results. Read only rows where `type` is `target_summary` or `domain` for a compact answer.

The Advanced section has a note on choosing fields when you fetch dataset items.

### Example inputs

Field keys below are the real input keys. Only `targets` (or `importUrl`) is required.

#### Marketers: a competitor's recent US ads

```json
{
  "mode": "ads",
  "targets": ["nike.com"],
  "region": "US",
  "dateRange": "last_90_days",
  "maxAdsPerTarget": 200
}
```

#### Agencies: all ads for two advertisers, text ads only

```json
{
  "mode": "ads",
  "targets": ["AR16735076323512287233", "hubspot.com"],
  "format": "text",
  "maxAdsPerTarget": 100,
  "maxTargets": 50
}
```

#### Lead generation: which of these sites run Google ads?

```json
{
  "mode": "domainCheck",
  "importUrl": "https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID/edit",
  "domainActiveWindow": true
}
```

#### Just the ad list: no text, regions or payer

```json
{
  "mode": "ads",
  "targets": ["nike.com"],
  "maxAdsPerTarget": 500,
  "listingOnly": true
}
```

#### AI agents: a small, low-cost look

```json
{
  "mode": "ads",
  "targets": ["hubspot.com"],
  "maxAdsPerTarget": 20,
  "readImageText": false,
  "adDetails": false
}
```

### FAQ

**Why do other scrapers return 0 ads for the US?**
Two reasons. First, Google uses its own region codes, not the usual country codes. The Actor maps codes like `US` for you. Second, Google returns nothing when you look up a subdomain. The Actor checks the main domain instead: `shop.globe.com.ph` becomes `globe.com.ph`, and `www.nike.com` becomes `nike.com`.

**Why does the Actor read text from images?**
In our tests, 92% of Search text ads show their copy only as an image. Without OCR you would get empty headlines. The Actor reads that text (OCR) by default, for +$0.001 per ad where text was read. To turn it off, clear **Read ad text from images (+$0.001 per ad where text was read)** in the form (`readImageText` set to `false`). The headline and description will then be empty for those ads, and you save the add-on.

**Is there a cap on how many ads I can get?**
No 35/100/1,000 ad caps. You choose with **Max ads per target** (`maxAdsPerTarget`). The default is 100; the form is prefilled with 20 for a small first run. Use 0 for no limit. Be careful with large brands: nike.com has more than 80,000 ads, so 0 there is a very large run. Set a limit first.

**How long does a run take?**
In our tests (nike.com, 100 ads, default settings), 100 ads took about 2 minutes 15 seconds with text reading on. With **Read ad text from images** off, they took about 90 seconds. With `listingOnly` on, they took under 15 seconds. Reading text from images is the slow part: it is what fills the headline and description of most text ads.

**What happens if my region has no ads?**
**Retry anywhere when the region has no ads** (`retryAnywhere`) is off by default, so a one-country request is never billed for other countries. You get a free status row (`region_too_narrow`) that says how many ads exist with no region filter. Turn it on to fetch ads from all countries instead. Those rows are marked with `region_fallback`.

**Can I pick Search, YouTube or Maps ads?**
There is no platform filter (Search, YouTube, Maps) yet: results cover every platform.

**How exact is a brand name?**
Brand names are matched through Google's suggestions and can pick the wrong company. Domains and advertiser IDs are exact. Some brands (for example McDonald's) have no domain suggestions, so enter their domain instead.

**What does `advertiser_match` mean?**
In Domain check it compares advertiser names (the top advertisers in the sample) with the domain or brand you gave. It is based on names only and does not verify domain ownership: it is a hint, not proof. `advertiser_match_reason` is `name` when a name looked like it and `none` when none did. An agency can advertise a client's site under its own name, and that shows as `none`.

**What does "ads point here" mean in domain check?**
It means Google ads exist whose landing page is on that domain. It does not say the site owner is the advertiser. Ended advertisers may not show up when you search by domain.

**Can I paste a Transparency Center link?**
Yes. Only the `region` part of a pasted link is used. Date parameters in links are ignored: use the form's date range (**Date range**, **Custom start date** and **Custom end date**).

**What do the totals mean?**
Google shows ad totals as buckets, so `total_ads_range` has a low and a high number. `ads_returned` is how many ads were found for the target. Ads found (up to your limit). Ad rows can be fewer when the run stops early or an ad was already returned for another target.

**Why is a target skipped?**
Three status reasons cover skips, and none is billed. `skipped_limit`: you hit **Max targets** (`maxTargets`). `skipped_budget`: the run reached your maximum cost per run, so the rest was left out. `skipped_timeout`: the run reached its time limit before that target. Raise the limit or split the list across runs. A `blocked` row means Google refused the requests after several retries: try again in a few minutes. A `failed` row means something went wrong on our side while handling that target. It is not billed. Try again, and report it in the Issues tab if it repeats. If every target fails this way, the run ends as failed instead of showing an empty result.

**Is this a Google Ads Transparency API?**
Google has no official API for this. The Actor reads the public Transparency Center and you can call it through the Apify API, so it works like one: send targets, get rows back.

**Is this a Google Ads Transparency Center scraper? What about the Google Ads Library?**
Yes. It is a Google Ads Transparency Center scraper. Some people call that public lookup the Google Ads Library; it is the same place.

**Can I use it as a Google ad spy tool for competitor Google ads?**
Yes. Enter a competitor's website or advertiser ID in Ads mode to list their ads, how long each has run and where it points. Long-running ads are usually the ones that work.

**How do I check if a website runs Google Ads?**
Use Domain check mode. You get one row per website that says whether any Google ads point to it and whether any ran in the last 30 days.

**Is this affiliated with Google?**
Not affiliated with Google. Data comes from the public Google Ads Transparency Center.

### Advanced

#### Sample output

These rows were produced by the Actor's own row builders from recorded data, so the fields are real. Numbers will differ on your run. Long lists are shortened to keep this page readable. The ad row is a real Cebu Pacific text ad whose headline and description were read from its image. The domain row is for `nike.com`.

**`target_summary`** (one per target; with a limit it comes before its ads, with no limit it comes after them):

```json
{
  "type": "target_summary",
  "input": "AR03755644507429797889",
  "status": "success",
  "verdict": "has_ads",
  "query_kind": "advertiser",
  "resolved_via": "advertiser_id",
  "advertisers": [{"name": "LL Law Firm", "id": "AR03755644507429797889", "ads": 3}],
  "total_ads_range": {"lo": 9, "hi": 9},
  "ads_returned": 3,
  "ads_active_last_30_days": 3,
  "format_mix": {"text": 3},
  "first_seen": "2025-06-09",
  "last_seen": "2026-10-20",
  "transparency_url": "https://adstransparency.google.com/advertiser/AR03755644507429797889",
  "region": null,
  "region_fallback": false
}
```

**`ad`** (one per ad, abbreviated):

```json
{
  "type": "ad",
  "query": "cebupacificair.com",
  "status": "success",
  "advertiser_id": "AR07044148030781521921",
  "advertiser_name": "Cebu Air Inc.",
  "ad_id": "CR11309760530983419905",
  "ad_url": "https://adstransparency.google.com/advertiser/AR07044148030781521921/creative/CR11309760530983419905",
  "format": "text",
  "headline": "Cebu Pacific Air - Flights to Boracay",
  "description": "Book and save on your next flight to Boracay. Check out our low fares today!",
  "first_shown": "2022-08-13",
  "last_shown": "2026-10-21",
  "days_running": 1531,
  "text_source": "ocr",
  "region_fallback": false
}
```

Some Search ads use Google keyword insertion, where the ad data holds a template such as `{KeyWord:Nike Shoes}`. `headline` and `description` show the default text ("Nike Shoes"), and `headline_template` and `description_template` keep the text exactly as Google has it. They are empty when the ad has no template. A template with no default text (`{KeyWord}`) cannot be filled in and is left as written.

`text_source` says where the words came from: `ocr` means they were read from the ad image. With **Fetch ad details** on (the default), the full row also has the countries it ran in, with dates and impression ranges, and the payer name. If the image is in a script the reader cannot read (for example Thai or Korean), the text is left empty, `text_source` is `none`, the `extraction` entries for `headline` and `description` say `unreadable`, and there is no OCR charge. See the **Ads** view for every column.

**`domain`** (one per domain in Domain check):

```json
{
  "type": "domain",
  "input": "nike.com",
  "query": "nike.com",
  "status": "success",
  "ads_point_here": true,
  "total_ads_range": {"lo": 80000, "hi": 90000},
  "sample_size": 40,
  "top_advertisers": [
    {"name": "Nike Retail BV", "id": "AR18378488041124659201", "ads": 24},
    {"name": "Nike, Inc.", "id": "AR16735076323512287233", "ads": 10}
  ],
  "advertiser_match": true,
  "advertiser_match_reason": "name",
  "latest_last_shown": "2026-10-21",
  "active_last_30_days": true,
  "active_last_30_days_range": {"lo": 10000, "hi": 20000}
}
```

Totals are ranges (for example 80,000 to 90,000) because Google only shows buckets, not exact counts.

#### Notes for AI agents

When you fetch dataset items with the `fields` parameter (for example through an MCP server), ask for `top_advertisers`, the whole list. Do not ask for `top_advertisers.name`: it is not a column, so you would get nothing back.

#### Dataset views and row types

The dataset has four views in the Apify Console: **Overview**, **Ads**, **Domain check** and **Status**. Each view shows the columns for one kind of row. Views cannot filter rows, so a view still lists every row and leaves the columns that do not apply empty. To get one kind of row only, export the dataset and filter the `type` column. The values are `ad`, `target_summary`, `domain` and `status`. In Google Sheets, use Data, Create a filter on the `type` column. With a limit (the default is 100), each target's summary row comes before its ads. With no limit (0), ads are delivered page by page and the summary row comes after them.

#### Status reasons

Each free status row has a reason column: `invalid_target`, `brand_not_found`, `no_ads`, `region_too_narrow`, `date_too_narrow`, `blocked`, `failed`, `skipped_limit`, `skipped_budget` or `skipped_timeout`. The message column says in plain English what to try.

#### All inputs

| Field (key) | What it does |
|---|---|
| Mode (`mode`) | `ads` (every ad per target) or `domainCheck` (do ads point to each domain?). Default `ads`. |
| Targets (`targets`) | One per line: a website domain, an advertiser ID, a Transparency Center link or a brand name. |
| Import targets from a link (`importUrl`) | A CSV link or a Google Sheets link shared as "anyone with the link". One target per row in the first column. |
| Region (`region`) | A country, or `anywhere` for all countries. Default `anywhere`. |
| Retry anywhere when the region has no ads (`retryAnywhere`) | When the region has no ads, fetch from all countries and mark the rows. Default off. |
| Date range (`dateRange`) | `all`, `last_30_days`, `last_90_days`, `last_12_months` or `custom`. |
| Custom start date (`startDate`) | First day (YYYY-MM-DD). Used only with a custom date range. |
| Custom end date (`endDate`) | Last day (YYYY-MM-DD). Used only with a custom date range. |
| Ad format (`format`) | `all`, `text`, `image` or `video`. |
| Max ads per target (`maxAdsPerTarget`) | Hard limit per target. The default is 100; the form is prefilled with 20 for a small first run. 0 means no limit. |
| Listing only (fastest: no ad text, regions or payer) (`listingOnly`) | Returns only the listing fields of each ad (advertiser, format, dates, ad link). No preview, details or OCR requests, so the text, countries, payer and `headline_template` fields are empty and their `extraction` entries say `missing`. Each ad costs $0.001 and `ad-text-ocr` is never charged. Default off. |
| Read ad text from images (+$0.001 per ad where text was read) (`readImageText`) | OCR for image-only text ads. Default on. |
| Fetch ad details (`adDetails`) | Adds countries with dates, impression ranges and the payer name. One extra request per ad, no extra charge. Default on. |
| Also check the last 30 days (domain check only) (`domainActiveWindow`) | Domain check only. Adds whether ads ran in the last 30 days. Same price. |
| Max targets (`maxTargets`) | Optional safety limit for scheduled runs. Extra targets are listed as skipped and not charged. |

### Issues

Report problems in the Issues tab. Include the run link and the target that went wrong.

# Actor input Schema

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

Ads returns every ad for each target. Domain check answers one question per domain: do any Google ads point to it? Domain check accepts website domains only.

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

One per line: a website domain (nike.com), an advertiser ID (AR16735076323512287233), a Transparency Center link, or a brand name. Domains and advertiser IDs are exact; brand names are matched through Google's suggestions and may pick the wrong company. Required unless you give an import link.

## `importUrl` (type: `string`):

Optional https link to a CSV file or a Google Sheets link (shared as "anyone with the link"). One target per row in the first column; a header row named target, domain, advertiser, url or brand is skipped. Example: https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID/edit

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

Only ads shown in this country. Anywhere returns ads from all countries.

## `retryAnywhere` (type: `boolean`):

When the chosen region has no ads, fetch the ads from all countries instead and mark each row. Off by default so a one-country request is never billed for other countries. When off, you get a free status row telling you how many ads exist elsewhere.

## `dateRange` (type: `string`):

Only ads shown in this period. Choose Custom to set the start and end dates below.

## `startDate` (type: `string`):

First day, as YYYY-MM-DD. Used only when the date range is Custom.

## `endDate` (type: `string`):

Last day, as YYYY-MM-DD. Used only when the date range is Custom.

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

Only ads of this format.

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

Hard limit per target: the run never fetches or bills more. Use 0 for no limit, but be careful with large brands (nike.com has more than 80,000 ads).

## `listingOnly` (type: `boolean`):

Returns only what the ad list shows: advertiser, format, dates and the ad link. No ad text, countries or payer, and no text is read from images. Each ad still costs $0.001. Turn on when you only need to count or list ads.

## `readImageText` (type: `boolean`):

Most Search text ads only show their copy as an image. When on, the Actor reads the headline and description from that image. You pay the extra $0.001 only for ads where text was actually read. Turn off to save.

## `adDetails` (type: `boolean`):

Adds the countries with first and last shown dates, impression ranges and the payer name. One extra request per ad, no extra charge. Turn off for a faster run.

## `domainActiveWindow` (type: `boolean`):

Domain check only. Adds whether ads pointing to the domain were shown in the last 30 days. Same price.

## `maxTargets` (type: `integer`):

Optional safety limit for scheduled runs. Extra targets are listed as skipped and not charged.

## Actor input object example

```json
{
  "mode": "ads",
  "targets": [
    "nike.com",
    "hubspot.com"
  ],
  "region": "anywhere",
  "retryAnywhere": false,
  "dateRange": "all",
  "format": "all",
  "maxAdsPerTarget": 20,
  "listingOnly": false,
  "readImageText": true,
  "adDetails": true,
  "domainActiveWindow": true
}
```

# Actor output Schema

## `overview` (type: `string`):

One row per target: verdict, total ads, ads returned, advertisers and dates. Start here.

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

One row per ad with advertiser, format, headline, description, landing page, dates, countries and payer.

## `domainCheck` (type: `string`):

One row per domain: whether ads point to it, recent activity and the top advertisers. Only in domain check mode.

## `status` (type: `string`):

Free rows for targets with no ads, invalid lines, blocked or skipped targets, with what to try.

## `runSummary` (type: `string`):

Targets per verdict, ads per text source, charged events, estimated cost and request statistics (key-value store record RUN_SUMMARY).

# 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 = {
    "mode": "ads",
    "targets": [
        "nike.com",
        "hubspot.com"
    ],
    "region": "anywhere",
    "maxAdsPerTarget": 20
};

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

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

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

```

## Python example

```python
from apify_client import ApifyClient

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

# Prepare the Actor input
run_input = {
    "mode": "ads",
    "targets": [
        "nike.com",
        "hubspot.com",
    ],
    "region": "anywhere",
    "maxAdsPerTarget": 20,
}

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

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

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

```

## CLI example

```bash
echo '{
  "mode": "ads",
  "targets": [
    "nike.com",
    "hubspot.com"
  ],
  "region": "anywhere",
  "maxAdsPerTarget": 20
}' |
apify call otterfetch/google-ads-transparency --silent --output-dataset

```

## MCP server setup

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

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

## OpenAPI specification

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