Instagram Ads Library Scraper - Meta Ad Library
Pricing
Pay per event
Instagram Ads Library Scraper - Meta Ad Library
Scrape Instagram ads from Meta's Ad Library by brand, page ID or Ad Library URL. Filters to Instagram placements and flags the ads that ran on Instagram and nowhere else, with creative text, images, videos, CTA, run dates and placement spread.
Instagram Ads Library Scraper
Pull the ads a brand is running on Instagram, with the creative text, the images and videos, the call to action, the run dates and the full placement spread. Search by brand name, by Meta page ID, or by pasting an Ad Library URL.
The one thing to know before you start: Instagram does not publish an ad
library of its own. There is no instagram.com/ads/library. Every Instagram ad
is disclosed through Meta's Ad Library, mixed in with Facebook, Messenger,
Audience Network and Threads placements, and the only thing that separates them
is a publisher_platform field on each ad. This Actor is that separation, done
properly. Nothing here comes from a source that does not exist.
Why not just use a Facebook Ad Library scraper
Because a Meta-wide scraper hands you one undifferentiated list and leaves the interesting question unanswered: which of these were made for Instagram?
:
| Advertiser | Market | Live ads | Ran on Instagram | Instagram and nowhere else |
|---|---|---|---|---|
| Nike | US | 59 | 59 | 20 |
| Zalando | NL | 51 | 51 | 10 |
Nearly everything a big brand runs touches Instagram, so "is it on Instagram" is barely a filter. The signal is the third column. Those 20 Nike creatives are ads someone deliberately built for the Instagram format and shipped nowhere else, and in a combined list they are indistinguishable from a Facebook banner that happened to get an Instagram placement.
This Actor puts that on every row as is_instagram_only, with also_on naming
the other surfaces and platform_count giving the breadth at a glance. An ad on
five placements is a budget decision. An Instagram-only ad is a creative one.
What you get
One row per ad creative. The fields worth knowing about:
is_instagram_only— true when Instagram was the ad's only placement.also_on— the other placements the same creative ran on,nullwhen Instagram-only. Meta addedTHREADSto this list without announcement, and unrecognised surfaces are passed through as themselves rather than dropped.platform_count— how many surfaces the ad ran on.body_text,title,caption,link_description— the creative copy.images,videos— media URLs.cta_text,cta_type,link_url— the call to action and destination.start_date,end_date,total_active_time— how long it has run. A creative still live after months is one that is working.page_name,page_id,page_like_count,page_categories— the advertiser.collation_id,collation_count— Meta groups the variants of one creative; this is how you tell a 12-variant test from 12 separate ads.contains_digital_created_media— Meta's AI-generated-content disclosure.byline,disclaimer_label,state_media_run_label— the regulatory labels, on ads that carry them.
What you do not get, and why
Spend and impressions are empty for commercial ads. This is Meta's policy,
not a gap in the scraper: spend, currency and reach_estimate are published
for political and issue ads only. Every commercial ad returns null there. Any
tool promising you Instagram ad spend for an ordinary brand is either guessing
or reselling an estimate. The fields are present and populate correctly when the
ad is political.
Targeting is not published either. Meta discloses targeted_or_reached_countries
and nothing finer for commercial advertising.
Input
| Field | What it does |
|---|---|
search | Advertiser name, e.g. nike |
placement | instagram (default), instagram_only, or all |
country | Two-letter market code, e.g. US, NL. Inventory differs per country |
page_id | Meta page ID, more precise than a name when brands share one |
url | Paste an Ad Library URL; advertiser, country and status are read from it |
active_only | Only ads running right now. Off includes stopped ads |
max_ads | Ceiling on ads fetched before filtering, so ask for more than you need |
max_ads is worth a second look. The Instagram filter runs after fetching, so
requesting 100 ads with placement: instagram_only returns however many of
those 100 were Instagram-exclusive, not 100 Instagram-exclusive ads.
Typical uses
- Creative research. Pull a competitor's Instagram-only ads and see what they build for the format: aspect ratios, hook length, whether they run Reels creative or repurposed feed assets.
- Longevity as a proxy for performance. Sort by
total_active_time. Brands kill ads that do not work, so the creative still running after ninety days is the one that earned its budget. - Placement strategy. Compare
platform_countacross competitors. A brand running everything cross-placement is buying reach; one with a large Instagram-only share is treating Instagram as its own channel. - Variant testing. Group on
collation_idto see how many versions of a creative a brand is testing at once. - Compliance and disclosure monitoring.
contains_digital_created_media,bylineandstate_media_run_labelare how Meta labels AI-generated creative, paid-for-by lines and state media.
Notes on behaviour
An empty result is a successful run, not a failure. When an advertiser is live
on Meta but runs nothing on the placement you asked for, the run reports a
no_instagram_ads note saying exactly that, rather than handing you an empty
dataset that looks like a broken scrape.
Ad inventory is per country. Searching US and NL for the same brand returns
different ads, and often different creative for the same campaign, so set
country deliberately rather than leaving it at the default.
Related Actors
If you want the whole Meta library rather than the Instagram slice, use the Facebook Ads Scraper - Meta Ad Library Actor instead. For Instagram organic content, profiles, posts, hashtags and locations, see the Instagram scrapers in the same account.