# Instagram Ads Scraper: Ad Library & Creatives (`deepmine/instagram-ads-scraper`) Actor

Instagram ads scraper for the Meta Ad Library: paste an advertiser's Instagram or Facebook link, a page id or a name, or type keywords, and get every Instagram ad with its copy, images, videos, landing page, CTA, start date, days running and variants. For competitor creative research. No login.

- **URL**: https://apify.com/deepmine/instagram-ads-scraper.md
- **Developed by:** [DeepMine](https://apify.com/deepmine) (community)
- **Categories:** Social media, Marketing, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.15 / 1,000 ads

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Instagram Ads Scraper

**Instagram ads scraper** for the Meta Ad Library: paste a brand's Instagram link (or its Facebook page, page id or name), or type a keyword, and get one clean row per ad it runs on Instagram, with the creative, ad text, headline, button, landing page, format, start date and days running, no login.

| Advertiser | Ad text | Headline | Button | Format | Started | Days active |
|---|---|---|---|---|---|---|
| Gymshark | Get ready to meet SoftSense™, our brand new fabric… | New SoftSense™ drops 22nd Oct | Learn more | Dynamic creative | 2026-10-20 | 0 |
| Gymshark | Sam Sulek's collection, made of the pieces he trus… | Oct 22nd. Gymshark x Sam Sulek | Learn more | Dynamic creative | 2026-10-20 | 0 |
| Gymshark | Set your reminders for when NEW SoftSense™ drops o… | Set your reminders ⏰ | Learn more | Dynamic creative | 2026-10-20 | 0 |

<sub>Collected 2026-10-20 from the prefilled run (`https://www.instagram.com/gymshark/`, US, newest first: the launch ads Gymshark started that day; Meta counted 924 Gymshark ads on Instagram). Every row also has the creative's picture, the video file, the landing page and the ad's Ad Library link.</sub>

**$0.19 per 1,000 ads** from advertiser searches on Starter ($0.22 Free, $0.17 Scale, $0.15 Business); keyword searches $0.59 per 1,000 ($0.62 Free, $0.57 Scale, $0.55 Business). The prefilled run (100 ads) costs about $0.02.

Only ads Meta shows on **Instagram** (feed, Stories, Reels, Explore), from the public Ad Library: no Instagram or Facebook account, no cookies. Add **ad details** for the advertiser's verification and Instagram account and, for ads shown in the EU or UK, reach by country, targeted ages and gender, payer and beneficiary.

### What you can do with it

- **Competitor creative research**: paste your competitors' Instagram links and get every ad they run on Instagram right now, newest first, with the video and image files, hooks, headlines and landing pages.
- **Launch tracking**: see the ads a brand started today and how many variants (*collationCount*) it tests per creative.
- **Winning ads**: sort by *Days active*: ads that keep running for weeks are usually the ones that work.
- **Niche research**: search a keyword ("protein powder", "skincare") to find every brand advertising it on Instagram.

### Input

| Field | What it does |
|---|---|
| **Advertisers** | Brands whose Instagram ads you want: an Instagram profile link (`instagram.com/gymshark`), an `@handle`, a Facebook page link, a page id (`129669023798560`), an advertiser's Ad Library link, or the name as it shows on its ads. |
| **Keywords** | Words to find Instagram ads by, as in the Ad Library search box. One search per line. |
| **Country** | Two-letter code where the ads ran (`US`, `GB`, `DE`, ...) or `ALL` (US in the form, `ALL` if left out). |
| **Max ads per search** | Stop each advertiser or keyword after this many ads (100 in the form, 200 if left out, up to 10,000). You pay per ad. |
| **Include ad details** | Adds the advertiser's profile and EU/UK reach data to each ad, at the with-details price (one more request per ad, so slower). |

Under **Filters**: ad status (active, inactive or both), media type, the Ad Library's date filter (*Shown on or after / before*: ads shown in that period, whatever day they started), exact phrase for keywords, and ad category (political and issue ads carry spend and impressions). Under **More inputs**: Ad Library links copied from your browser (their filters are used; the platform is always Instagram) and single ads by their Library ID.

An Instagram link is read as the brand's Facebook page of the same username (the Ad Library lists advertisers by their Facebook page); when there is none, the run looks the brand up by name. The run's OUTPUT says which page each advertiser was read as. Example:

```json
{
  "advertisers": ["https://www.instagram.com/gymshark/", "@drinkag1", "15087023444"],
  "searchQueries": ["protein powder"],
  "country": "US",
  "maxAdsPerQuery": 500
}
```

### Output

One row per ad. Advertiser searches come **newest first** (the ads a brand started today, then yesterday, ...): each advertiser's ads are sorted once its read is done, so they arrive together. Keyword searches come in Meta's own order (most impressions first), page by page. An ad found by several searches appears once, under the first search that found it. Every row is an ad Meta shows on Instagram: `platforms` always includes Instagram (often with Facebook, Threads and others: one ad can run on several).

A real row from the prefilled run (2026-10-20), clean part (media links cut):

```json
{
  "image": "https://scontent-dfw6-2.xx.fbcdn.net/v/t39.35426-6/856155994...",
  "pageName": "Gymshark",
  "adText": "Get ready to meet SoftSense™, our brand new fabric that responds to your body in real time 🧘‍♀️💖 Drops Thurs 22nd Oct, 12pm MDT.",
  "adTextSnippet": "Get ready to meet SoftSense™, our brand new fabric…",
  "headline": "New SoftSense™ drops 22nd Oct",
  "adLibraryUrl": "https://www.facebook.com/ads/library/?id=1420136789651374",
  "landingUrl": "https://www.gymshark.com/pages/soft-sense",
  "ctaText": "Learn more",
  "format": "Dynamic creative",
  "platforms": ["Facebook", "Instagram", "Audience Network", "WhatsApp", "Threads"],
  "isActive": true,
  "pageLikes": 2230257,
  "collationCount": 6,
  "adsCount": 5,
  "daysActive": 0,
  "startedAt": "2026-10-20",
  "lastShownAt": "2026-10-20",
  "rank": 1,
  "totalCount": 924,
  "videoUrl": null,
  "pageUrl": "https://www.facebook.com/Gymshark/",
  "adArchiveId": "1420136789651374",
  "pageId": "129669023798560",
  "searchInput": "https://www.instagram.com/gymshark/",
  "scrapedAt": "2026-10-20T16:47:27Z"
}
```

Clean fields, in row order:

- `image`: the creative's picture: its first image, the video's preview frame, or the first card's image.
- `pageName`: the advertiser.
- `adText`, `adTextSnippet`: the ad's primary text in full, and its first 50 characters on one line.
- `headline`: the headline under the creative.
- `adLibraryUrl`: the ad in the Meta Ad Library.
- `landingUrl`: where the ad's button leads.
- `ctaText`: the button text, e.g. *Shop now*.
- `format`: Image, Video, Carousel, Dynamic creative, Catalog, ...
- `platforms`: where the ad runs: Instagram, plus Facebook, Messenger, Threads, Audience Network, WhatsApp when it runs there too.
- `isActive`: still running when the run read it.
- `pageLikes`: likes of the advertiser's Facebook page.
- `collationCount`: how many ads use this creative and text (the variants a brand tests). Meta says it on one ad of each group, so it's often `null`.
- `adsCount`: how many ads Meta lists together with this one (one result group).
- `daysActive`: days from `startedAt` to `lastShownAt`.
- `startedAt`, `lastShownAt`: the day the ad started, and the last day it ran (the run's day for active ads).
- `rank`: the ad's place in its search.
- `totalCount`: Meta's count of Instagram ads matching the search (`50001` means 50,000+).
- `videoUrl`: the ad's video file, for video ads.
- `cards`: for carousel, dynamic and catalog ads, every card's headline, text, description, landing page, button, image and video.
- `pageUrl`, `adArchiveId`, `pageId`: the advertiser's Facebook page, the ad's Library ID and the page id.
- `searchInput`: the advertiser, keyword or link that found the ad.
- `scrapedAt`: when the run started (UTC).

With **Include ad details**, these come after `pageUrl`: `detailsStatus` (OK, Not available, Failed), `isPageVerified`, `instagramUrl` and `instagramFollowers` (the advertiser's Instagram account), `euReach`, `ukReach`, `targetAges`, `targetGender`, `reachByCountry`, `payer` and `beneficiary` (EU/UK ads). Political and issue ads also carry `spend`, `spendMin`, `spendMax`, `currency`, `impressions`, `reachEstimate` and `paidFor`.

After `scrapedAt`, every row also has Meta's full ad record under apify/facebook-ads-scraper's field names (`adArchiveID`, `pageID`, `snapshot` with every image and video variant in HD and SD, `publisherPlatform`, `startDateFormatted`, `categories`, ...), so pipelines built on that Actor keep working. The Console tables show the clean fields.

**Images and videos expire.** `image`, `videoUrl` and the media links in `snapshot` are Meta's signed CDN links; they stop working after a few days, so download what you want to keep.

The run's **OUTPUT** record lists every search with Meta's count of its Instagram ads (`metaCount`), the ads delivered and why it stopped (`complete`, `maxAds`, `chargeLimit`, or a failure: `blocked`, `error`, `incomplete`).

### How advertiser searches are read

An advertiser's Instagram ads are read day by day, newest first, mostly over Apify's datacenter IPs (Meta's per-day counts say how many ads each day holds), and only the busy days that need it are paged over residential IPs. That's why advertiser searches cost less than keyword searches, whose results must be paged one by one in Meta's order. With *Max ads per search* below the brand's total, you get its newest days whole (the newest ads first). Measured on the platform (2026-10-20): AG1, all 423 of the Instagram ads Meta counts; Gymshark, 917 of 924; Liquid Death, 274 of 277 (Meta counts a few ads that none of its lists show).

### Pricing

Pay per ad, by your Apify plan. No start fee, no monthly fee, platform usage included.

| Per 1,000 ads | Free | Starter | Scale | Business |
|---|---|---|---|---|
| Ad from an advertiser search | $0.22 | $0.19 | $0.17 | $0.15 |
| Ad from a keyword search | $0.62 | $0.59 | $0.57 | $0.55 |
| Advertiser search ad with details | $0.37 | $0.34 | $0.32 | $0.30 |
| Keyword search ad with details | $0.77 | $0.74 | $0.72 | $0.70 |

- An advertiser search is one given in *Advertisers* (or an advertiser's Ad Library link, or an ad by its Library ID). A keyword search, and an advertiser search with a date filter (*Shown on or after / before*), are read page by page and cost the keyword price.
- Ad details add a flat $0.15 per 1,000, only for ads whose details came.
- Set a maximum cost per run in the run options: the run stops before it would go past it and keeps what it collected (`OUTPUT.chargeLimitReached` is then `true`).

### Limitations

- Page transparency (the page's creation date, name changes, admin countries) isn't included yet.
- An Instagram link works when the brand's Facebook page has the same username or the brand's ads carry its Instagram name; otherwise paste its Facebook page link or page id (the Ad Library link of the advertiser works too).
- Spend and impressions exist only for political and issue ads (Meta's rule); commercial ads have none in any Ad Library tool.

### FAQ

**Do I need an Instagram or Facebook account?** No. Everything comes from the public Meta Ad Library, without logging in.

**Are these only Instagram ads?** Yes: every search asks Meta for ads shown on Instagram, and an ad Meta lets through anyway that isn't on Instagram is dropped and not charged.

**How many ads can I get?** Set *Max ads per search* up to 10,000. Several advertisers and keywords run in parallel.

### Related Actors

- **Facebook ads too, or monitoring?** [Meta Ad Library API](https://apify.com/deepmine/meta-ad-library) searches every platform, and [Facebook Ads Monitor](https://apify.com/deepmine/facebook-ads-monitor) returns only the new ads of your competitors on each scheduled run.
- **Only video ads?** [Facebook Video Ads](https://apify.com/deepmine/facebook-video-ads) returns HD and SD MP4 links of Facebook and Instagram video ads.
- **Winning products?** [Meta Ad Spy](https://apify.com/deepmine/meta-ad-spy) finds long-running ads and winning products by keyword.
- **The brand's organic Instagram?** [Instagram Profile Scraper](https://apify.com/deepmine/instagram-profile-scraper) and [Instagram Reels Scraper](https://apify.com/deepmine/instagram-reels-scraper) return its profile, posts and Reels.

### Feedback

Found a bug or missing a field? Open an issue on the **Issues** tab and we'll look at it within 48 hours. Happy with the data? A short review on the Store helps others find this Actor.

# Actor input Schema

## `advertisers` (type: `array`):

Brands whose Instagram ads you want: an Instagram or Facebook profile link (instagram.com/gymshark), an @handle, a page id, an advertiser's Ad Library link, or the name as it shows on its ads. Newest ads first.

## `searchQueries` (type: `array`):

Words to find Instagram ads by, as you'd type them in the Ad Library search box, e.g. protein powder. One search per line. A keyword search costs more per ad than an advertiser search (see Pricing).

## `country` (type: `string`):

Two-letter code of the country where the ads ran (US, GB, DE, ...), or ALL for every country.

## `maxAdsPerQuery` (type: `integer`):

Stop each advertiser, keyword or link after this many ads. You pay per ad, so this caps each search's cost. Up to 10,000.

## `includeAdDetails` (type: `boolean`):

Also read each ad's details: the advertiser's verification, Instagram account and followers and, for ads shown in the EU or UK, reach by country, ages and gender, payer and beneficiary. Charged only for ads whose details came.

## `activeStatus` (type: `string`):

Only ads running now, only ads that stopped, or both.

## `mediaType` (type: `string`):

Only ads with this kind of media.

## `dateFrom` (type: `string`):

Only ads shown on or after this date, whatever day they started (the Ad Library's own filter), e.g. 2026-10-01. An advertiser search with dates is priced as a keyword search. Empty = any time.

## `dateTo` (type: `string`):

Only ads shown on or before this date. Empty = up to today.

## `exactPhrase` (type: `boolean`):

Match the keywords as an exact phrase instead of in any order.

## `adType` (type: `string`):

All ads, or only ads about social issues, elections or politics (these carry spend and impressions ranges).

## `startUrls` (type: `array`):

Searches copied from facebook.com/ads/library in your browser. The link's own filters (country, status, media, dates) are used; the platform is always Instagram.

## `adIds` (type: `array`):

Single ads by their Library ID (e.g. 1234567890123456) or their Ad Library link with ?id=. Priced as advertiser ads.

## `proxyConfiguration` (type: `object`):

Leave as is: residential proxies (US) are needed past the first page of results; the first pages are read on cheaper datacenter IPs on their own.

## Actor input object example

```json
{
  "advertisers": [
    "https://www.instagram.com/gymshark/"
  ],
  "country": "US",
  "maxAdsPerQuery": 100,
  "includeAdDetails": false,
  "activeStatus": "active",
  "mediaType": "all",
  "exactPhrase": false,
  "adType": "all",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "advertisers": [
        "https://www.instagram.com/gymshark/"
    ],
    "country": "US",
    "maxAdsPerQuery": 100,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("deepmine/instagram-ads-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "advertisers": ["https://www.instagram.com/gymshark/"],
    "country": "US",
    "maxAdsPerQuery": 100,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("deepmine/instagram-ads-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "advertisers": [
    "https://www.instagram.com/gymshark/"
  ],
  "country": "US",
  "maxAdsPerQuery": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call deepmine/instagram-ads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,deepmine/instagram-ads-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/eYuTVlFjp4eqzErhG/builds/xNw0JIgEVt2GIe450/openapi.json
