Instagram Ads Library Scraper - Creatives, Video
Pricing
from $0.50 / 1,000 ad delivereds
Instagram Ads Library Scraper - Creatives, Video
Filter the Meta Ad Library to Instagram placements and export the creative: image and video URLs, carousel cards, headline, primary text, call to action, landing domain, days running and how often a creative is reused. Sort by impressions, keep active ads only, schedule a swipe file. Pay per ad.
Pricing
from $0.50 / 1,000 ad delivereds
Rating
0.0
(0)
Developer
Automation Craft
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Share
Instagram Ads Library Scraper - Creatives, Video
Instagram Ads Library Scraper: search the Meta Ad Library (Facebook, Instagram, Messenger, Audience Network, WhatsApp and Threads ads) by keyword, advertiser page, ad ID or a pasted Ad Library URL, apply every filter the Ad Library website has, and export the ads as clean JSON, CSV or Excel. No login, no cookies, no API keys, no code, and you pay only for the ads you receive.
Built around the complaints buyers leave on other Ad Library scrapers:
- Every Ad Library filter, applied on Meta's side. Country (all 250 plus "All countries"), ad category (all, political, housing, employment, financial), active status, media type, platform, ad language, impressions date window, sort order, "targeted at country", and the political-only filters: paid-for-by, delivery region and estimated audience size. Filters that Meta applies are filters you do not pay for.
- A cap that is honoured, billing that matches it.
maxAdsandmaxAdsPerQueryare hard caps. You are charged exactly once per delivered ad; duplicates, filtered-out ads, total counts, summaries and empty runs are free. - A free total count before you pay. Tick "Only count matching ads" and you get the Ad Library's own total per query at no cost, so you can size a job first.
- Honest coverage. Every query ends with
totalCount,delivered,coverage(complete,partial,empty) andstopReason(cap,end_of_results,thin_pages,blocked). You are told when the data is incomplete instead of guessing. - EU and political transparency, parsed into columns. Political ads carry spend, impressions and audience-size ranges as numbers; "Fetch ad details" adds EU (DSA) reach by country, age and gender, political age / gender and region distributions, payer / beneficiary data and the advertiser profile (page likes, Instagram followers, lifetime spend by disclaimer).
- Free cross-run memory. Name a memory and later runs return only ads you have not received yet. Schedule it and you have a change feed of a competitor's new ads.
- Derived "winning ad" filters, free. Minimum days running, minimum creative reuse (collation count), creative format, text must / must not contain, exclude pages.
This listing preselects the Instagram placement; clear the Platforms filter to get ads from every Meta surface.
Quick start (30 seconds)
- Type one or more Keywords (one per line), or paste advertiser pages (facebook.com/nike, a page ID, an Instagram profile), advertiser names, Ad Library URLs (every parameter in the URL is applied) or Ad IDs.
- Pick the Countries and any Ad Library filters you would use on the website.
- Set Max ads. Start. Download JSON, CSV or Excel from the Dataset tab, or read it through the API.
Prices in one line: $0.50 per 1,000 ads delivered, plus $0.25 per 1,000 for ad details and $0.20 per 1,000 for resolved landing pages, so $0.75 per 1,000 for an ad with details. Duplicates, filtered-out ads and total counts are free. Full breakdown below.
What you get
One item per ad. Nested objects (images, videos, cards, details) for developers, flat columns (imageUrls, spendLower, landingDomain, ...) for spreadsheets. IDs are strings (they exceed JavaScript's number range).
| Field group | Fields |
|---|---|
| Identity | adArchiveId, adLibraryUrl, adId, collationId, collationCount (how many ads share this creative), pageId, pageName, pageProfileUrl, pageProfilePictureUrl, pageLikeCount, pageCategories |
| Status and timing | isActive, startDate, endDate, daysRunning, totalActiveTimeSeconds, publisherPlatforms |
| Creative | displayFormat (IMAGE, VIDEO, CAROUSEL, MULTI_IMAGES, DCO, DPA, TEXT), adText, title, caption, linkDescription, ctaText, ctaType, images[] / imageUrls, videos[] (HD, SD, preview) / videoUrls, cards[] (carousel items with their own text, link and media), extraTexts, extraLinks, extraImageUrls, extraVideoUrls, allText |
| Destination | linkUrl (as served), landingUrl (l.facebook.com wrappers unwrapped), landingDomain, landingUtm, linkIsTemplate (catalogue placeholders such as {{product.name}}), landingResolved when resolution is on |
| Transparency (political) | isPolitical, adCategories, byline (paid for by), disclaimerLabel, spendText / spendLower / spendUpper, currency, impressionsText / impressionsLower / impressionsUpper, audienceSizeText / audienceSizeLower / audienceSizeUpper, transparencyScope (POLITICAL, EU_DSA, NONE) |
| Flags | containsDigitalCreatedMedia (AI disclosure), containsSensitiveContent, isAaaEligible, gatedType, hideDataStatus, stateMediaRunLabel, hasUserReported, regionalRegulation, brandedContent, ecCertificates, brazilTaxId |
| Details (optional) | details.advertiser (page alias, category, likes, verification, Instagram handle and followers, lifetime and weekly spend by disclaimer, entity type), details.eu (targetsEu, totalReach, reachByCountry[], reachBreakdown[] by country x age x gender, age / gender / location targeting), details.political (ageGender[], regions[] with share, singleCountry), details.payerBeneficiary[], details.isAdTakenDown, details.violationTypes |
| Provenance | searchTerm, searchCountry, searchAdType, queryKey, scrapedAt, changeType (NEW, UPDATED, DUPLICATE), isKnown, firstSeenAt, lastSeenAt, contentHash, charged |
Which transparency numbers exist depends on the ad, not on this Actor: Meta publishes spend, impressions and audience size only for ads in the "Issues, elections or politics" category, and EU reach breakdowns only for ads that were shown in the EU. For every other ad those fields are null and transparencyScope says why. Measured fill rates from live runs at build time:
| Field | Commercial ads (US, keyword) | Political ads (US) |
|---|---|---|
adText | 98% | 100% |
title | 79% | 82% |
linkUrl | 93% | 78% |
landingDomain | 92% | 78% |
ctaType | 93% | 77% |
imageUrls | 40% | 10% |
videoUrls | 25% | 55% |
pageLikeCount | 98% | 97% |
spendText | 2% | 100% |
impressionsText | 2% | 100% |
audienceSizeText | 2% | 98% |
byline | 2% | 98% |
collationCount | 80% | 93% |
endDate | 100% | 100% |
Output
type: "ad" items, type: "count" rows in count mode, type: "status" rows when something could not be done (never charged), and one type: "run-summary" item at the end with per-query totalCount, delivered, pages, coverage, stopReason, the resolved advertisers, dedup stats, exact charges, proxy statistics and fill rates.
Sample item from a live run:
{"type": "ad","adArchiveId": "1785179045778580","adLibraryUrl": "https://www.facebook.com/ads/library/?id=1785179045778580","adId": null,"collationId": "974017695598335","collationCount": 1,"isActive": false,"startDate": "2026-05-07T07:00:00.000Z","endDate": "2026-06-29T07:00:00.000Z","daysRunning": 53,"totalActiveTimeSeconds": null,"pageId": "721404351056614","pageName": "IControl: Easy Widgets Themes","pageProfileUrl": "https://www.facebook.com/61578892468353/","pageProfilePictureUrl": "https://scontent-lga3-2.xx.fbcdn.net/v/t39.35426-6/695177587_1511487320476777_920753808075...","pageLikeCount": 4501,"pageCategories": ["Topic"],"pageIsDeleted": false,"publisherPlatforms": ["FACEBOOK","INSTAGRAM","AUDIENCE_NETWORK","MESSENGER","THREADS"],"displayFormat": "IMAGE","adText": "❤️Aesthetic presets for your phone✨","title": "🥰a FREE and personalized APP for you","caption": "play.google.com","linkDescription": null,"linkUrl": "http://play.google.com/store/apps/details?id=com.icontrol.easy.widgets.themes","landingUrl": "http://play.google.com/store/apps/details?id=com.icontrol.easy.widgets.themes","landingDomain": "play.google.com","landingUtm": null,"linkIsTemplate": false,"ctaText": "Install now","ctaType": "INSTALL_MOBILE_APP","images": [{"url": "https://scontent-lga3-3.xx.fbcdn.net/v/t39.35426-6/689490050_1634784394244050_406178336346...","resizedUrl": "https://scontent-lga3-2.xx.fbcdn.net/v/t39.35426-6/691720374_1271927545153646_343053186879..."}],"imageUrls": ["https://scontent-lga3-3.xx.fbcdn.net/v/t39.35426-6/689490050_1634784394244050_406178336346..."],"videos": [],"videoUrls": [],"videoPreviewImageUrls": [],"cards": [],"cardCount": 0,"extraTexts": [],"extraLinks": [],"extraImageUrls": [],"extraVideoUrls": [],"allText": "❤️Aesthetic presets for your phone✨\n🥰a FREE and personalized APP for you\nplay.google.com","adCategories": ["UNKNOWN"],"isPolitical": false,"byline": null,"disclaimerLabel": null,"spendText": null,"spendLower": null,"spendUpper": null,"currency": null,"impressionsText": null,"impressionsLower": null,"impressionsUpper": null,"impressionsIndex": -1,"audienceSizeText": null,"audienceSizeLower": null,"audienceSizeUpper": null,"transparencyScope": "NONE","targetedOrReachedCountries": [],"countryIsoCode": null,"gatedType": "ELIGIBLE","isAaaEligible": true,"containsDigitalCreatedMedia": false,"containsSensitiveContent": false,"hideDataStatus": "NONE","stateMediaRunLabel": null,"hasUserReported": false,"reportCount": null,"isReshared": false,"brandedContent": null,"event": null,"brazilTaxId": null,"additionalInfo": null,"ecCertificates": [],"regionalRegulation": {"finserv": {"is_deemed_finserv": false,"is_limited_delivery": false},"tw_anti_scam": {"is_limited_delivery": false}},"searchTerm": "nike","searchCountry": "US","searchAdType": "ALL","queryKey": "term:nike:US","scrapedAt": "2026-09-01T18:30:38.204Z","changeType": "NEW","isKnown": false,"firstSeenAt": "2026-09-01T18:30:38.204Z","lastSeenAt": "2026-09-01T18:30:38.204Z","charged": true}
How much does it cost to scrape Instagram ads?
You pay per event, never per hour, and every price below is the current base price on this listing.
| Charge event | What triggers it | Price |
|---|---|---|
Ad delivered (ad-result) | One ad record delivered to the dataset | $0.50 per 1,000 |
Ad details fetched (ad-details) | Advertiser profile, EU (DSA) reach breakdown, political age / gender / region insights and payer data for one ad, when "Fetch ad details" is on | $0.25 per 1,000 |
Landing page resolved (landing-page-resolved) | Final landing URL and domain after redirects, when "Resolve landing pages" is on, charged only when a page answered | $0.20 per 1,000 |
Actor Start (apify-actor-start) | Apify's standard start event, once per run per gigabyte of memory. This Actor defaults to 256 MB, so it is one event per run | $0.05 per 1,000 runs ($0.00005 per run) |
An ad with details costs $0.75 per 1,000 ads.
Always free: duplicates inside a run, ads the memory already knows across runs, ads dropped by the post-filters, the total counts from "Only count matching ads", status rows, the run summary, and a run that finds nothing.
Worked examples (start event included): 500 ads for three keywords = $0.25; 2,000 competitor ads with details = $1.50; a daily re-run under a memory name that finds 8 new ads among 300 known ones = $0.00405; a run that finds nothing = $0.00005.
Input reference
| Input | What it does |
|---|---|
| Keywords, Keyword matching | The Ad Library search box. "Exact phrase" is the quoted search. |
| Advertiser pages, Advertiser names | Page IDs, page URLs, Instagram profiles or plain names (resolved through the Ad Library's own advertiser lookup; the run summary lists the candidates). Returns the page's "See all ads" view. |
| Ad Library URLs | Paste a URL from your browser; keyword, page, country, ad type, status, media type, platforms, languages, dates, sort and political filters are all read from it. ?id= URLs fetch that single ad. |
| Ad IDs | Library IDs to fetch directly (current status, dates, creative, political numbers). Unknown IDs are reported and free. |
| Countries | Any of the 250 countries or All countries. Several countries = one query each (fair share of the cap). EU expands to the 27 member states (API). |
| Ad category | All, political, housing, employment, financial (the regulated categories). Political ads are the ones with spend and impressions. |
| Active status, Media type, Platforms, Ad languages | Exactly the website's filters. |
| Impressions within / from / to | The website's "Impressions by date": ads that were shown in the window (an ad that started earlier and is still running matches). |
| Sort | Default relevance, impressions high to low / low to high, most recent (grouped by launch month), as the website offers. |
| Only ads targeted at the country | The is_targeted_country switch. |
| Paid for by, Delivery regions, Audience size | Political-only filters. Region names as the website shows them ("California"). Audience buckets: 100-1K, 1K-5K, 5K-10K, 10K-50K, 50K-100K, 100K-500K, 500K-1M, above 1M. |
| Minimum days running, Minimum creative reuse, Creative formats, text filters, Exclude pages | Free post-filters. |
| Max ads, Max ads per query | Hard caps on delivered, charged ads. maxItems: 0 through the API means no cap. |
| Only count matching ads | Free preflight: one count row per query, no ads, no charge. |
| Fetch ad details, Resolve landing pages | Paid add-ons, charged only when data came back. |
| Memory name, Also return already-known ads, Reset memory | Cross-run dedup (named key-value store ads-library-memory-v2-<name> in your account). Known ads are never charged. |
Stop after N fully-known pages (maxKnownPages) | Optional, off by default (0). For scheduled change feeds: stop a query after N consecutive result pages that contain only ads the memory already knows (stopReason known_pages), instead of paging to the cap. Cheaper polls; pair it with the "Most recent" sort so new ads are never behind known ones. |
| Proxy, Parallel queries, IP retries, Stop after N empty pages | Advanced. Leave the defaults. |
Using the API
Same input as the form.
curl -X POST "https://api.apify.com/v2/acts/automation_craft~instagram-ads-library-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"searchTerms": ["skincare"],"countries": ["US"],"activeStatus": "active","mediaType": "video","publisherPlatforms": ["instagram"],"deliveredWithinDays": "30","maxAds": 100}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation_craft/instagram-ads-library-scraper').call({advertiserNames: ['Nike'], countries: ['ALL'], fetchAdDetails: true, maxAds: 200, memoryName: 'nike-watch',});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.filter((i) => i.type === 'ad').length, 'ads');
from apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("automation_craft/instagram-ads-library-scraper").call(run_input={"searchTerms": ["vote"], "countries": ["US"], "adType": "political_and_issue_ads", "bylines": ["VOTEVETS"], "fetchAdDetails": True, "maxAds": 50,})ads = [i for i in client.dataset(run["defaultDatasetId"]).iterate_items() if i["type"] == "ad"]
Input keys are tolerant: country names or codes, enum labels or ids, lowercase or uppercase, strings or arrays, and the common aliases other scrapers use (keyword, maxItems, startUrls, period, startDateMin) are accepted.
Recipes
- Competitor monitoring: advertiser pages +
memoryName, scheduled daily. Only new ads arrive;changeType: UPDATED(with "Also return already-known ads") flags ads whose status, dates or creative changed. - Winning ads: keyword +
activeStatus: active+minDaysRunning: 30+minCollationCount: 3+sortBy: total_impressions_desc. - Political spend research:
adType: political_and_issue_ads+bylinesorregions+fetchAdDetails: truefor age / gender / region distributions and lifetime spend by disclaimer. - EU DSA audits: an EU country +
fetchAdDetails: truefor reach by country, age and gender and the declared targeting. - Sizing a job: the same input with
onlyTotalCount: truefirst (free).
What this Actor does NOT do
- It does not log in and never asks for cookies or tokens, so it only sees what the public Ad Library shows. Spend, impressions and audience size exist for political ads only; EU reach data only for ads shown in the EU. Meta's ranges (">$1M", "100K-500K") are ranges, not exact numbers.
- Very broad keywords: the Ad Library's own result pages thin out after a few hundred ads (
stopReason: thin_pages,coverage: partial). Split the job by country, platform, date window or advertiser page for complete coverage. - It does not download media files; it delivers the CDN URLs (which expire after some days, so download what you need).
- It does not read the aggregate "Ad Library report" spend tables, branded-content listings or the collation "summary" panel; open an issue if you need them.
- Meta rate-limits roughly half of all residential IPs. The Actor rotates IPs automatically and the run summary shows
proxy.blockedIps; a query that cannot get a clean IP is reported ascoverage: blockedand costs nothing.
FAQ
Is there a separate Instagram Ad Library?
No. Instagram ads sit in the Meta Ad Library next to Facebook, Messenger, Audience Network, WhatsApp and Threads ads. This listing preselects the Instagram placement, so you search that library and get Instagram ads back.
Can I filter the Meta Ad Library to Instagram placements only?
Yes, that is the "Platforms" filter and it is preselected here. Clear it to get ads from every Meta surface. Each ad carries publisherPlatforms, so you can always check where it ran.
How do I download a competitor's Instagram ad creatives and videos?
Put the advertiser in "Advertiser pages" or "Advertiser names". Every ad returns imageUrls, videoUrls (HD, SD and preview) and cards[] for carousels, with the headline, primary text, caption and call to action. The Actor delivers the CDN URLs rather than the files, and those URLs expire after some days, so fetch what you want to keep.
How can I tell which Instagram ads are working for a brand?
Use the free post-filters: "Minimum days running" (an ad still live after weeks is usually paying for itself) and "Minimum creative reuse" (collationCount, how many ads run the same creative), together with "Active ads only". Meta does not publish spend or impressions for commercial ads, so those two are the signals that exist.
Can I scrape Instagram ads without an account or an API key?
Yes. No login, no cookies, no tokens. The Actor reads the public Ad Library through Apify residential proxies and pays for itself per ad delivered.
How much will it cost to scrape 1,000 Instagram ads?
$0.50 for 1,000 ads as delivered, or $0.75 if you also switch "Fetch ad details" on, plus Apify's start event of $0.00005 for the run itself. Ads your memory already knows, ads your post-filters drop and the free total count are not charged, so a scheduled watch pays only for what is new.
Why does this Actor run with limited permissions?
Least privilege. It only reads and writes its own storages: the run's dataset, and, when you set a memory name, a key-value store it creates itself (ads-library-memory-v2-<your memory name>). It never needs access to the rest of your Apify account, so it does not ask for it, and schedules and API calls do not raise an approval prompt.
Changelog
- 1.1.0: cheaper runs, same results; Apify's standard start event ($0.05 per 1,000 runs) added, every other price unchanged. The first page a run loads now provides the session tokens (no second page load per run); the memory is written only when it changed; runs default to 256 MB (enough for this HTTP-only engine; up to 1024 MB can still be requested); optional
maxKnownPagesfor cheaper scheduled change feeds (off by default). No input or output changes; ad, details and landing-page prices unchanged. - 1.0.0: first release. Keyword, page, advertiser-name, URL and ad-ID modes; every Ad Library filter; exact caps with fair share; free total count; post-filters; cross-run memory; ad details (EU, political, advertiser); landing-page resolution; per-query coverage reporting.
More data tools by Automation Craft
Same engine, other placements:
Other marketing and ecommerce data: