Google Ads Transparency Center Scraper (Advertisers & Ads)
Pricing
from $0.80 / 1,000 ads
Google Ads Transparency Center Scraper (Advertisers & Ads)
Scrape Google Ads Transparency Center: find advertisers by name or ID and export their ads with format, first and last shown dates, preview and ad links, filtered by region. No browser. $0.80 per 1,000 ads, $0.50 per 1,000 advertisers.
Pricing
from $0.80 / 1,000 ads
Rating
0.0
(0)
Developer
subimpact
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
11 hours ago
Last modified
Categories
Share
Scrape Google's public Ads Transparency Center (adstransparency.google.com) for advertisers
and their ads. Search advertisers by name or domain, or pass AR... advertiser ids directly, then
get one row per creative with its format, preview link, public ad permalink, first and last shown
dates, and the region you asked for.
Pure HTTP against the site's own JSON RPC. No browser, no Playwright, no login, no Google API key. Requests run through the Apify proxy because Google answers direct requests from datacenter IPs with HTTP 429.
Input
| Field | Type | Default | Notes |
|---|---|---|---|
searchTerms | array of strings | none (prefill ["adidas"]) | Advertiser names or domains. Each term is resolved to advertisers first |
advertiserIds | array of strings | none | AR... ids, used directly and skipping the search |
region | string | anywhere | Two letter ISO code such as US, GB, MY, SG, TH, or anywhere |
maxAdsPerAdvertiser | integer | 40 | 1 to 1000. The form default is 40; an empty API input ({}) uses 10 |
maxAdvertisersPerTerm | integer | 3 | 1 to 20, in the order Google returns them |
maxItems | integer | 100 | Global cap on ad rows for the whole run, 1 to 5000 |
concurrency | integer | 5 | Parallel advertisers, 1 to 20. Each one gets its own proxy session |
proxyConfiguration | object | {"useApifyProxy": true} | Required, see the proxy note below |
At least one of searchTerms or advertiserIds must be non-empty. Invalid values (an advertiser
id that is not AR followed by letters and digits, a region Google has no geo id for, a cap of 0)
fail the run immediately with a clear message, before any request and before any charge.
Example inputs
Pre-filled example, one advertiser with 20 ads, region not filtered:
{"searchTerms": ["adidas"],"maxAdvertisersPerTerm": 1,"maxAdsPerAdvertiser": 20}
An empty input works too. {} is treated as adidas, 10 ads per advertiser, at most 3 advertisers
and 100 ads in total:
{}
By advertiser id, filtered to Thailand, up to 40 ads:
{"advertiserIds": ["AR17365672681860497409"],"region": "TH","maxAdsPerAdvertiser": 40}
A domain instead of a name:
{"searchTerms": ["adidas.com"],"maxAdvertisersPerTerm": 2,"maxAdsPerAdvertiser": 15}
Google's suggestion endpoint answers a domain query with domain entries that carry no advertiser
id, so the Actor retries such a term with the domain's name part (adidas.com becomes adidas)
and logs that it did so. If you already know the advertiser, advertiserIds is exact and skips
this round trip.
Output
One row per ad plus one row per matched advertiser. rowType tells them apart: ad, advertiser
or error. Error rows are informational and are never charged.
| Field | Type | On | Notes |
|---|---|---|---|
rowType | string | all | ad, advertiser or error |
advertiserId | string or null | all | AR... id |
advertiserName | string or null | ad, advertiser | Name as Google publishes it |
country | string or null | advertiser | Country code on the matching suggestion |
adCountEstimate | integer or null | advertiser | Upper bound of Google's ad count range |
verified | boolean or null | advertiser | Google's verification flag, null when the payload omits it |
creativeId | string or null | ad | CR... id |
adFormat | string or null | ad | text, image, video or unknown |
previewUrl | string or null | ad | Google hosted preview, either an image or a content.js renderer |
adUrl | string or null | ad | Public Ads Transparency Center permalink |
firstShown | string or null | ad | ISO 8601 timestamp |
lastShown | string or null | ad | ISO 8601 timestamp |
regionQueried | string or null | ad | The region used for the search, or anywhere |
searchTerm | string or null | all | Term that produced the advertiser, null for advertiserIds |
scrapedAt | string | all | ISO 8601 timestamp of this run |
error | string or null | error | Failure reason |
Real rows, taken from the captured Nike SRL responses in test/fixtures/. The ad row is the first
creative in that response:
{"rowType": "advertiser","advertiserId": "AR17365672681860497409","advertiserName": "NIKE SRL","country": "IT","adCountEstimate": 8,"verified": null,"searchTerm": "nike","scrapedAt": "2026-10-24T12:00:00.000Z"}
{"rowType": "ad","advertiserId": "AR17365672681860497409","advertiserName": "NIKE SRL","creativeId": "CR00017566880097107969","adFormat": "text","previewUrl": "https://tpc.googlesyndication.com/archive/simgad/5369694199582718379","adUrl": "https://adstransparency.google.com/advertiser/AR17365672681860497409/creative/CR00017566880097107969","firstShown": "2025-12-05T04:56:43.000Z","lastShown": "2025-12-22T22:59:54.000Z","regionQueried": "anywhere","searchTerm": "nike","scrapedAt": "2026-10-24T12:00:00.000Z"}
The other seven creatives in the same captured response are CR06126911430613532673 (video,
shown 2025-11-26 to 2025-12-22), CR02919090104867749889 (image, 2025-12-02 to 2025-12-22),
CR13902772011454693377 (text), CR08131215574932914177 (image), CR03470410798679982081
(video, 2025-10-19 to 2025-11-22), CR10815781378604400641 (image) and CR16552501301028585473
(image). Advertiser rows from the nike suggestion response include Nike, Inc.
(AR16735076323512287233, US, estimate 10000) and Nike Srl (AR03550664066492006401, IT,
estimate 1).
adFormat comes from the creative's format code, which was verified against the preview payloads:
| Code | Label | Evidence in the preview payload |
|---|---|---|
| 1 | text | overlay protobuf carries headline, description, visurl |
| 2 | image | overlay carries productAdsRenderingData with the product and image data |
| 3 | video | assets protobuf carries media asset ids |
| other | unknown | labelled rather than guessed |
A text ad still gets an image preview from Google (simgad render), and video ads get a
content.js renderer. previewUrl points at whichever form Google returned.
adCountEstimate is the upper bound of the range Google reports. For an advertiser shown as
"9000 to 10000 ads" the row carries 10000. verified is true when the suggestion payload
carries Google's verification flag and null when the flag is absent, which is the common case.
How it works
Session and proxy
GET https://adstransparency.google.com/?region=XX mints the session cookie (NID on
.google.com). Each advertiser then uses its own proxy session and its own cookie jar, so one
throttled advertiser cannot poison the others.
The proxy is not optional. On 2026-10-24 every direct request from an Apify container got HTTP 429,
while the Apify datacenter proxy (auto group) returned 200 for the homepage, suggestions and
creatives, including a 10 way parallel suggestion burst (10/10). If the proxy cannot be created or
cannot issue a URL, the Actor fails instead of silently going direct.
Advertiser search
POST /anji/_/rpc/SearchService/SearchSuggestions?authuser= with a form encoded body
f.req={"1":"<term>","2":10,"3":10}.
The response has one mixed array under "1". Entries shaped {"1":{...}} are advertisers:
1 name, 2 AR... id, 3 country, 4.2.1/4.2.2 ad count range, 5 verification flag.
Entries shaped {"2":{"1":"nike.com"}} are domains and carry no advertiser id.
Ads by advertiser
POST /anji/_/rpc/SearchService/SearchCreatives?authuser= with
f.req={"2":40,"3":{"12":{"1":"","2":true},"13":{"1":["AR..."]}},"7":{"1":1}}.
Field notes, all verified against live responses:
"2"is the page size (40 works and returns 40 distinct creatives)."3"."13"."1"is the advertiser id list."3"."8"is the region filter, a list of numeric Google Ads geo target ids."4"at the top level is the next page token, echoed back from the previous response's top level"2". Two consecutive pages of one advertiser contained 40 and 40 creatives with no overlapping ids.- Each creative:
1advertiser id,2CR...id,3preview block (3.1.4is thecontent.jsURL,3.3.2is an<img>snippet),4format code,6.1first shown in Unix seconds,7.1last shown in Unix seconds,12advertiser name.
An empty result set is {}, which is valid and means zero matching creatives. A changed payload
(an items array with no usable CR... id, or a non-array where an array belongs) raises a shape
error: the run records an uncharged error row instead of delivering hollow rows.
Region filter
The region is translated from the ISO code to Google's Ads geo target id using the country table
published in the Google Ads API geo targets CSV (release 2026-10-06, 219 active countries). The
table is embedded in src/regions.js and maps, for example, US to 2840, MY to 2458, SG to 2702 and
TH to 2764.
This was checked against the live service: the same advertiser returned 8 ads with "8":[2840]
(US) and a full 40 of 200 to 300 with "8":[2458] (MY). anywhere sends no "8" filter at all.
Pagination
The Actor follows the top level "2" token as "4" until it has maxAdsPerAdvertiser rows, the
token stops changing, a page adds no new creative ids, the global maxItems cap is reached, or 60
pages have been read. Creative ids are deduped per advertiser, so a token that re-serves an item
cannot double charge.
Retries and rate limits
Each request has a 30 second timeout. HTTP 429, 5xx and network errors are retried up to 3 times, and every retry opens a fresh proxy session with a new session id and new cookies. A 429 waits 5 to 15 seconds with jitter first. HTTP 400 and 404 are not retried. If all attempts fail, the search term or advertiser produces one error row and the run continues with the rest.
Pay per event
| Event | Price | Charged when |
|---|---|---|
ad | $0.0008 per ad row | Immediately after the row is pushed to the dataset |
advertiser | $0.0005 per advertiser row | Immediately after the row is pushed to the dataset |
Rows are pushed and charged one at a time, so a run that times out still delivers and bills only what it already pushed. Error rows are pushed for diagnostics and are never charged. A failed charge logs a warning and never kills the run. Apify platform usage is paid by you, the buyer, on top of these event prices.
Typical event cost: the pre-filled example (1 advertiser, at most 20 ads) is at most about $0.0165.
An empty input ({}, up to 3 advertisers and 30 ads) is at most about $0.026. A run that hits the
100 ad cap is $0.08 in ad rows plus advertiser rows.
How this compares
At $0.80 per 1,000 ads and $0.50 per 1,000 advertisers, this Actor costs about half of the $1.50 actors and less than half of scrapesage's $2.00. Unlike scrapesage, there is no separate "ad details" event: every row already includes the format, the preview URL, the public permalink and both dates.
| Actor | Ads (per 1,000) | Other events | Platform usage |
|---|---|---|---|
| subimpact/google-ads-transparency-scraper | $0.80 | advertiser rows $0.50 per 1,000 | paid by you |
| scrapesage/google-ads-transparency-scraper | $2.00 | ad details $3.00 per 1,000, advertisers $3.00 per 1,000. Listing shows 1,261 users in 30 days | see listing |
| solidcode Ads Transparency actor | about $1.50 | see listing | see listing |
| s-r Ads Transparency actor | about $1.50 | see listing | see listing |
Prices are Apify Store list prices on the Free plan, checked 24 October 2026. Competitor prices can change; check their listings.
Limits and cost guardrails
maxItemsdefaults to 100 ad rows and can be set from 1 to 5000. It is enforced across all advertisers and all search terms, including the parallel workers.maxAdsPerAdvertiseris 1 to 1000. The form default is 40, an empty API input uses 10.maxAdvertisersPerTermis 1 to 20. ExplicitadvertiserIdsare all processed.- At most 100 advertisers are processed in one run, whatever the input. This keeps a many-term run from turning into hundreds of advertiser rows.
concurrencyis 1 to 20 and defaults to 5. Higher values finish faster and hit rate limits more often.- Only 219 country codes are accepted for
region, plusanywhere. The list comes from Google's own geo target table. - Ads are returned 40 per request and at most 60 pages per advertiser are read.
- Preview URLs are Google hosted. A
content.jspreview is a renderer, not an image file, so it needs a browser to display; an image preview can be opened or downloaded directly.
Responsible use
The Ads Transparency Center is a public archive about advertisers and their creatives. This Actor is meant for competitive research, ad monitoring, brand safety checks and journalism. It does not collect data about ad viewers, log in anywhere, or touch private accounts.
Google still owns the service. Keep request volume modest, do not use the output to target or profile individuals, respect Google's terms and any local rules that apply to political advertising data, and check a sample of rows before you rely on them for a decision.
When Google blocks
If Google rate limits every request, the run retries each request three times on fresh proxy
sessions. A term or advertiser that still fails leaves one error row in the dataset and is not
charged. A run that delivers no ad and no advertiser row fails with a status message instead of
ending as a silent empty success. RUN_SUMMARY in the key-value store records request counts,
retries, rate limited responses and the per-run caps.
Development
npm installnpm test
The tests run with node --test and are fully offline: parser, input validation, billing order,
budget and proxy helpers are pure functions, and the parser runs against the captured fixtures in
test/fixtures/. Captures were taken on 2026-10-24; signed preview URLs had their signature
parameters scrubbed. A failing parser test means the code changed or Google changed the payload,
not that the network flaked.