Google Ads Transparency Scraper avatar

Google Ads Transparency Scraper

Pricing

from $2.00 / 1,000 scraped ads

Go to Apify Store
Google Ads Transparency Scraper

Google Ads Transparency Scraper

Extract ad creatives from the Google Ads Transparency Center and see what changed since your last run. Other scrapers list an advertiser's ads; this one flags which are new, which stopped, and which have run longest. Schedule it and the change log builds itself.

Pricing

from $2.00 / 1,000 scraped ads

Rating

0.0

(0)

Developer

Ege

Ege

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

6 days ago

Last modified

Share

Extract ad creatives from the Google Ads Transparency Center — and see what changed since your last run.

Other scrapers answer "what ads is this advertiser running?". This one also answers "what did they change?": which creatives are new, which stopped, and which have been running longest. Schedule it and the change log builds itself.

Output

FieldDescription
advertiserIdGoogle advertiser ID (AR...)
advertiserNameAdvertiser display name
creativeIdCreative ID (CR...)
formattext, image, or video
formatCodeRaw format code from the API
previewUrlGoogle-hosted creative preview
transparencyUrlLink back to the ad in the Transparency Center
firstShownDate the ad first ran
lastShownDate the ad last ran
daysActiveDays between first and last shown
isActiveWhether lastShown falls inside your active window
changeTypenew, stopped, continuing, or baseline
previousLastShownlastShown recorded on the previous run

Every record carries a transparencyUrl, so you can verify any row against the real page in one click.

Input

Find an advertiser at adstransparency.google.com and paste either its URL or its advertiser ID:

{
"queries": ["AR17828074650563772417"],
"mode": "changes",
"activeWithinDays": 7,
"stateKey": "default"
}
OptionDefaultMeaning
queriesAdvertiser IDs or Transparency Center advertiser URLs
modechangessnapshot for a plain extract, changes to track movement
activeWithinDays7An ad last shown before this counts as stopped
maxAdsPerAdvertiser500Cap per advertiser
stateKeydefaultNamespace for change detection — one per tracked portfolio
regions["anywhere"]Only anywhere is supported today

How change detection works

Each run stores a fingerprint of every creative it saw. The next run compares against it:

  • new — not present last time
  • stopped — gone from the results, or last shown before your active window
  • continuing — still running

The first run on a new stateKey has nothing to compare against, so every ad comes back as baseline and the run summary sets baselineRun: true. It does not pretend your whole back catalogue just launched.

Use a separate stateKey per portfolio you track. Histories are isolated.

Current limitations

Stated plainly so nothing surprises you:

  • Domain and brand-name lookup is not supported. Pass an advertiser ID or URL. Anything else is listed in advertisersUnresolved and is never charged.
  • Region filtering is not supported. All results are worldwide.

Run summary

Written to the run's own key-value store as RUN_SUMMARY, so each run keeps its own copy:

{
"advertisersRequested": 20,
"advertisersResolved": 20,
"advertisersUnresolved": [],
"advertisersSucceeded": 20,
"advertisersFailed": {},
"advertisersWithNoAds": ["AR047...", "AR075..."],
"successRate": 1.0,
"itemsPushed": 360,
"changesDetected": 0,
"baselineRun": false,
"truncatedAdvertisers": ["AR183..."]
}

A failure on one advertiser never discards the others' results.

advertisersWithNoAds matters more than it looks: an advertiser can be scraped successfully and simply have no ads running. That is a different outcome from a failure, and you should not have to guess which one you got. truncatedAdvertisers names advertisers that hit your maxAdsPerAdvertiser cap and have more available.

Pricing

$0.002 per ad, $0.004 per detected change. You are charged only for items actually delivered to your dataset.

Development

pip install -r requirements-dev.txt
pytest # 57 tests, no network calls
pytest -m live # contract tests against the real endpoint
apify validate-schema # run before every push; the build rejects on one bad key

Publishing gotchas are recorded in docs/publishing-notes.md.

normalize.py and differ.py are pure and import neither httpx nor apify, so the logic that produces the change data is tested entirely from fixtures.