# Snapchat Ads & Media Asset Catalog Scraper (`simpleapi/snapchat-ads-scraper`) Actor

Snapchat Ads & Media Asset Catalog Scraper extracts public Snapchat Ad Library campaigns and media assets, including images, videos, advertisers, ad copy, landing pages, and campaign details. Ideal for competitor analysis, creative research, ad monitoring, and marketing insights.

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

## Pricing

from $2.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### Snapchat Ads Scraper — Media Asset Catalog

Snapchat Ads & Media Asset Catalog Scraper turns the public Snapchat Ads Library into a downloadable media-asset catalog — every ad enriched with a ready-to-download filename, media kind, file extension, and an optional live reachability check on the actual download URL, plus per-advertiser asset-count summary rows. It's built for creative and competitive intelligence teams building a swipe file of competitor ad creative, ad-ops teams verifying media links are actually live before archiving them, and market researchers who want a per-advertiser breakdown of how much video versus image creative a brand is running. No Snapchat account is required. Every section below documents an input, an output field, or exactly how the media enrichment and reachability check work.

### What is Snapchat Ads & Media Asset Catalog Scraper?

This Actor searches Snapchat's public Ads Library by advertiser/brand keyword, paginating through Snapchat's own cursor-based feed, and for every ad computes a downloadable-asset record — a suggested filename, the media kind (video/image), the file extension, and (optionally) a live HEAD-request check confirming the download link actually resolves.

Key capabilities, read from the source:

- **Real media enrichment computed from actual ad data.** `compute_media_fields()` derives `mediaAvailable`, `mediaKind`, `mediaExtension`, and `suggestedFilename` from the ad's own `snapMediaDownloadLink`/`snapMediaType` fields — nothing here is guessed when the underlying media link is absent.
- **Optional live reachability verification.** `validateMedia` sends a lightweight HEAD request to each ad's media download URL and records `mediaUrlReachable` (true/false) and the real `mediaContentType` response header — when disabled, both fields are explicitly `null` rather than left implying "checked and clean."
- **Per-advertiser asset-count summaries that reflect every ad seen, not just kept ones.** A `recordType: "asset_summary"` row per advertiser tallies `adsTotal`, `adsWithMedia`, `videoAssets`, and `imageAssets` — counted across every ad the search encountered, even ones filtered out of the ad rows by `onlyWithMedia`.
- **A downloadable-only default filter.** `onlyWithMedia` (on by default) keeps only ads that carry a real downloadable media asset in the ad-row output — useful since not every ad in the library has a directly downloadable creative asset.
- **Proxy escalation that sticks once engaged.** The proxy manager starts direct, escalates to datacenter then residential on a rate-limit challenge, and stays on residential for the remainder of the run once reached.
- **Bulk multi-advertiser search in one run.** `searchQueries` accepts multiple brand names processed independently, or a single empty string to fetch all ads in the library filtered only by country/date/status.

### What data can I extract with Snapchat Ads & Media Asset Catalog Scraper?

Every field below is read directly from `extract_ads()` and `compute_media_fields()` in the source — the dataset's default view surfaces all 27 as table columns.

#### Ad rows (`recordType: "ad"`)

| Field | Example Value | Notes |
| --- | --- | --- |
| `id` / `adName` / `adType` | ad identifiers | |
| `payingAdName` / `accountName` / `brandName` / `profileName` / `profileLogoUrl` | advertiser identity | |
| `headline` | ad copy | |
| `totalImpressions` / `adStatus` / `startDate` | reach and delivery info | |
| `snapMediaDownloadLink` / `snapMediaType` | raw media reference | Snapchat's own fields |
| `mediaAvailable` | `true` | Whether a downloadable asset exists at all |
| `mediaKind` | `"video"` or `"image"` | Derived from `snapMediaType` |
| `mediaExtension` / `suggestedFilename` | `"mp4"` / `"ikea_ad_abc123.mp4"` | Computed, ready-to-use for a download step |
| `mediaUrlReachable` | `true` or `null` | `null` when `validateMedia` is off — never guessed |
| `mediaContentType` | `"video/mp4"` | Real HTTP response header from the HEAD check |

#### Asset summary rows (`recordType: "asset_summary"`)

| Field | Example Value | Notes |
| --- | --- | --- |
| `advertiserName` / `searchQuery` | grouping keys | |
| `adsTotal` | `24` | Every ad seen for this advertiser, regardless of filters |
| `adsWithMedia` | `19` | How many carried a downloadable asset |
| `videoAssets` / `imageAssets` | `12` / `7` | Split by media kind |

### Why not build this yourself?

The Snapchat Ads Library has no public API for programmatic bulk access — reaching it means replicating its internal cursor-paginated search endpoint and its exact request-body shape for country/status/date filtering, none of which is documented externally. Confirming that a media download link is genuinely still live requires an actual HEAD request per asset, since Snapchat's search response includes the link regardless of whether the underlying asset has since expired or moved — skipping that check means building a "catalog" that silently includes dead links. This Actor performs that verification and is explicit — via a `null` rather than a guessed `true`/`false` — whenever the check wasn't requested.

### How to use data extracted from Snapchat Ads & Media Asset Catalog Scraper?

#### Creative and competitive intelligence

Search a competitor's brand name with `onlyWithMedia` on to build a downloadable swipe file of their active ad creative, using `mediaKind` to separate video from image assets for a format-specific creative review.

#### Ad-ops link verification

Turn on `validateMedia` before archiving a batch of ad assets to catch dead download links (`mediaUrlReachable: false`) before they end up in a broken asset library.

#### Market and category research

Run several brand names in one `searchQueries` batch and compare each advertiser's `asset_summary` row to see who's running the most video-heavy creative strategy in a category.

#### AI agents and creative pipelines

Because `suggestedFilename` and `mediaExtension` are pre-computed, an agent can pass `snapMediaDownloadLink` directly to a download step without any additional filename logic.

### 🔼 Input sample

| Parameter | Required | Type | Description | Example Value |
| --- | --- | --- | --- | --- |
| `searchQueries` | **Yes** | array | Advertiser/brand names to search. An empty string fetches all ads. | `["Ikea"]` |
| `maxItems` | No | integer (1–10000) | Max ads to fetch per search keyword. Default `10`. | `50` |
| `country` | No | string enum | Restrict to one EU country. Empty = all countries. | `"DE"` |
| `status` | No | string enum | `""` (any), `ACTIVE`, or `PAUSED`. | `"ACTIVE"` |
| `startDate` / `endDate` | No | string (date) | Only ads with a start date in this range (`YYYY-MM-DD`). | `"2026-01-01"` |
| `onlyWithMedia` | No | boolean | Keep only ads with a downloadable asset in ad rows. Summary rows always count everything. Default `true`. | `true` |
| `validateMedia` | No | boolean | Live HEAD-check each media URL. Default `true`. | `true` |
| `proxyConfiguration` | No | object | Starts direct; escalates to datacenter then sticky residential automatically. | `{"useApifyProxy": false}` |

```json
{
  "searchQueries": ["Ikea", "Nike"],
  "maxItems": 25,
  "onlyWithMedia": true,
  "validateMedia": true
}
```

**Common pitfall:** `onlyWithMedia` only filters the ad rows — the per-advertiser `asset_summary` rows always tally every ad seen, including ones with no media, so `adsTotal` on a summary row can legitimately exceed the number of ad rows you actually received for that advertiser.

### 🔽 Output sample

Output is one JSON row per ad, plus one summary row per advertiser, pushed to the run's default dataset and charged as one `row_result` event per row.

```json
{
  "recordType": "ad",
  "searchQuery": "Ikea",
  "id": "abc123",
  "adName": "Summer Collection 2026",
  "adType": "SNAP_AD",
  "brandName": "IKEA",
  "headline": "New arrivals for your home",
  "totalImpressions": 1250000,
  "adStatus": "ACTIVE",
  "snapMediaDownloadLink": "https://ads.snapchat.com/media/abc123.mp4",
  "snapMediaType": "VIDEO",
  "startDate": "2026-06-01",
  "mediaAvailable": true,
  "mediaKind": "video",
  "mediaExtension": "mp4",
  "suggestedFilename": "ikea_summer_collection_2026_abc123.mp4",
  "mediaUrlReachable": true,
  "mediaContentType": "video/mp4"
}
```

An asset summary row:

```json
{
  "recordType": "asset_summary",
  "searchQuery": "Ikea",
  "advertiserName": "IKEA",
  "adsTotal": 24,
  "adsWithMedia": 19,
  "videoAssets": 12,
  "imageAssets": 7
}
```

### How do you filter and target specific ads and assets?

**Scope by country and date for regional creative audits.** `country` plus `startDate`/`endDate` together narrow a search to a specific EU market's ad activity within a window — useful for a regional launch review rather than a global creative sweep.

**Status filter separates live from historical creative.** `status: "ACTIVE"` focuses a catalog on what's currently running; leave it on Any to include paused ads for a fuller historical archive.

**Verification is worth the extra requests before archiving.** Keep `validateMedia` on for any run whose output will feed a download step — the extra HEAD request per asset is cheap insurance against building a catalog full of dead links.

Three real examples:

```json
{ "searchQueries": ["Nike"], "country": "DE", "status": "ACTIVE", "maxItems": 50 }
```

Active-only creative audit for one brand in Germany.

```json
{ "searchQueries": ["Ikea", "Wayfair", "Article"], "onlyWithMedia": true, "maxItems": 30 }
```

Multi-advertiser furniture-category creative comparison.

```json
{ "searchQueries": [""], "status": "ACTIVE", "startDate": "2026-06-01", "maxItems": 200 }
```

Broad library sweep of all currently-active ads since a given date.

### ▶️ Want to try other scrapers?

| Scraper | What it extracts |
| --- | --- |
| Snapchat Profile Scraper — Spotlight & Transcripts | Public profile Spotlight content with transcripts |
| TikTok Video Scraper — Hashtag, Sound & Reach | Video-level reach and sound data |
| Instagram Reels Hashtag Scraper | Reels-only hashtag content with audio metadata |
| Google Search Autocomplete API | Keyword suggestion expansion |

### How to extract Snapchat ads data programmatically

This Actor runs as a standard Apify Actor call — one API call in, structured JSON dataset out, using your Apify API token.

#### Python example

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("<YOUR_USERNAME>/snapchat-ads-media-asset-catalog").call(run_input={
    "searchQueries": ["Ikea"],
    "onlyWithMedia": True,
    "validateMedia": True,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item.get("recordType") == "ad" and item.get("mediaUrlReachable"):
        print(item["suggestedFilename"], item["snapMediaDownloadLink"])
```

#### Export to spreadsheets or CRM

Every dataset supports one-click CSV/Excel export from the Apify Console. Filter on `recordType` to separate ad rows from advertiser summary rows before exporting.

### Is it legal to scrape the Snapchat Ads Library?

Scraping the Snapchat Ads Library is generally lawful, since Snapchat itself publishes this ad-transparency data publicly for anyone to view without logging in — most major ad platforms maintain a public ads library specifically for transparency purposes. Downloaded ad creative remains the advertiser's copyrighted material, so use it for research, competitive analysis, or archival purposes rather than redistribution, and consult legal counsel for commercial applications involving reuse of the creative assets themselves.

### ❓ FAQ

#### Does onlyWithMedia affect the summary rows too?

No — `asset_summary` rows always tally every ad the search encountered (`adsTotal`), regardless of whether `onlyWithMedia` filtered that specific ad out of the ad-row output. Use the summary rows when you need a true total count.

#### What does mediaUrlReachable actually verify?

A live HEAD request to the ad's `snapMediaDownloadLink`, confirming the URL currently resolves and capturing its real Content-Type header. It's `null` (not `false`) when `validateMedia` is off, so you can distinguish "not checked" from "checked and dead."

#### Can I fetch every ad in the library without a specific brand?

Yes — include a single empty string in `searchQueries` to fetch all ads, filtered only by whatever `country`/`status`/date range you set.

#### Why would an ad have no downloadable media?

Not every ad format in the Snapchat Ads Library carries a directly downloadable creative asset — `mediaAvailable: false` reflects that honestly rather than fabricating a placeholder link.

#### Does this require a Snapchat account or API key?

No — it scrapes the Snapchat Ads Library's public search interface directly; no login or API key is needed.

#### How does this compare to other ad-library scrapers?

As observed on the Apify Store on 2026-07-26, `memo23/google-ad-transparency-scraper-cheerio` covers a comparable ad-transparency use case for a different platform (Google), and `apify/social-media-leads-analyzer` focuses on lead analysis rather than creative-asset cataloging — neither documents a live media-reachability check like this Actor's `validateMedia`.

#### Does this work with AI agent frameworks?

Yes — call it as a standard HTTP endpoint via the Apify API from any agent framework capable of making an API call; there's no MCP-specific integration for this Actor.

### Conclusion

Snapchat Ads & Media Asset Catalog Scraper turns a brand search into a downloadable creative catalog — real media classification, a live reachability check before you rely on a download link, and per-advertiser asset summaries. It fits creative intelligence, ad-ops link verification, and category-level creative research. Start a run from the Apify Console or the Apify API with your target advertiser names to get your first media catalog.

# Actor input Schema

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

🏷️ Enter one or more **advertiser / brand names** to search the Snapchat Ads Library for (e.g. `Ikea`, `Nike`, `McDonald's`). Bulk input is fully supported — every keyword is processed independently and its results are tagged with the search query in the output.

💡 Use an empty string `""` as a single entry to fetch **all ads** in the library (filtered only by country / date / status).

## `maxItems` (type: `integer`):

🎯 Maximum number of ads to fetch **per search keyword**. Higher numbers = more data and longer runtime. Snapchat paginates internally; the actor follows the cursor until this limit is reached or no more ads are available.

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

🇪🇺 Restrict results to ads served in a single EU country. Leave empty to include **all countries**.

## `status` (type: `string`):

🟢 Filter by the current delivery status of the ad. Choose **Any** to include both active and paused ads.

## `startDate` (type: `string`):

📆 Only return ads with a `start_date` **on or after** this date (format: `YYYY-MM-DD`). Leave empty for no lower bound.

## `endDate` (type: `string`):

📆 Only return ads with a `start_date` **on or before** this date (format: `YYYY-MM-DD`). Leave empty for no upper bound.

## `onlyWithMedia` (type: `boolean`):

✅ When enabled (default), only ads that carry a real downloadable media asset (`snapMediaDownloadLink`) are emitted as ad rows. Disable to keep every ad, including those with no media. Per-advertiser asset-count summary rows always reflect **all** ads seen, regardless of this filter.

## `validateMedia` (type: `boolean`):

🛰️ When enabled (default), the actor sends a lightweight HEAD request to each media download URL and records `mediaUrlReachable` (true/false) and the real `mediaContentType` header. Disable to skip these network checks — the fields are then set to `null` (never faked).

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

🛡️ By default the actor runs **without a proxy**. If Snapchat rate-limits or rejects the request, the actor automatically falls back to a **datacenter proxy**, then to a **residential proxy** (with up to **3 retries** on residential). Once residential is engaged, it stays engaged for the rest of the run.

## Actor input object example

```json
{
  "searchQueries": [
    "Ikea"
  ],
  "maxItems": 10,
  "country": "",
  "status": "",
  "onlyWithMedia": true,
  "validateMedia": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All scraped items in the Actor's default dataset.

# 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 = {
    "searchQueries": [
        "Ikea"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("simpleapi/snapchat-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 = {
    "searchQueries": ["Ikea"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("simpleapi/snapchat-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 '{
  "searchQueries": [
    "Ikea"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call simpleapi/snapchat-ads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,simpleapi/snapchat-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/OJTcAnFOOGcHUdtKB/builds/cCT59AFnzoppsoLqs/openapi.json
