# Google Ads Scraper & Ad Copy, Email full contact info (`mangop/google-ads-transparency-center-scraper`) Actor

Scrape the Google Ads Transparency Center by brand, domain or advertiser ID: every ad with its copy (headline, description, display URL, sitelinks), format, first and last shown dates, countries, EU reach and YouTube video. Track new and stopped ads. No login.

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

## Pricing

from $2.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 Center Scraper & Ad Copy

This Google Ads Transparency Center scraper does two jobs. **Ads:** export every ad Google lists for a brand, a website, a keyword or a whole country, with the ad copy (headline, description, display URL, sitelinks), the format, the dates it was shown, the countries it ran in and its EU reach. **Advertiser contacts:** find the businesses that advertise on Google in a country or for a keyword, and get the email, phone number and social profiles from each advertiser's own website, plus how many ads it runs. Download the results as JSON, CSV or Excel, or read them through the Apify API.

### What can this Google Ads scraper do?

- **Search the way you think.** Enter brands ("Nike"), websites ("nike.com") or advertiser IDs, or leave them empty and give a keyword ("dentist", "zahnarzt", "plumbing") or just a country: the Actor finds the advertisers for you.
- **Read the ad copy.** Google publishes many search ads only as pictures. The Actor reads those with OCR, so you get the headline and description as text. It also reads Maps and local service ads, and leaves out template ads that only show placeholders.
- **Video, Shopping and display ads:** the YouTube video ID, headline, call to action and landing page of video ads; the product title, shop and picture of Shopping ads.
- **Dates and reach:** first shown, last shown, days shown, whether the ad still runs, and (optional) every country with its own dates, EU impression ranges, targeting and who paid.
- **Advertiser contacts:** for each advertiser website, the best email address (its own domain first, never the web agency's or a regulator's), every other address on the site, phone numbers, Facebook, Instagram, LinkedIn, X, YouTube and TikTok profiles, and the page the email came from.
- **Only real advertisers.** Every advertiser found by a keyword or scan has ads in the Transparency Center: the row shows how many, the last day one was shown and the accounts that pay for them. For a list of brands or websites, the row tells you whether each one advertises at all.
- **Monitor a market.** Give the run a monitor name and schedule it: ads are marked new, running or stopped; advertisers new or known. Turn on "Deliver only new results" to get, and pay for, only what earlier runs did not deliver.
- **Honest run report.** The `REPORT` record says, per search, what was found, what was skipped and why the search stopped.
- **Hard limits.** One "Max results" for the whole run, shared fairly between your searches; the run also stops at your maximum cost per run.

### How to use it

1. Pick **What to collect**: **Ads** (one row per ad) or **Advertiser contacts** (one row per advertiser, with email).
2. Fill in one of these:
   - **Brands, websites or advertiser IDs**, one per line, for example `hubspot.com`;
   - or **Find advertisers by keyword**: words that appear in the advertisers' web addresses, in the language of the country (`dentist`, `zahnarzt`, `plumber`);
   - or nothing, and pick a **country**: the Actor scans the advertisers of that country.
3. Pick the **countries** and set **Max results**. Everything else is under **Advanced options** and can stay as it is.
4. Click **Start**. Results appear in the **Output** tab as they are found. Export them or connect the dataset to Google Sheets, Make, Zapier or your own code.

### Input

| Field | Default | What it does |
|---|---|---|
| `mode` | `ads` | `ads`: one row per ad. `contacts`: one row per advertiser website, with email, phone and social profiles |
| `queries` | empty | Brands, websites, advertiser IDs or Transparency Center links |
| `keywords` | empty | Find the advertisers whose web address contains these words |
| `regions` | anywhere | ISO country codes, e.g. `["US", "DE"]`. A scan without brands or keywords needs at least one |
| `maxResults` | 100 | Ads (or advertisers) for the whole run, shared evenly by the searches |

Advanced options:

| Field | Default | What it does |
|---|---|---|
| `format` / `platform` | all | Text, image or video ads / Search, YouTube, Shopping, Maps or Play. In contacts mode: only advertisers with such ads |
| `dateFrom` / `dateTo` | none | `2026-10-01` or relative, like `30 days` |
| `maxAdsPerAdvertiser` | 0 (automatic) | Ads mode: most ads per brand and country, and per advertiser found by a keyword or scan |
| `includeAdText` | true | Ads mode: read the ad copy (no extra charge) |
| `includeDetails` | false | Ads mode: countries, EU reach, targeting and payer (extra event) |
| `includeWithoutEmail` | false | Contacts mode: also deliver advertisers whose website shows no email (cheaper event) |
| `monitorName` / `onlyNew` | off | Remember results between runs; deliver only new ones |
| `maxAdvertisersPerQuery` | 5 | Advertiser accounts kept for a brand name |
| `maxConcurrency` | 6 | Parallel connections |

Proxies are chosen automatically: Google's search requests go through Apify residential proxies, previews, pictures and advertiser websites through cheaper routes. The traffic is included in the price.

### Output: ads

A search ad whose copy Google only publishes as a picture (read with OCR), with details turned on, and a YouTube ad. Real rows from a test run, shortened:

```json
[
  {
    "adId": "CR02306867169935228929",
    "advertiserName": "Hubspot, Inc.",
    "advertiserId": "AR10072600183532683265",
    "format": "text",
    "headline": "HubSpot Free CRM Software - Enhance Customer Experience",
    "headlines": ["HubSpot Free CRM Software", "Enhance Customer Experience"],
    "description": "Generate leads, close deals and create better customer experiences. Use AI-powered tools to streamline your work, align your teams and grow your business. Free To Start.",
    "displayUrl": "www.hubspot.com/products/crm",
    "businessName": "HubSpot",
    "sitelinks": ["Generate More Leads", "All-in-One Platform", "Get a Free HubSpot Demo", "HubSpot Smart CRM", "HubSpot Pricing"],
    "firstShown": "2024-04-08",
    "lastShown": "2026-11-12",
    "daysShown": 944,
    "isActive": true,
    "adUrl": "https://adstransparency.google.com/advertiser/AR10072600183532683265/creative/CR02306867169935228929",
    "textSource": "ocr",
    "ocrConfidence": 95.8,
    "platforms": ["Google Search"],
    "regions": [
      { "code": "IE", "name": "Ireland", "firstShown": "2024-04-08", "lastShown": "2026-11-12", "impressionsMin": 6000, "impressionsMax": 7000 }
    ],
    "euImpressionsMin": 6000,
    "euImpressionsMax": 7000,
    "targeting": { "demographics": "included", "locations": "included", "contextualSignals": "included and excluded", "topicsOfInterest": "not used", "customerLists": "excluded" },
    "fundedBy": "Hubspot, Inc.",
    "query": "AR10072600183532683265",
    "matchedBy": "advertiser ID",
    "searchRegion": "anywhere"
  },
  {
    "adId": "CR14275481671309459457",
    "advertiserName": "Canva, Pty Ltd",
    "format": "video",
    "headline": "Free presentation templates",
    "description": "Choose from a variety of styles and themes, fit for any industry.",
    "callToAction": "Learn more",
    "youtubeVideoId": "tBcNLxUx4zI",
    "firstShown": "2026-09-07",
    "lastShown": "2026-11-12",
    "isActive": true,
    "textSource": "ad-preview",
    "query": "canva.com",
    "matchedBy": "domain"
  }
]
```

### Output: advertiser contacts

One row per advertiser website. The shape of a row (the values are illustrative):

```json
{
  "domain": "smile-dental.example",
  "website": "https://www.smile-dental.example/",
  "websiteTitle": "Smile Dental Studio",
  "email": "info@smile-dental.example",
  "emailMatchesWebsite": true,
  "emails": ["info@smile-dental.example", "jobs@smile-dental.example"],
  "phones": ["+1 512 555 0100"],
  "facebookUrl": "https://www.facebook.com/smiledental.example",
  "instagramUrl": "https://www.instagram.com/smiledental.example",
  "linkedinUrl": null,
  "contactPageUrl": "https://www.smile-dental.example/contact",
  "emailSourceUrl": "https://www.smile-dental.example/contact",
  "advertiserNames": ["Smile Dental Studio LLC"],
  "advertiserIds": ["AR00000000000000000000"],
  "adCountMin": 34,
  "adCountMax": 34,
  "lastAdShown": "2026-11-12",
  "isActive": true,
  "formats": ["image", "text"],
  "transparencyUrl": "https://adstransparency.google.com/?region=US&domain=smile-dental.example",
  "websiteError": null,
  "status": "new",
  "query": "dental",
  "matchedBy": "keyword",
  "searchRegion": "US"
}
```

How the email is chosen: an address on the website's own domain comes first, then an address of the same business on another domain, then a free-mail address (Gmail, GMX…) the business uses. Addresses of web agencies, site builders, chambers and regulators are never picked. Role addresses (info@, office@) beat personal and privacy mailboxes.

In our tests about half of the advertiser websites showed an email (48–68% for US plumbers and dentists and French plumbers) and 75–100% of German dentist websites did, since German sites must name a contact. By default only advertisers with an email are delivered, so you pay for leads you can use; turn on "Include advertisers without an email" to get the others too.

### How much does it cost?

You pay per result, not for run time:

| Event | Price |
|---|---|
| Ad delivered (with ad copy) | $2.00 per 1,000 ads |
| Ad details (countries, impressions, targeting) | $1.00 per 1,000 ads, only when turned on |
| Advertiser contact with an email | $10.00 per 1,000 advertisers |
| Advertiser without an email (only when asked for, or for a brand you listed) | $2.50 per 1,000 advertisers |
| Stopped-ad notices, known results skipped by a monitor, the run report | free |

Example: 1,000 ads of a competitor with their ad copy cost $2.00. 500 advertisers with an email cost $5.00, however many websites had to be read to find them.

### Monitor a competitor or a market

Set **Monitor name** (for example `dentists-de`) and schedule the Actor daily or weekly. In ads mode each ad gets a `status`: `new` the first time it is seen, `running` while it is still shown, `stopped` when Google no longer shows it. In contacts mode each advertiser is `new` or `known`. Turn on **Deliver only new results** to pay only for what you have not received yet.

### Use it with the API, MCP and AI agents

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
// Every ad nike.com showed in Germany
const ads = await client.actor('mangop/google-ads-transparency-center-scraper').call({ queries: ['nike.com'], regions: ['DE'], maxResults: 200 });
// 100 dentists in Germany that advertise on Google, with their email
const leads = await client.actor('mangop/google-ads-transparency-center-scraper').call({ mode: 'contacts', keywords: ['zahnarzt'], regions: ['DE'], maxResults: 100 });
const { items } = await client.dataset(leads.defaultDatasetId).listItems();
```

AI agents can run it through the Apify MCP server, for example: "Find 50 plumbers in the US that advertise on Google and list their emails."

### FAQ

**Is it legal to scrape the Google Ads Transparency Center?** The Actor reads only what Google publishes for anyone to see, without logging in. Ads are listed per advertiser (companies and verified organisations).

**Can I email the advertisers I find?** The contacts are what businesses publish on their own websites. How you may use them depends on where you and they are: in the EU and UK, GDPR and the ePrivacy rules apply to business email too (you need a legitimate interest or consent, must say who you are and must honour opt-outs); in the US, CAN-SPAM requires a real sender, a working unsubscribe and no misleading subject lines. Check your use with a lawyer if you are unsure.

**How are advertisers found without a brand?** Google suggests the websites that advertise in a country. The Actor asks for the websites that contain your keyword (or, in a scan, common business words and city names of that country), checks that each one has ads, and delivers them. Sites on the country's domain come first.

**Why does an advertiser have no email?** Some websites only have a contact form, show the address as an image, or block automated visits (`websiteError` says why). Those rows are left out unless you ask for them.

**Why do some ads have no ad copy?** Image ads are pictures without text fields: you get `imageUrl`. Text ads that Google publishes only as a picture are read with OCR (`textSource: "ocr"`). Template ads that show placeholders instead of the business's data, and ads that Google archived as an error page, are left without copy rather than guessed. When the ad's photo covers part of the text in Google's picture, the copy shows "…" for the hidden words.

**What is `{KeyWord:Water Heater Repair Near Me}` in a headline?** That is Google's keyword insertion, shown as the advertiser wrote it: people see their own search there, or the text after the colon when their search does not fit. In the same way, `<dynamically generated location>` stands for the searcher's town.

**Can I get landing pages, keywords, clicks or spend?** Landing pages: yes for video ads and product-feed display ads. For search ads Google shows only the display URL. Keywords, clicks and spend are not published by Google. Impression ranges exist only for ads shown in the EU.

**A brand name found the wrong company.** Exact names win and namesakes with very few ads are skipped; the `REPORT` lists every kept and skipped account. Use the website domain or the advertiser ID for exact results.

**How fast is it?** In our tests, 100 advertiser contacts took under 3 minutes (about two websites are read per contact delivered), and 100 ads with their copy under a minute. Google limits how fast one IP may ask, so the Actor paces requests, switches proxy IPs when blocked and tries blocked searches again.

**Is this an official Google tool?** No. This Actor is independent and is not affiliated with, endorsed or sponsored by Google. Google is a trademark of Google LLC.

### Changelog

- **0.2 (November 2026):** advertiser contacts (email, phone, social profiles) from the advertisers' websites; find advertisers by keyword or scan a whole country; a simpler form with the rarely used options under "Advanced options"; ad copy of Maps and local service ads.
- **0.1 (November 2026):** first release.

### About

Adversee builds Apify Actors for competitor ad research. Missing a field or found a bug? Open an issue on the Issues tab; every issue gets an answer.

# Actor input Schema

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

Ads: one row per ad, with its copy, format, dates and links. Advertiser contacts: one row per advertiser website, with the email, phone and social profiles shown on the website, plus who pays for the ads and how many run. Contacts cost more per row because every website is read.

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

One per line. A website ("nike.com") covers every advertiser whose ads lead there. A brand name ("Nike") finds the matching advertiser accounts. An advertiser ID ("AR16735076323512287233") or a Transparency Center link is exact. Leave empty to find advertisers by keyword or country instead.

## `keywords` (type: `array`):

Words in the advertiser's website address, one per line, in the language of the country: "dentist", "zahnarzt", "plumber". Finds every website with Google ads that contains the word, in the countries below. Leave brands and keywords empty to scan the advertisers of the countries.

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

Only ads shown, and advertisers advertising, in these countries. Leave empty for anywhere. A scan without brands or keywords needs at least one country.

## `maxResults` (type: `integer`):

Ads (or advertisers, in contacts mode) to deliver in total, shared evenly by your brands, keywords and countries. Each result is charged; the run also stops at your maximum cost per run.

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

Only text (search), image or video ads.

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

Only ads shown on one Google surface.

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

Only ads shown on or after this date: YYYY-MM-DD or relative ("30 days"). Google keeps about 12 months of dates.

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

Only ads shown on or before this date: YYYY-MM-DD or relative ("7 days").

## `maxAdsPerAdvertiser` (type: `integer`):

Ads mode: most ads per brand and country, and per advertiser website found by a keyword or scan. 0 = share Max results evenly between brands, and a few ads per website found (Max results / 20, at most 10), so a search covers more advertisers.

## `includeAdText` (type: `boolean`):

Ads mode: headline, description, display URL, business name and sitelinks of text ads (from Google's preview data, or by OCR when Google only shows a picture), plus call to action, landing page and YouTube video. No extra charge; makes runs slower.

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

Ads mode: one more request per ad for every country with its dates, EU impression ranges per platform, audience targeting and who paid. Charged as a separate event per ad.

## `includeWithoutEmail` (type: `boolean`):

Contacts mode: keyword searches and country scans deliver only advertisers whose website shows an email. Turn on to get the others too (website, phone, social profiles), at the lower price for a row without an email. Brands you list always get a row.

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

Any name, for example "dentists-de". Runs with the same name remember what they delivered: ads get a status (new, running, stopped) and advertisers new or known. Schedule the Actor with it. Empty = no monitoring.

## `onlyNew` (type: `boolean`):

With a monitor name: only ads, or advertisers, that earlier runs did not deliver. Ads that stopped since the last run come as free notices. Known results are not charged.

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

A brand name can match several accounts (one per country or legal entity). The biggest matching accounts are kept; namesakes with under 1% of the top account's ads are skipped.

## `maxConcurrency` (type: `integer`):

Connections used at once. More is faster for big runs; each one waits about a second between Google requests so it is not blocked.

## Actor input object example

```json
{
  "mode": "ads",
  "queries": [
    "nike.com",
    "Wayfair",
    "AR16735076323512287233"
  ],
  "keywords": [
    "dentist",
    "plumbing"
  ],
  "regions": [],
  "maxResults": 50,
  "format": "all",
  "platform": "all",
  "maxAdsPerAdvertiser": 0,
  "includeAdText": true,
  "includeDetails": false,
  "includeWithoutEmail": false,
  "onlyNew": false,
  "maxAdvertisersPerQuery": 5,
  "maxConcurrency": 6
}
```

# Actor output Schema

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

Every ad with its copy, format, dates shown and links.

## `contacts` (type: `string`):

Contacts mode: each advertiser website with its email, phone, social profiles, who pays for the ads and how many run.

## `adCopy` (type: `string`):

Headline, description, display URL, sitelinks and call to action of each ad.

## `changes` (type: `string`):

Monitor runs: new, running and stopped ads since the last run.

## `report` (type: `string`):

Per search: how it was resolved, Google's ad count, results delivered, websites read and emails found, and why it stopped.

# 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": [
        "hubspot.com"
    ],
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("mangop/google-ads-transparency-center-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": ["hubspot.com"],
    "maxResults": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("mangop/google-ads-transparency-center-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": [
    "hubspot.com"
  ],
  "maxResults": 50
}' |
apify call mangop/google-ads-transparency-center-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mangop/google-ads-transparency-center-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/RlcpcAyfgtrc6Nqa7/builds/aRhbWwahO11CVmUWp/openapi.json
