# Google Ads Transparency Scraper: Competitor Ads + Days Running (`f0rty7even/google-ads-transparency-tracker`) Actor

Scrape every ad a competitor runs on Google Search, Display and YouTube, from Google's official Ads Transparency Center. Each creative comes with how many days it has been running, so proven winners are obvious. Run it again and it reports what launched, stopped and changed.

- **URL**: https://apify.com/f0rty7even/google-ads-transparency-tracker.md
- **Developed by:** [Michael Yousrie](https://apify.com/f0rty7even) (community)
- **Categories:** SEO tools, Automation
- **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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

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

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

# README

## Google Ads Transparency Scraper: See Every Ad a Competitor Runs

Pull every ad your competitors are running on Google Search, Display and YouTube, straight from Google's own [Ads Transparency Center](https://adstransparency.google.com/), and find out **how long each ad has been running**.

That last number is the point. Anyone can see what a competitor is advertising today. This tells you which of those ads they have been paying for since 2024, and an ad that survives two years of a competitor's budget is an ad that works.

Run it once for a snapshot. Run it on a schedule and it reports what launched, what got switched off, and what changed since last time.

### What you get

| Field | What it tells you |
| --- | --- |
| `daysRunning` | How many days the ad has been live. The single most useful column here. |
| `isLongRunning` | True once an ad passes 90 days, which is well past the point a test would have been cut. |
| `firstShown` / `lastShown` | The window Google reports for the creative. |
| `changeType` | `new`, `still_running`, `stopped` or `creative_changed` since your last run. |
| `advertiserName` | The legal entity paying for the ad, which is often not the brand name. |
| `format` | `text`, `image` or `video`. |
| `assetUrl` / `previewHtml` | The creative itself, ready to download or embed. |
| `regionCount` | How many countries the ad runs in, a decent proxy for budget. |
| `adUrl` | Link to the ad's page in the Ads Transparency Center. |

### Example output

One row, taken from a real run against `linear.app`:

```json
{
  "advertiserId": "AR01614221664915521537",
  "advertiserName": "Linear Orbit, Inc.",
  "creativeId": "CR10758577049937575937",
  "adUrl": "https://adstransparency.google.com/advertiser/AR01614221664915521537/creative/CR10758577049937575937?region=US",
  "format": "text",
  "firstShown": "2024-09-23",
  "lastShown": "2026-08-10",
  "daysRunning": 654,
  "isLongRunning": true,
  "regionCount": 3,
  "region": "US",
  "changeType": "still_running"
}
```

654 days on the same ad. That is not a test, that is a proven winner, and now you can read the copy.

### What to use it for

#### Find the ads your competitor refuses to turn off

Sort the output by `daysRunning`, descending. The top of that list is your competitor's proven creative, paid for with their budget and validated over years. It is the highest-signal free research available in paid search.

#### Track a competitor's launches week by week

Turn on change tracking and put the actor on a weekly schedule. Every run after the first reports exactly which creatives are new and which disappeared, so you see a campaign launch in the week it happens instead of noticing it a quarter later.

#### Size up a market before you enter it

Run a list of every competitor domain in a category. The number of advertisers, the number of live creatives and the `regionCount` spread give you a fast read on how contested the keywords are and who is actually spending.

#### Build a swipe file automatically

`assetUrl` gives you the creative asset and `previewHtml` gives you the rendered ad. Point the actor at ten competitors and you have a categorised, dated swipe file that refreshes itself.

#### Check an agency's work

If an agency runs your Google Ads, this shows you what is actually live under your own domain, when it went live, and what they quietly turned off.

### Input

| Setting | Description |
| --- | --- |
| **Advertiser websites** | The domains whose ads you want, such as `nike.com`. Full URLs are fine. |
| **Advertiser IDs** | Exact IDs like `AR16735076323512287233`, for when you want one specific advertiser account. |
| **Country** | Two-letter code such as `US`, `GB`, `DE` or `AE`. Google reports ads per country. |
| **Max ads per advertiser** | Spend cap. Large brands run tens of thousands of creatives, so this controls what a run costs. |
| **Track changes between runs** | Remembers this run and compares the next one against it. |
| **Include ads that stopped running** | Adds a row for each ad that has disappeared since the last run. |

A domain can return more than one advertiser. Searching `hubspot.com` returns Hubspot's own account plus the partners and resellers who advertise on the same domain, which is usually what you want.

### Pricing, and what is never charged

Pay per event, no subscription.

| Event | Price |
| --- | --- |
| Ad scanned | $2 per 1,000 |
| Change detected | $20 per 1,000 |

Three things are deliberately never charged:

1. **Your first run's "changes."** With no previous run to compare against, every ad is trivially new. That is not an insight, so a first run costs you nothing in change events.
2. **Advertisers that could not be reached.** If Google is throttling or the domain has no ads in that country, you get an explanation and no charge.
3. **Anything a truncated run might have "changed."** If your ad cap cuts a sweep short, this actor refuses to compare that run at all. Google does not return creatives in a stable order, so comparing partial slices would invent launches and stops that never happened, and you would be paying for noise. It tells you in the log and leaves your baseline intact.

That third one costs us money on purpose. It is the difference between a change report you can act on and one you have to second-guess.

### Change tracking, in practice

Change tracking needs to see an advertiser's full set of ads, so it only runs when your cap covers everything that advertiser has live. For most companies a cap of 200 is plenty. For a global brand running 20,000 creatives you would need to raise it, and the log tells you exactly when that is the case and by how much.

History is stored in a key-value store in **your** account, so your comparison history is yours. Give two schedules different store names if you want to track the same advertisers weekly and monthly without them overwriting each other.

### Notes and limits

- The Ads Transparency Center is Google's own public disclosure service. This actor reads it, and nothing here is behind a login or a paywall.
- Ads are reported **per country**. The same advertiser returns a different set in `US` than in `DE`, so pick the market you care about.
- `firstShown` and `lastShown` are Google's figures, not estimates. `daysRunning` is the gap between them.
- Video creatives are previewed through a signed URL that changes on every request, so this actor never reports a video ad as having a changed creative. That avoids charging you for a difference that is not real.
- Political ads are covered by a separate part of the Center and are not included here.

### Frequently asked questions

**Is scraping the Ads Transparency Center allowed?**
The Center is a public transparency service Google publishes to meet ad disclosure obligations. It needs no account and no API key. This actor reads the same public data your browser does.

**How is this different from just using the Ads Transparency Center myself?**
The website shows you one advertiser at a time, in a browser, with no export, no history and no way to tell how long an ad has run without reading dates off individual cards. This gives you every advertiser at once, as JSON, CSV or Excel, with `daysRunning` computed and changes tracked between runs.

**Does it work for advertisers outside the US?**
Yes. Set the country to any two-letter code, such as `GB`, `DE`, `AE`, `IN`, `BR` or `ZA`.

**Can I find a competitor's YouTube ads?**
Yes. Video creatives appear with `format: "video"` and a preview URL.

**How much does a typical run cost?**
Ten competitors at 200 ads each is 2,000 ads, which is $4.00, plus change events on later runs. A weekly schedule over ten competitors runs to a few dollars a month.

**Why do I sometimes see several advertisers for one domain?**
Google ties ads to the advertiser account that paid, not to the domain. Resellers, regional subsidiaries and agencies all show up under the domain they point at. The `advertiserName` and `advertiserId` fields tell them apart.

**What happens if Google changes the format of its data?**
The actor validates the shape of every response and fails loudly with a clear message rather than quietly reporting zero ads. A silent zero would be the worst possible outcome for a monitoring tool.

### Other actors you might need

- [Website Lead Extractor](https://apify.com/f0rty7even/website-lead-extractor) - pull contact details off any list of websites.
- [Tech Stack Detector](https://apify.com/f0rty7even/tech-stack-detector) - see what a competitor's site is built on.
- [Domain Intelligence](https://apify.com/f0rty7even/domain-intelligence) - domain age, DNS, mail setup and registrar detail.
- [SEO Audit & Site Health Checker](https://apify.com/f0rty7even/seo-auditor) - crawl a site and score its on-page SEO.
- [Email Verifier](https://apify.com/f0rty7even/email-verifier) - check deliverability before you send.

# Actor input Schema

## `advertiserDomains` (type: `array`):

The websites whose ads you want, one per line. A full URL is fine, only the domain is used. A domain can return more than one advertiser when resellers and partners also advertise on it.

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

Exact advertiser IDs, which look like AR16735076323512287233. Use these instead of a website when you want one specific advertiser account rather than everyone advertising on a domain. You can read the ID out of any Ads Transparency Center URL.

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

Two-letter country code for the country whose ads you want, such as US, GB, DE or AE. Google reports ads per country, so the same advertiser returns a different set in each one.

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

Hard stop after this many ads for each advertiser. Large brands run tens of thousands of creatives, so this is the setting that controls what a run costs. Leave empty to take everything.

## `trackChanges` (type: `boolean`):

Remember this run and compare the next one against it, so later runs report what launched, what stopped and what changed. The first run has no baseline and is never charged for changes. Turn this off for a one-off snapshot.

## `includeStoppedAds` (type: `boolean`):

Add a row for each ad that was live last run and has since disappeared. These rows carry the last known detail rather than fresh data. Only applies when change tracking is on.

## `stateStoreName` (type: `string`):

Name of the key-value store holding the history used to compare runs. The default is fine. Change it only to keep two schedules from overwriting each other, for example a weekly and a monthly run over the same advertisers.

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

Proxy used to reach the Ads Transparency Center. The default is usually fine; a different IP helps if Google starts rate limiting a long run.

## Actor input object example

```json
{
  "advertiserDomains": [
    "nike.com",
    "https://www.booking.com/"
  ],
  "advertiserIds": [
    "AR16735076323512287233"
  ],
  "region": "US",
  "maxAdsPerAdvertiser": 200,
  "trackChanges": true,
  "includeStoppedAds": true,
  "stateStoreName": "google-ads-tracker-state",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per creative. Export as JSON, JSONL, CSV or Excel.

# 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 = {
    "advertiserDomains": [
        "nike.com",
        "adidas.com"
    ],
    "region": "US",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("f0rty7even/google-ads-transparency-tracker").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 = {
    "advertiserDomains": [
        "nike.com",
        "adidas.com",
    ],
    "region": "US",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("f0rty7even/google-ads-transparency-tracker").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 '{
  "advertiserDomains": [
    "nike.com",
    "adidas.com"
  ],
  "region": "US",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call f0rty7even/google-ads-transparency-tracker --silent --output-dataset

```

## MCP server setup

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

```

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/BnoZlZkdZogJz2Buo/builds/Q2y1X2pNCoQrkaNbc/openapi.json
