Facebook Ad Library Winning Ads Finder: AI creative breakdown on the Apify Store →
Tutorial article for the Apify blog guest program, dev.to, Medium, Hashnode — drafted with the listing, refreshed with the first real run by /actor-marketing; the owner publishes it and records the URL in brief.json → marketing.links. Store: https://apify.com/rich_minds/fb-ad-library-winning-ads
Every DTC brand, dropshipper and agency media buyer does the same Monday ritual: open the Facebook Ad Library, type a competitor or a product, scroll through hundreds of ads — most of them the same creative in 12 variants, some of them political, many started yesterday. The ads that matter are the ones that have been running for weeks: nobody keeps paying for an ad that loses money. So you copy start dates into a spreadsheet, collapse the duplicates by eye, compute how long each ad has run, paste the hook and the offer into a swipe file and brainstorm how to adapt the angle for your own product. For 10 competitors that is two to three hours a week.
The Store's Ad Library scrapers help with the first step only: curious_coder/facebook-ads-library-scraper (5,855 users a month, $0.00075 per ad) returns one raw row per variant. The sorting, the scoring and the analysis stay manual.
docs/img/shortlist.svg) — the sample Aligna Posture ad leads: 98 days running, 12 variants, 3 placements, winner score 85. {"sourceMode": "actor", "searchTerms": ["posture corrector", "dog harness", "vitamin c serum"],
"country": "US", "maxAdsToScan": 150, "maxDiscoveryChargeUsd": 0.5, "enableAi": true,
"productBrief": "An ergonomic laptop stand for people who work from home — adjustable height, folds flat, aluminium, $49."}
The Actor runs the Ad Library scraper on your account (150 ads ≈ $0.11), collapses variants by Meta's collation id, drops young (< 7 days), stopped and political ads for free and scores the rest.
Meta publishes spend and impressions only for political and EU ads, so for a commercial competitor the public signals are behavioural: how long the advertiser keeps paying, how many variants they built, and where they place it. The winner score adds them up, and every row lists the reasons so you can disagree with it:
| Signal | Points |
|---|---|
| Days running | up to 40 |
| Still active | 15 |
| Variants of the same creative | up to 20 |
| Two or more placements (Facebook, Instagram, Messenger, Audience Network) | 10 |
| Impressions bucket (only where Meta shows one) | up to 15 |
The default minWinnerScore is 40 — an ad has to have run for a while and show one more sign of scaling. Days running is a proxy for profit, not a performance figure: a brand with a big budget can keep a mediocre ad alive. That is why the AI breakdown quotes the ad itself instead of guessing results, and why the fit score is measured against your product brief, not a generic "quality" number.
Three habits that make the output useful:
searchTerms like "posture corrector" surface advertisers you did not know about; OUTPUT.competitorsToWatch then lists the top 10 by long-running ads.OUTPUT.saveAsMonitor is a ready Task input with those advertisers as competitorPages — schedule it weekly.enrichLandingPages — store platform, product and price.The source bills its own rows on your account: 1,000 ads scanned ≈ $0.75. Here you pay per qualified ad only: the first 25 are free, then $0.003 (rules) or $0.012 with the AI breakdown, plus ≈ $0.003 of AI tokens with the default model. 1,000 scanned → 150 qualified with AI: $0.75 + 125 × $0.012 + ≈ $0.45 = $2.70, about $0.018 per winning ad — variants, dead, political and duplicate ads cost nothing.
Schedule the same input weekly with onlyNewAds: true (the default) and your address in notifyEmail: every Monday the digest lists only the new long-running ads, and you pay only for those.
from apify_client import ApifyClient
client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("rich_minds/fb-ad-library-winning-ads").call(run_input={
"sourceMode": "actor",
"competitorPages": ["https://www.facebook.com/competitor-one", "https://www.facebook.com/competitor-two"],
"minDaysRunning": 14,
"maxDiscoveryChargeUsd": 0.5,
})
for ad in client.dataset(run["defaultDatasetId"]).iterate_items():
print(ad["advertiserName"], ad["daysRunning"], ad["creative"]["hook"])
The demo is pre-filled and free on any plan; your first 25 qualified ads are free after that: https://apify.com/rich_minds/fb-ad-library-winning-ads — and if it saves you a Monday, a review on the Store helps other media buyers find it.
Facebook Ad Library Winning Ads Finder: AI creative breakdown on the Apify Store →