DEV Community

FeatherScrape
FeatherScrape

Posted on Fully Autonomous

See every Google ad your competitors run, with Python (Google Ads Transparency Center)

Since 2023, Google publishes every ad it shows in the Ads Transparency Center: Search ads, YouTube videos, display banners, Shopping, Maps and Play ads, for every advertiser, with the countries and dates they ran.

That's a goldmine for competitive research. But the website only lets you browse ads one by one, there's no export, and most Search ads are shown as screenshots, so you can't even copy their text.

In this post I'll pull every ad of two competitors (Asana and monday.com) into pandas with a few lines of Python, then answer a few questions you'd actually ask about a competitor's advertising.

Disclosure: I built the Google Ads Transparency Scraper used below. It runs on Apify, which has a free plan with monthly credits, so you can follow along without paying anything.

What we'll get

One row per ad, with:

  • advertiserName, format (text, image or video), firstShown, lastShown
  • headline, description, displayUrl for Search ads, read from the screenshot when Google doesn't publish the text
  • countries where the ad ran, with per-country dates and impression ranges (published for EU and political ads)
  • paidBy: the entity that paid for the ad, which sometimes reveals the agency behind a brand
  • imageUrl, youtubeUrl for image and video ads

Step 1: install the client

Create a free Apify account, copy your API token from Settings → API & Integrations, and install:

pip install apify-client pandas
Enter fullscreen mode Exit fullscreen mode

Step 2: fetch the ads of two competitors

Searching by domain is the most complete option: Google returns the ads of every account that sends traffic to that domain, including agencies and local entities.

import os
import pandas as pd
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])

run = client.actor("featherscrape/google-ads-transparency-scraper").call(run_input={
    "searchTerms": ["asana.com", "monday.com"],  # domains, brand names or advertiser IDs
    "region": "US",                                # where the ads were shown; empty = everywhere
    "maxAdsPerSearch": 100,                        # most recently shown first
})

ads = pd.DataFrame(client.dataset(run["defaultDatasetId"]).iterate_items())
ads["firstShown"] = pd.to_datetime(ads["firstShown"])
ads["lastShown"] = pd.to_datetime(ads["lastShown"])
print(len(ads), "ads")
Enter fullscreen mode Exit fullscreen mode

You can also filter by platform (search, youtube, shopping, maps, play), format (text, image, video) and a dateFrom / dateTo range.

Step 3: what are they running?

print(ads["format"].value_counts())
print(ads["advertiserName"].value_counts())
Enter fullscreen mode Exit fullscreen mode

On my run (US, October 2026), 200 ads came back: 158 Search ads, 36 videos and 6 image ads. The advertiser list already holds a surprise:

monday.com LTD      99
Asana, Inc.         94
MightyHive, INC.     6
Enter fullscreen mode Exit fullscreen mode

MightyHive is a media agency: it runs the display banners pointing to asana.com, in up to 23 countries each. That's the kind of thing you won't see by searching Google yourself.

Step 4: read their ad copy

text_ads = ads[ads["headline"].notna()]
for _, ad in text_ads[text_ads["advertiserName"] == "monday.com LTD"].head(10).iterrows():
    print(f'{ad["headline"]}\n  {ad["description"]}\n  {ad["displayUrl"]}\n')
Enter fullscreen mode Exit fullscreen mode

A few of them:

monday CRM is So Much Better
  Manage contacts, sales, and pipelines in one place with tools your team will enjoy.
  monday.com

What Makes monday.com Better?
  Choose monday.com to Build Workflows Perfectly Customized to Your Team's Needs.
  monday.com

Project Management Templates
  Plan, Track, Manage and Collaborate Using the Top Templates Teams Love. Try for Free.
  monday.com
Enter fullscreen mode Exit fullscreen mode

Comparative headlines, a CRM push and templates as a lead magnet: you get monday.com's messaging strategy in one screen.

Step 5: find the ads that work

Advertisers don't keep paying for ads that don't convert. An ad that has been running for years is a strong signal:

ads["daysRunning"] = (ads["lastShown"] - ads["firstShown"]).dt.days
print(ads.sort_values("daysRunning", ascending=False)[["advertiserName", "headline", "daysRunning"]].head())
Enter fullscreen mode Exit fullscreen mode

"What Makes monday.com Better?" has been running since October 2021: five years. If you compete with monday.com, that's the message to answer.

Step 6: where do they advertise?

print(ads.explode("countries")["countries"].value_counts().head(10))
Enter fullscreen mode Exit fullscreen mode

Each ad also has a regions list with first and last shown dates per country, and impression ranges where Google publishes them (ads shown in the EU and political ads).

Step 7: get alerted on new ads

Turn on onlyNewAds and schedule the run (for example every morning in the Apify Console, or from cron with the code above). Each run then returns only the ads that weren't in previous runs, so you can push them to Slack, a Google Sheet or an email digest:

run = client.actor("featherscrape/google-ads-transparency-scraper").call(run_input={
    "searchTerms": ["asana.com", "monday.com"],
    "onlyNewAds": True,
})
new_ads = list(client.dataset(run["defaultDatasetId"]).iterate_items())
print(f"{len(new_ads)} new ads since the last run")
Enter fullscreen mode Exit fullscreen mode

A few things to know

  • Impressions are rare. Google publishes impression ranges only for ads shown in the EU (Digital Services Act) and for political ads. There's no spend or click data for commercial ads.
  • Screenshot text is read automatically (textSource: "ocr"). It's accurate on standard ads, with the occasional OCR slip (for example "Al" instead of "AI"). ocrText keeps the raw text.
  • Domains beat names. A name like "Asana" is matched to the closest advertiser accounts; a domain catches every account and agency advertising for it.

Wrapping up

The Ads Transparency Center is one of the best free sources of competitive intelligence, once you can get the data out of it. With a few lines of Python you can see what your competitors say, where and since when, and get notified when they launch something new.

The scraper costs $1.50 per 1,000 ads. If you need a field or hit a bug, open an issue on the scraper's page: I usually answer within 48 hours. And I'm curious: which competitor would you look at first?

Top comments (0)