Arcadium Data Scrapers
Home / Actors / Google Ads Transparency Scraper

Google Ads Transparency Scraper

Give it a brand name, a landing domain or a Google advertiser id and it returns the ads Google publishes in its Ads Transparency Center as JSON: one row per ad with the advertiser's verified name and country, format (text, image, video), first and last day shown, days shown, regions and the archived ad image. From $1.80 per 1,000 ads; you pay only for rows you get.

$1.80 per 1,000 ads on the Free plan, down to $1.35 on higher plans

Why this actor

What you get

Ad row (rowType: "ad"): one ad creative.

FieldWhat it holds
advertiserId, advertiserName, advertiserCountryGoogle's advertiser id (reuse it in advertiserIds), the verified legal name and the country it is based in. The name is null (and advertiserNameWithheld true) when it may belong to a private person.
creativeId, adUrlGoogle's id of the ad and its page on adstransparency.google.com.
formattext, image or video.
firstShown, lastShown, daysShownFirst and last day shown (YYYY-MM-DD) and the number of days Google showed it.
regionsShown, domainCountries where it ran, and the landing domain on domain searches.
imageUrl, imageWidth, imageHeight, previewUrlThe archived image of the ad (Google archives most text ads as an image) and the preview script the website uses to render it.
political, spendMin, spendMax, spendCurrency, impressionsMin, impressionsMaxElection ads: spend and impression ranges.
detailed, regionStatsWith includeDetails: one entry per region with first/last date, impression range and the split by surface (search, YouTube, Shopping, Maps, Play) where Google publishes it (EU/EEA and political ads).
contentKind, headline, description, displayUrl, businessName, sitelinks, adTextWith includeDetails: the decoded creative. Text ads: headline, description, display URL, sitelinks. Shopping ads: product title and store. adText is all visible text.
imageUrls, youtubeVideoId, youtubeUrlWith includeDetails: product images and thumbnails, and the YouTube video of a video ad.
searchTerm, matchedByThe input the row came from, and whether it matched by advertiser id, name or domain.

A decoded text ad adds:

Advertiser row (rowType: "advertiser", mode advertisers): one verified advertiser with advertiserId, advertiserName, advertiserCountry, adsMin / adsMax (approximate number of ads), advertiserUrl, and for name searches the matchingDomains Google suggests.

Monitor rows (mode monitor): per advertiser and run one summary row (status baseline, changed or unchanged; activeAds, newAds, resumedAds, stoppedAds, previousCheckAt), and one ad-change row per ad with changeType new (first shown since the last check), resumed (an older ad active again) or stopped (not shown for activeWithinDays days), with the ad fields above.

Sample row (from the README example; long text shortened, lists cut to two items):

{
  "rowType": "ad",
  "platform": "google-ads-transparency",
  "advertiserId": "AR04217635482122584065",
  "advertiserName": "Spotify USA Inc",
  "advertiserNameWithheld": false,
  "advertiserCountry": "US",
  "creativeId": "CR08508353801336389633",
  "adUrl": "https://adstransparency.google.com/advertiser/AR04217635482122584065/creative/CR08508353801336389633?region=GB",
  "format": "video",
  "firstShown": "2025-03-18",
  "lastShown": "2026-10-22",
  "daysShown": 520,
  "regionsShown": [
    "GB",
    "FR"
  ],
  "detailed": true,
  "impressionsMin": 500000,
  "impressionsMax": 600000,
  "regionStats": [
    {
      "region": "FR",
      "firstShown": "2025-03-25",
      "lastShown": "2026-10-21",
      "impressionsMin": 40000,
      "impressionsMax": 45000,
      "platforms": [
        {
          "platform": "youtube",
          "impressionsMin": 35000,
          "impressionsMax": 40000
        }
      ]
    }
  ],
  "contentKind": "video",
  "youtubeVideoId": "2BfJuvCtfEI",
  "youtubeUrl": "https://www.youtube.com/watch?v=2BfJuvCtfEI",
  "searchTerm": "AR04217635482122584065",
  "matchedBy": "advertiser"
}

Price

Live Apify price on 2026-11-03, per 1,000 rows, by Apify plan. You pay only for rows delivered; error and summary rows marked free in the README cost nothing. Plus $0.001 per GB of memory when a run starts.

Per 1,000FreeBronzeSilverGoldPlatinumDiamond
Ad (main)$1.80$1.62$1.44$1.35$1.35$1.35
Ad with details$4.50$4.05$3.60$3.38$3.38$3.38
Advertiser$2.70$2.70$2.70$2.70$2.70$2.70
Advertiser checked (monitor)$2.70$2.43$2.16$2.03$2.03$2.03

Use cases

Run it from code or an AI agent

Actor ID arcadium/google-ads-transparency. Set APIFY_TOKEN to your Apify API token. The input below is the actor’s prefilled example; see the guide for every field.

curl
curl -X POST "https://api.apify.com/v2/acts/arcadium~google-ads-transparency/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms":["nike.com"],"mode":"ads","maxAdsPerAdvertiser":20}'
JavaScript
// npm install apify-client
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('arcadium/google-ads-transparency').call({
  "searchTerms": [
    "nike.com"
  ],
  "mode": "ads",
  "maxAdsPerAdvertiser": 20
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
Python
# pip install apify-client
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("arcadium/google-ads-transparency").call(run_input={
    "searchTerms": ["nike.com"],
    "mode": "ads",
    "maxAdsPerAdvertiser": 20,
})
items = client.dataset(run.default_dataset_id).list_items().items  # apify-client 3.x returns a Run object
print(items)
MCP
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=arcadium/google-ads-transparency",
      "headers": {
        "Authorization": "Bearer <APIFY_TOKEN>"
      }
    }
  }
}
LangChain
# pip install langchain-apify   (reads APIFY_API_TOKEN from the environment)
from langchain_apify import ApifyActorsTool

tool = ApifyActorsTool("arcadium/google-ads-transparency")
rows = tool.invoke({"run_input": {
    "searchTerms": ["nike.com"],
    "mode": "ads",
    "maxAdsPerAdvertiser": 20,
}})
# or give `tool` to an agent: create_react_agent(llm, [tool])
LlamaIndex
# pip install llama-index-readers-apify
import os
from llama_index.core import Document, VectorStoreIndex
from llama_index.readers.apify import ApifyActor

reader = ApifyActor(os.environ["APIFY_TOKEN"])
documents = reader.load_data(
    actor_id="arcadium/google-ads-transparency",
    run_input={
        "searchTerms": ["nike.com"],
        "mode": "ads",
        "maxAdsPerAdvertiser": 20,
    },
    dataset_mapping_function=lambda item: Document(text=str(item.get("description") or ""), metadata={"url": item.get("url")}),
)
index = VectorStoreIndex.from_documents(documents)
CrewAI
# pip install crewai crewai-tools langchain-apify   (reads APIFY_API_TOKEN from the environment)
from crewai import Agent
from crewai_tools import ApifyActorsTool

tool = ApifyActorsTool(actor_name="arcadium/google-ads-transparency")
researcher = Agent(
    role="Research analyst",
    goal="Answer with data collected by the tool",
    backstory="Uses public web data.",
    tools=[tool],
)
n8n
{
  "nodes": [
    {
      "name": "Run arcadium/google-ads-transparency",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4,
      "position": [
        0,
        0
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.apify.com/v2/acts/arcadium~google-ads-transparency/run-sync-get-dataset-items",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "{\"searchTerms\":[\"nike.com\"],\"mode\":\"ads\",\"maxAdsPerAdvertiser\":20}",
        "options": {
          "timeout": 300000
        }
      }
    }
  ],
  "connections": {}
}
Google Sheets
// Extensions > Apps Script. Store your token once: Project Settings > Script properties > APIFY_TOKEN.
function importLastRun() {
  const token = PropertiesService.getScriptProperties().getProperty('APIFY_TOKEN');
  const url = 'https://api.apify.com/v2/acts/arcadium~google-ads-transparency/runs/last/dataset/items?status=SUCCEEDED&clean=true&format=json';
  const res = UrlFetchApp.fetch(url, { headers: { Authorization: 'Bearer ' + token } });
  const rows = JSON.parse(res.getContentText());
  if (!rows.length) return;
  const keys = Object.keys(rows[0]);
  const values = rows.map((r) => keys.map((k) => (typeof r[k] === 'object' ? JSON.stringify(r[k]) : r[k])));
  const sheet = SpreadsheetApp.getActiveSheet();
  sheet.clearContents();
  sheet.getRange(1, 1, 1, keys.length).setValues([keys]);
  sheet.getRange(2, 1, values.length, keys.length).setValues(values);
}

Tutorials

Limitations

FAQ

How do I find an advertiser id? Run mode advertisers with the brand name, or open the advertiser on adstransparency.google.com and copy the AR... part of the link.

Why do I get ads of several advertisers for one brand? Big brands verify one advertiser per country entity. A name search uses the maxAdvertisersPerTerm best matches (name contains your text, then most ads); a domain search returns every advertiser whose ads point at the domain.

How does monitor mode decide that an ad stopped? An ad is active when Google shows it on one of the last activeWithinDays days. It is reported as stopped on the first run after it has not been shown for that long.

Something looks wrong in the output. Who do I tell? Open an issue on the actor page with the run link. We read them all.