Temporary failures now always say they are temporary, nothing is ever silently dropped, and a garbled read is never billed.
- A screenshot host that refuses or fails to answer no longer writes the creative off as unavailable. Refusals, throttles and server errors from the screenshot service now come back as a free
screenshot_fetch_failed row with re-run advice; only a screenshot the archive genuinely no longer serves keeps screenshot_unavailable.
- If our text-reading service becomes unavailable mid-run, every remaining creative and target now gets its own free row saying so. Previously the run stopped cleanly but the unprocessed remainder was simply absent from the dataset, and the one creative that hit the outage was described as unreadable. The rows now say plainly that the problem is on our side, nothing was charged for them, and trying again later will retry them.
- A garbled read can no longer be billed. If the text reader returns an implausible wall of repeated junk instead of ad copy, the creative ships as a free
ocr_unreliable row instead of a charged extraction. Genuinely short ad copy ("50% off" is a real ad) is still extracted and charged exactly as before.
- New
retryable column. Rows a fresh run can genuinely recover — source weather, screenshot-host blips, an outage on our side — carry retryable: true, so you can filter exactly what a re-run would fix.
- A resumed run that cannot fully trust its own delivery record now stops instead of guessing. After an interruption, a run that cannot completely read back what it already delivered and charged stops with charging disabled — never risking a second charge for creatives you already paid for — and a run resurrected after its time window has already ended stops immediately instead of starting partial work.
- The steadyfetch actor directory at the bottom of this page now links every live actor.
A blocked lookup no longer reads as an advertiser that does not exist.
- When the Transparency Center refuses or drops an advertiser-name lookup, the row now says so and asks you to re-run — instead of reporting that no advertiser goes by that name. A genuinely unknown name still gets the same spelling, advertiser-ID and domain guidance as before.
- A results page that returns no ads while still reporting that ads matched your target is now treated as a temporary source problem — an uncharged, re-runnable row — rather than "no creatives currently listed". A page that reports nothing and lists nothing keeps the plain "nothing listed here, try another region" answer.
- An ad listed without its display details is now reported as re-runnable, instead of "this creative has no public screenshot to read". Ads that really carry no readable screenshot keep that answer.
- All of the above stay free: nothing is charged for a row that carries no ad text.
- A typo in an input field name now gets a helpful pointer instead of sample rows. A field the actor does not recognise is ignored by the platform, so an input like
advertizers used to look exactly like a blank run and came back with the free sample creatives — as if the typo had worked. Such a run now returns one free row that names the field it could not recognise and names the field to use instead (advertisers, with the shape to paste). The same is true for settings sent without any advertiser or domain, and for a run whose only problem was a value the actor cannot use (an unknown creative format, a cap below 1) — each now gets its own free pointer row rather than sample rows. Nothing is charged, and a genuinely blank run still returns the two free sample rows exactly as before.
Two run-cost fixes — same rows, same prices.
- An outage of our text-reading service now stops the run cleanly instead of failing creative after creative. If the service refuses this actor's access mid-run, the creative that hit it ships free with an honest
ocr_service_unavailable reason, and the run stops right there — no more fetching each remaining screenshot only to fail at the last step. The closing message says the problem is ours and that undelivered creatives were not charged. Ordinary rate-limit blips keep their usual retries.
- When the Transparency Center soft-blocks a lookup, retries now change route instead of re-asking the same way. Those retries used to be answered with the same degraded page three times; they now switch to a fresh network route, which recovers real listings more often on busy advertisers.
- Better guidance when a name search finds less than the brand really runs. A brand name matches exactly one verified advertiser entity, while big brands often run ads under several — searching by
domains covers every advertiser verified for the domain. The README now says so next to the cost table, the "advertiser not found" row suggests the domain route alongside the AR… ID, and the all-video guidance row notes that a brand's text and image ads may live under other advertiser accounts a domain search would find.
- The closing status line no longer reads one video creative as two free deliverables. Guidance and summary rows (the all-video pointer, region notices, no-matching-formats summaries) now have their own count — "N free guidance row(s)" — separate from creatives, and free rows without content name where to look ("see statusReason"). What is charged is unchanged.
- The per-advertiser limit now counts rotated-out creatives too. The Transparency Center
constantly re-orders which ads it lists first, so a run resumed after an interruption could
fail to re-encounter creatives it had already delivered and top the advertiser back up to the
limit with new ones — more rows in total than the limit asked for. A resumed run now counts
everything it already delivered for an advertiser, listed again or not, so the limit is exact
across an interruption.
- An interrupted or resurrected run never delivers or charges the same creative twice. The
platform occasionally moves a long run to another server mid-flight, and any finished run can be
resurrected from the console. Both used to start over from the top — re-extracting creatives the
run had already delivered and charging for them again. A restarted run now recognises everything
already in its results: delivered creatives are skipped without a duplicate row or a second
charge, a charge interrupted mid-settlement is finished exactly once, and only the unfinished
work runs. The per-advertiser creative limit holds across the interruption too.
- The free demo can no longer be interrupted by the weather. With no input, the run used to
fetch and read two live ads; a hiccup anywhere along that path could fail it. It now returns two
sample rows — real Amazon text ads this actor extracted, frozen — instantly, fetching nothing.
Still free, still the same row shape, and the rows now carry a
_demo marker so chained runs
can tell them apart from real results.
- A country code we don't support no longer costs you money in silence. Asking for a region
like
ZZ used to be accepted without comment: the run went ahead in a different market and
charged you for the ads it found there. The run now says so up front — a free row naming the
code you sent, telling you the run used US instead, and listing every supported code — and
everything after that is the US market you can see you got.
- Every row now says whether it was charged. A new
charged column is true only on rows
that were actually billed, so a dataset reconciles line by line against your invoice.
- The free demo run's rows now say they are a demo, in words. They previously looked like
ordinary paid extractions.
- A dropped connection while reading a creative no longer ends the run. If the text-extraction
service disconnected mid-request, the whole run stopped there and every creative still queued was
lost. Those failures are now retried, and a creative that still cannot be read comes back as a
free row giving the reason — the rest of the run continues and delivers.
- A stalled extraction request now gives up instead of holding the run. A request that never
answers is cut off after a minute and retried, rather than sitting until the run hits its own
time limit.
- Fixed: a run no longer says creatives were "charged" when nothing was charged. The free demo run — and any run that bills nothing — now ends by saying plainly that nothing was charged, and the number reported as charged is always the number actually billed.
- Fixed: an incomplete screenshot download is never read as ad text. A screenshot that arrives short is now retried, and if it is still incomplete the creative comes back as a free row giving the reason. Previously a partial image could be read and charged for.
- Fixed: a Maximum cost per run that affords exactly one creative now returns that creative instead of coming back empty.
- Price cut. An extracted creative now costs $0.015 down to $0.004 depending on your Apify plan tier — the volume price was $0.010. The free-plan price is unchanged, and you are still charged only when content is actually extracted.
- The pricing block in this page now shows the new figures.
- Added a plain note that this is an independent actor — unofficial, and not affiliated with or endorsed by Google.
- The directory of other steadyfetch actors now covers every family (ad creatives, trends and keywords, YouTube, Instagram, jobs, Amazon, and general media) and names each one exactly as it appears on the Store, so a link always lands where the name says. It now sits at the end of the page, just above support.
- Added a Feedback & support section, matching the other steadyfetch actors.
- The README now has an Output section near the top — a sample results table, a screenshot of a real run's output (including an image ad read by OCR), and a link to a permanent live example dataset — so you can see exactly what you get back before spending anything.
- Added a copy-and-paste block for AI agents and LLM clients: actor id, a complete input example, every output field, and the exact event price.
- Added a directory of the other steadyfetch ad-intelligence actors (Facebook & Instagram, Google Ads video, TikTok, LinkedIn, Instagram Reels, Google Trends) with their free n8n templates.
- Fixed: advertisers whose ads are all video no longer return an empty dataset. Video creatives are now listed as free metadata rows by default, as documented — previously they were skipped unless VIDEO was explicitly included in
formats. A target whose creatives are all video (or all excluded by your formats setting) now also gets one clear free row explaining what happened and what to run instead. Nothing is charged for any of these rows.
firstShown / lastShown now arrive as readable YYYYMMDD dates (as the README always showed) instead of raw timestamp objects.
- Free rows about a whole target (like
advertiser_not_found) now carry the advertiser/domain you asked for in the advertiserName column, so multi-target runs are easy to audit.
- README: added a Related actors section — the video-transcript companion for what an advertiser's video ads say, plus the same pipeline on other ad platforms and their free n8n chaining templates. No change to pricing or behavior.
- Billing accuracy improvement for runs with a Maximum cost per run: capped runs now deliver every creative the cap affords — a rounding quirk could previously stop one creative early.
- Initial release: extracts what Google ads actually say — headline, body, CTA, display URL, and all visible text — from Ads Transparency Center creatives (TEXT and IMAGE formats), by advertiser name, advertiser ID, or domain, region-aware.
- Video creatives are listed with their metadata for free; you are charged only when a creative's content is extracted. Missing or unreadable screenshots arrive as free rows with the reason stated.