Versions follow MAJOR.MINOR.PATCH (src/version.py); Apify shows MAJOR.MINOR from .actor/actor.json.
Every run logs its version and records it in the RUN_STATS key-value record.
- Fixed: a search Meta kept answering with ads it had already sent, always with a next page to come, was paged until
the run timed out (onlyNew off). Any search now stops after 3 pages in a row with no ad it hadn't returned yet, as
onlyNew searches already did, and the run ends SUCCEEDED with what it found.
- No change to output fields or price.
- A run that returns nothing (every input bad, private, blocked or unreachable, or an empty input) now ends
SUCCEEDED with an empty dataset and the reason as its status message and in the log, instead of FAILED. Only an
unexpected error still fails the run.
RUN_STATS keeps the reason as before.
- No change to output fields or price.
- Fixed: a Page address written without the periods of its username (facebook.com/HelloFreshDE for
facebook.com/HelloFresh.de) wasn't matched, although Facebook treats both as the same Page. Usernames are now compared
the way Facebook does: case and periods don't count.
- Fixed: Page and Ad Library links from a localized Facebook (
de-de.facebook.com, mbasic.facebook.com) and Page
links in Facebook's /p/Name-<id>/ form were refused as "not a Facebook Page address".
- Fixed: country
UK (and anything Meta doesn't know, like EU) failed every search with "Meta has probably changed
the Ad Library". UK is now searched as GB (EL as GR); other unknown codes fail before any request, saying
what to give instead; and Meta's answer to a value it can't read says to check the country and dates.
- A run where every search fails now shows the reason in its status message, not just "see log".
- Fixed: spend, impressions, reach estimates and button labels came back in the language of the proxy IP's country
(Indonesian
US$500 rb - US$600 rb, Pelajari selengkapnya), because logged out the Ad Library answers in the
visitor's local language and runs go out through residential IPs anywhere. Every query now asks for US English
(locale=en_US and an Accept-Language header); checked from Indonesian, German, Japanese and Brazilian IPs.
- New fields
spendMin/spendMax, impressionsMin/impressionsMax, reachEstimateMin/reachEstimateMax: the
ranges as numbers (>1M is 1000000 and no max, <1K is 0 and 1000). Text in any other format gives no number,
never a wrong one.
- New dataset view "Spend and impressions".
- A Page address whose username changed (facebook.com/allbirds is now /weareallbirds) is matched by the Page's exact
name when exactly one advertiser has it; two Pages with that name fail the line, listing both IDs.
RUN_STATS
says how each Page was matched (pageMatchedBy: address or name) and its pageId.
First release.
- Ads from Meta's Ad Library (facebook.com/ads/library) by search term, advertiser Page (address, Page ID or Ad
Library page address) or pasted Ad Library URL, including single-ad links. Filters: country, active status, ad
category, media type, platforms, words in any order or exact phrase, shown-from/until dates. A pasted URL keeps its
own filters; the input fills in the rest.
- One flat row per ad: text, headline, button, link, image and video URLs (carousel, dynamic-creative and catalogue
cards included), start and end day, days running, platforms, format, versions, special categories, and spend,
impressions and reach estimate where Meta shows them (political and issue ads). Catalogue templates
({{product.name}}) give way to the first card's real text.
- Ad details (optional, no extra charge): EU reach in total and by country, age and gender, EU targeting, payer and
beneficiary, advertiser Page and Instagram figures.
- Only new ads: remembered per input line and filter set in the user's
meta-ad-library-seen store, written only
after the ads are in the dataset; a search stops after 3 pages in a row with nothing new.
- Source: the Ad Library page's own GraphQL queries, logged out, no cookie, no account. Docs and terms checked
2026-10-14: the official Ad Library API (developers.facebook.com/docs/graph-api/reference/ads_archive) needs an
identity-confirmed Facebook account and covers political/issue ads and ads shown in the EU/UK only; facebook.com's
robots.txt disallows every crawler and Meta's terms on automated collection bind its users (Meta v. Bright Data,
N.D. Cal. 2024: not logged-out collection of public data). Read under Michael's platform robots.txt exception
(2026-10-14); the README says so.
- On Apify every search goes through a residential IP (Meta rate-limits Apify's own and datacenter IPs on the first
request) and moves to a fresh one if Meta rate-limits it.
- Charged per ad returned, through Apify's standard
apify-default-dataset-item event. "Max ads per search" and
"Max results per run", and the maximum cost per run, stop the run before the next page is fetched.
- Failure isolation: a failing input line (bad address, unknown Page, a refused query) only affects itself.