Apify Actors / Google Ads Transparency scraper

Apify Actor

Google Ads Transparency scraper

Google's Ad Transparency Center answers one question well. What is this advertiser running right now, and how long has each creative been up? It answers it one card at a time, in a browser, for one advertiser. This Actor turns the same public data into dataset rows you can sort, diff and chart.

Paste advertiser names, advertiser IDs or domains, one per line, up to 100 lines. You get one row per ad with the creative ID, format, first and last shown dates, days shown, landing domain, image URL and a link to the ad itself. Run it daily and drop the creative IDs you already have; new rows are the ads that went live since yesterday.

Run it on ApifySee input and output

$0.0012 per ad row · pay per result, no subscription

Price

EventPriceCharged when
ad$0.0012Each ad row saved, after filters and duplicate removal
ad-detail$0.002Each successful detail lookup, only with Include ad details on
Example runUnitsCost
The prefilled first run (20 ads)20 × $0.0012$0.024
1,000 ads1,000 × $0.0012$1.20
1,000 ads with details1,000 × ($0.0012 + $0.002)$3.20

What you get

Input

Set the run options in the Apify console, or send the same object through the API.

{
  "advertisers": [
    "nike.com"
  ],
  "region": "anywhere",
  "platform": "all",
  "maxAdsPerAdvertiser": 20,
  "includeDetails": false
}

The prefilled input. Lines can be a domain (nike.com), an advertiser name or an AR… advertiser ID. Up to 100 lines per run.

Output

{
  "advertiserId": "AR16735076323512287233",
  "advertiserName": "Nike, Inc.",
  "creativeId": "CR06692121344286392321",
  "format": "text",
  "firstShown": "2023-11-16T21:49:06.000Z",
  "lastShown": "2026-11-05T11:22:35.000Z",
  "daysShown": 885,
  "landingDomain": "nike.com",
  "imageUrl": "https://tpc.googlesyndication.com/archive/simgad/11274417169112350865",
  "width": 348,
  "height": 305,
  "adUrl": "https://adstransparency.google.com/advertiser/AR16735076323512287233/creative/CR06692121344286392321",
  "query": "nike.com",
  "queryType": "domain"
}

One real row, trimmed to the fields most people use. With Include ad details on, the row also carries headline, description, display URL and targeting details.

Run it from your own code

The Actor takes the same input as a JSON body. This call starts a run, waits for it and returns the dataset items.

curl -X POST "https://api.apify.com/v2/acts/zovo-one~google-ads-transparency-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"advertisers": ["nike.com"], "region": "anywhere", "platform": "all", "maxAdsPerAdvertiser": 20, "includeDetails": false}'

A sync call waits at most 300 seconds. For longer runs, start a run with POST /v2/acts/zovo-one~google-ads-transparency-scraper/runs, wait for it, then read /v2/datasets/<defaultDatasetId>/items.

Limits

Up to 100 advertisers and 1,000 input lines per run, and up to 5,000 ads per input line. Google's date filter covers about the last 12 months; for older ads leave the dates empty and filter on firstShown and lastShown. The Actor reads 40 ads per request, 0.3 s apart with Apify Proxy. After 3 failed detail lookups in a row the rest of the run is saved without details, and those rows cost the ad price only.

Questions

How do I scrape Google ads for a competitor?

Put the competitor's domain, name or advertiser ID on one line and run the Actor. Domains are the most reliable input, because nike.com finds Nike's ads even when the display name is written differently. The dataset gets one row per creative, and you can filter by region, format and date range.

Why did one domain return ads from several advertisers?

Google groups a domain with the advertisers that point to it, and resellers or regional subsidiaries often run ads for the same shop. The advertiserName column shows who paid for each creative, so filter on it if you need one brand.

How do the date filters work?

dateFrom and dateTo pass a range to Google, which covers about the last 12 months. A range that ends before that is rejected with an explanation. For older ads, leave the dates empty and filter on firstShown and lastShown after the run.

Can I monitor a competitor every day?

Yes. Schedule a daily run, keep maxAdsPerAdvertiser modest, and drop creativeId values you have already seen on your side. The Actor doesn't remember ads between runs, so deduplication is something you do in your own table or script.

What happens when Google blocks a run?

Blocked requests are retried up to 5 times with a new proxy session. After 3 advertisers in a row fail, the run stops and marks the remaining lines as skipped. After 3 failed detail lookups in a row, ads are saved without details.

Is scraping the Ad Transparency Center legal?

The Actor reads ads that anyone can see on adstransparency.google.com without logging in. It doesn't log in, doesn't touch private data, and doesn't download video. How you use the data is your call. Check Google's terms and your local rules before publishing it.

Support this work

If this Actor saves you time, you can support the work on GitHub Sponsors. Monthly tiers start at $5, and one-time tiers start at $15. Sponsorship is optional, and the tool works the same without it.

Built and maintained by Zovo. Actor on Apify · All Actors.