How to use Google Ads Transparency Scraper
Step by step: in the Apify Store, over the API, from JavaScript or Python, in n8n, and from AI agents through MCP or LangChain.
$1.80 per 1,000 ads on the Free plan, down to $1.35 on higher plans (live Apify price on 2026-11-03).
1. In the Apify Store (no code)
- Open arcadium/google-ads-transparency and sign in to Apify (a free account works).
- Fill in the input form. The fields below are the ones the example uses.
- Set a maximum cost per run in the run options if you want a hard cap.
- Start the run. Rows appear in the Output tab as they arrive.
- Export the dataset as JSON, CSV or Excel, or connect an integration.
| Input field | Type | Description |
|---|---|---|
searchTerms | array | What to look up, one per line: a brand or company name such as "Nike" (matched to Google's verified advertisers, see 'Advertisers per name'), a landing domain such as "nike.com" (all advertisers whose ads point there), or an advertiser/creative link from adstransparency.google.com. |
mode | string | ads = one row per ad creative (default). advertisers = one row per matching advertiser with country and approximate ad count. monitor = only what changed since your last run: new and stopped ads per advertiser, plus one summary row per advertiser. |
maxAdsPerAdvertiser | integer | Ads to return per advertiser (or per domain), newest 'last shown' first, for example 100. Default 40, up to 10,000. |
Example input:
{
"searchTerms": [
"nike.com"
],
"mode": "ads",
"maxAdsPerAdvertiser": 20
}
2. Over the Apify API
The synchronous endpoint runs the actor and returns its rows in one call (for runs up to about five minutes; use the asynchronous run endpoint for longer ones).
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}'
3. From 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);
4. From 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)
5. In n8n
Paste this node into a workflow (it is a plain HTTP Request node). Create a Header Auth credential with name Authorization and value Bearer <APIFY_TOKEN>; each returned row becomes one item for the next node.
{
"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": {}
}
6. From an AI assistant (MCP)
Add Apify’s MCP server to Claude Desktop, Cursor, VS Code or any MCP client, limited to this actor:
{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com/?tools=arcadium/google-ads-transparency",
"headers": {
"Authorization": "Bearer <APIFY_TOKEN>"
}
}
}
}
More on the MCP page.
7. From 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])
Sample output
One row, from the example in the actor’s README. Long text is shortened and lists are 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"
}
| Field | What it holds |
|---|---|
rowType | Kind of row. Filter on this first. 'ad': one ad creative (charged as 'ad', or 'ad-detail' when detailed is true). 'ad-change': monitor mode, an ad that is new, resumed or stopped since the last run (charged like an ad row). 'advertiser': one matching advertiser (charged as 'advertiser'). 'summary': monitor mode, one row per advertiser and run (charged as 'advertiser-check'). 'error': an input could not be read; see code and message (free). |
platform | Always 'google-ads-transparency'. |
advertiserId | Google's advertiser id (AR...). Use it in 'advertiserIds' to fetch the same advertiser again. |
advertiserName | Verified legal name of the advertiser as Google shows it. null when the name may belong to a private person (see advertiserNameWithheld). |
advertiserNameWithheld | true when Google shows a name that may be a private person (sole trader); we do not output it. |
advertiserCountry | Country the advertiser is based in (verified by Google), two-letter code. |
creativeId | Google's id of the ad creative (CR...). |
adUrl | Page of the ad on adstransparency.google.com (with the region when one region was filtered). |
format | 'text', 'image' or 'video'. Text ads are often archived as an image of the ad (see imageUrl). |
firstShown | Day the ad was first shown, YYYY-MM-DD. |
lastShown | Day the ad was last shown, YYYY-MM-DD. |
daysShown | Number of days Google showed the ad. |
domain | Landing domain, on domain searches. |
previewUrl | Google's preview script that renders the ad (what the website loads). |
imageUrl | Archived image of the ad (text and image ads), tpc.googlesyndication.com. |
imageWidth | Width of imageUrl in pixels. |
imageHeight | Height of imageUrl in pixels. |
political | true for election ads (they carry spend and impressions). |
impressionsMin | Lower bound of total impressions where Google publishes them (political ads; EU/EEA with details). 0 means 'under impressionsMax'. |
impressionsMax | Upper bound of total impressions; null with a set impressionsMin means 'impressionsMin or more'. |
spendMin | Political ads: lower bound of spend, in spendCurrency. |
spendMax | Political ads: upper bound of spend, in spendCurrency. |
spendCurrency | Currency of spendMin/spendMax, e.g. USD. |
regionsShown | Countries where the ad was shown (two-letter codes); with details, every region in regionStats. |
detailed | true when the ad detail was read (includeDetails). |
regionStats | With details: one entry per region shown: region, firstShown, lastShown, impressionsMin/Max and per-surface impressions (search, youtube, shopping, maps, play) where Google publishes them (EU/EEA, political). |
variationCount | With details: number of renderings (sizes, versions) of the creative. |
contentKind | With details: what the decoded preview is: 'text', 'product' (Shopping), 'image', 'video', 'html' (rendered but no fields), 'unknown'. |
headline | Decoded headline of a text ad, or product title of a Shopping ad. |
description | Decoded description line of a text ad. |
displayUrl | Decoded display URL of a text ad, e.g. www.example.com/shoes. |
businessName | Business name line of a text ad, or store name of a Shopping ad. |
sitelinks | Sitelink texts of a text ad. |
adText | All visible text of the rendered ad, emails and phone numbers removed. |
imageUrls | Image URLs found in the decoded ad (product images, YouTube thumbnail, archived images). |
youtubeVideoId | YouTube video id of a video ad. |
youtubeUrl | YouTube watch link of a video ad. |
searchTerm | The input this row came from. |
matchedBy | How the input was resolved: 'advertiser' (id or link), 'name' (brand name lookup) or 'domain'. |
scrapedAt | When the row was read (ISO datetime). |
changeType | Monitor change rows: 'new' (first shown since the last check), 'resumed' (older ad active again) or 'stopped' (not shown in the last activeWithinDays days). |
checkedAt | Monitor rows: time of this check. |
adsMin | Advertiser rows: lower bound of the number of ads Google lists for the advertiser. |
adsMax | Advertiser rows: upper bound of the number of ads. |
advertiserUrl | Advertiser page on adstransparency.google.com. |
verticals | Advertiser rows for id inputs: Google's categories, e.g. commercial, political. |
matchingDomains | Advertiser rows for a name: landing domains Google suggests for the same text (not tied to this advertiser). |
status | Summary rows: 'baseline' (first run, active ads recorded), 'changed' or 'unchanged'. |
target | Summary rows: key of the saved state (advertiser or domain plus filters). |
regions | Summary rows: the region filter of the check. |
activeWithinDays | Summary rows: an ad is active when shown on one of the last N days. |
activeAds | Summary rows: active ads now. |
complete | Summary rows: false when the active list hit maxActiveAdsPerAdvertiser (stopped ads are then not reported). |
previousActiveAds | Summary rows: active ads at the previous check (null on a baseline). |
newAds | Summary rows: ads first shown since the previous check. |
resumedAds | Summary rows: older ads active again. |
stoppedAds | Summary rows: ads no longer shown. |
changesDeferred | Summary rows: changes over maxChangesPerAdvertiser, reported on the next run. |
previousCheckAt | Summary rows: time of the previous check. |
input | Error rows: the input that failed. |
code | Error rows: invalid_input, not_found, no_match, blocked or unavailable. |
message | Error rows: what went wrong, in plain words. |
Tutorials
Schedule it
In Apify Console, create a Task from your input and add a Schedule (for example daily). Each run writes a new dataset; integrations can push the rows to Google Sheets, Slack, a webhook or your database.