# Apple Ads Library Scraper - App Store Ads Transparency (`scrapesage/apple-ads-library-scraper`) Actor

See every Apple Search Ads campaign on the App Store. Scrape Apple's Ad Repository by app or developer: creatives, placements, targeting, impression dates, locale variations & new-ad monitoring. The Apple side of your ads transparency stack.

- **URL**: https://apify.com/scrapesage/apple-ads-library-scraper.md
- **Developed by:** [Scrape Sage](https://apify.com/scrapesage) (community)
- **Categories:** SEO tools, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 ad scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Apple Ads Library Scraper — App Store Ads, Advertisers & New-Ad Monitoring (Apple Search Ads Transparency)

See **every ad any app runs on the App Store**. This actor scrapes Apple's official **Ad Repository** — the transparency register of Apple-delivered App Store advertising in the EU — and turns it into clean, structured competitor intelligence: **who advertises, in which countries, on which placements (search results, Search tab, Today tab), with which creatives and localized copy, targeting refinements, and exactly when each ad ran**. Search by app or developer name, sweep whole countries, build directories of active Apple Search Ads advertisers — and flip on **monitor mode** to get only the *new* ads a competitor launches between runs.

No login, no API key, no browser — fast JSON extraction straight from Apple's own documented public API, with 99%+ reliability.

### Why this Apple Ads Library scraper?

Google, Meta and TikTok ad-spy tools are everywhere — but **Apple Search Ads is the blind spot**: a $10B+/yr ad platform that decides who wins App Store search, and almost zero competitive-intel coverage. Every serious app publisher bids there; almost nobody can see what competitors run. This actor closes that gap and ships the **richest dataset in the category**:

| Data | Typical scrapers | This actor |
|---|---|---|
| App + developer identity (incl. **legal name**) | partial | ✅ complete |
| Placement (search results / Search tab / Today tab) | ❌ | ✅ |
| Ad format & creative assets (full-res screenshots, video) | ❌ | ✅ |
| First & last impression dates + **days active** | ❌ | ✅ |
| Audience targeting flags (age / gender / location / customer type) | ❌ | ✅ |
| App Store metadata (icon, subtitle, category, description, IAP) | ❌ | ✅ |
| **Per-language ad variations** (localized name, subtitle, promo text, device creatives) | ❌ | ✅ opt-in |
| Search by app **or developer name** (no numeric IDs needed) | ❌ | ✅ |
| Advertiser directory mode (who's actively buying Apple Search Ads) | ❌ | ✅ |
| Country browse (every ad running in a market) | ❌ | ✅ |
| Advertising **restriction events** (removed ads, suspended accounts + reasons) | ❌ | ✅ |
| Monitor mode — only new/changed ads per run | ❌ | ✅ |

### Use cases

- **Competitor Apple Search Ads intelligence** — see exactly which of a competitor's apps advertise, in which EU markets, on which placements, and how long each ad has been running. `daysActive` + `isRecentlyActive` reveal their evergreen winners vs. abandoned tests.
- **ASO & creative research** — pull the creative assets, localized subtitles and promotional texts competitors pair with their ads; `includeAdVariations` returns every language version with per-device screenshots — a ready-made swipe file for your next custom product page.
- **New-ad alerts** — schedule a daily run with `monitorMode` on a competitor's developer name and get only their newly launched ads, straight to Slack/CRM via integrations.
- **Lead generation** — `entitySearchQueries` turns the register into a list of apps & developers **actively spending on Apple Search Ads** ("vpn", "casino", "fitness"…) with live ad counts — pre-qualified, budget-proven prospects for UA agencies, ASO tools and mobile-marketing sales.
- **Market landscape sweeps** — country browse returns the full ad feed of any EU market (France alone: 130k+ ads/90 days) — category mix, seasonal pushes, who's scaling.
- **Policy & compliance research** — the restrictions feed exposes which advertising Apple removed or suspended, why (ToS incompatibility, government order…), and in which countries.

### How to use

1. [Sign up for Apify](https://console.apify.com/sign-up) — the free plan is enough to try this actor.
2. Open the **Apple Ads Library Scraper**, enter app/developer names (or App Store URLs), and click **Start**.
3. Watch results stream into the dataset table.
4. **Export** as JSON, CSV, Excel, XML, or RSS — or pull results programmatically via the [Apify API](https://docs.apify.com/api/v2).

### Input

```json
{
    "searchQueries": ["Duolingo", "Spotify"],
    "countries": ["DE", "France"],
    "datePreset": "LAST_90_DAYS",
    "includeAdVariations": true,
    "maxResults": 100,
    "monitorMode": false
}
````

- **searchQueries** — app or developer names; each is resolved in the register (apps + developers) and all their ads are scraped.
- **appIds / developerIds** — exact App Store IDs (the number in `apps.apple.com/…/id123456789` URLs) for direct scraping.
- **entitySearchQueries** — search the **advertiser register** instead: one record per matching app/developer with live `adsCount` + sample ads. Directory mode for lead lists.
- **startUrls** — App Store app or developer URLs (or bare numeric IDs), auto-detected.
- **countries** — EU country filter (ISO codes or names). **Countries as the only input = browse those countries' entire ad feeds.**
- **datePreset** — `LAST_90_DAYS` (default), `LAST_180_DAYS`, or `LAST_YEAR` impression window.
- **placements** — keep only search-results / Search-tab / Today-tab ads.
- **includeAdVariations** *(default false)* — fetch every ad's language variations (localized app name, subtitle, promotional text, per-device creatives) + all icon variations (one extra request per ad).
- **includeRestrictions** — also emit Apple's advertising-restriction events; set it with no other input for the restrictions feed alone.
- **maxResults** *(default 100)* — total record cap; `0` = no limit (explicit opt-in).
- **monitorMode / monitorStoreName** — cross-run new-ad detection (see below).

### Output

One record per ad per country (`type: "ad"`), plus optional directory records (`type: "entity"`) and restriction events (`type: "restriction"`):

```json
{
    "type": "ad",
    "adId": "391259fb1eaa579411f7b59d52b5bcdc",
    "appId": 570060128,
    "appName": "Duolingo: Sprachen und Schach",
    "developerId": 570060151,
    "developerName": "Duolingo",
    "legalName": "Duolingo, Inc",
    "placement": "APPSTORE_SEARCH_RESULTS",
    "placementLabel": "App Store search results",
    "format": "Icon + Asset Ad",
    "countryOrRegion": "DE",
    "countryName": "Germany",
    "targeting": { "ageTarget": false, "genderTarget": false, "locationTarget": false, "customerTypeTarget": false },
    "targetingUsed": false,
    "firstImpressionDate": "2026-06-25",
    "lastImpressionDate": "2026-06-27",
    "daysActive": 3,
    "isRecentlyActive": true,
    "defaultLanguage": "German",
    "appIconUrl": "https://is5-ssl.mzstatic.com/image/thumb/…/1024x1024.png",
    "appSubtitle": "Englisch, Schach, Mathe, Musik",
    "appCategory": "Education",
    "inAppPurchases": true,
    "editorialBadge": true,
    "promotionalText": "Checkmate! You can now learn Chess on Duolingo!…",
    "appDescription": "Lerne spielend leicht eine neue Sprache…",
    "adAssets": [ { "assetType": "image", "url": "https://…/iOS_6.5_01.jpg/2688x1242.jpg", "order": 1, "width": 1242, "height": 2688, "orientation": "PORTRAIT" } ],
    "assetCount": 3,
    "hasVideoAsset": false,
    "localeVariations": [ { "languageTag": "en-GB", "appName": "Duolingo: Language & Chess", "promotionalText": "…", "deviceAssets": [ … ] } ],
    "adLanguages": ["English (United Kingdom)", "German", "Spanish (Spain)"],
    "appStoreUrl": "https://apps.apple.com/app/id570060128",
    "developerAppStoreUrl": "https://apps.apple.com/developer/id570060151",
    "dataWindow": { "start": "2025-06-27", "end": "2026-06-27" },
    "queryTotalCount": 19,
    "discoverySource": "q:Duolingo→APP:Duolingo: Language Lessons",
    "platform": "apple",
    "adLibrary": "Apple Ad Repository (EU — DSA transparency)",
    "scrapedAt": "2026-07-02T12:00:00.000Z"
}
```

#### What to expect (field coverage)

- App/developer identity, placement, format, country, impression dates, language, icon, subtitle, category, description, creative assets — populated on ~100% of ads.
- `subFormat` — Apple populates it only when a new ad-format variation is introduced; usually `null` (that's the source, not a scraping gap).
- `promotionalText` — only apps that set promotional text have it; with `includeAdVariations` the actor also recovers it from the ad's language variations.
- `localeVariations` / `iconVariations` / `adLanguages` — filled when `includeAdVariations` is on.
- Data freshness: Apple publishes the repository with a **~7-day delay** (each record carries its exact `dataWindow`).

### Monitor mode — only new ads, run after run

Set `monitorMode: true` and every scraped ad's fingerprint is remembered in a named key-value store. The next run outputs **only ads that are new or changed**, each tagged `monitorStatus: "new"` or `"updated"`. Pair it with an [Apify Schedule](https://docs.apify.com/platform/schedules) (they complement each other — the Schedule triggers runs, monitor mode dedupes the output):

1. Input: `{ "searchQueries": ["Duolingo"], "monitorMode": true, "maxResults": 0 }`
2. Schedule: daily.
3. Add a [webhook](https://docs.apify.com/platform/integrations/webhooks) or Zapier/Make step → new competitor ads land in Slack, email, or your CRM.

Running several monitors? Give each schedule its own `monitorStoreName`.

> **Tip:** monitor app/developer-scoped inputs with `maxResults: 0` so the full ad set is compared every run. A country browse capped far below its total samples a different slice each run — those ads aren't really "new", you just hadn't seen them yet.

### Automate & schedule

Run this actor on autopilot and pull results into your own stack:

- **[Apify API](https://docs.apify.com/api/v2)** — start runs, fetch datasets, and manage schedules over REST.
- **[apify-client for JavaScript](https://docs.apify.com/api/client/js/)** and **[apify-client for Python](https://docs.apify.com/api/client/python/)** — official SDKs.
- **[Schedules](https://docs.apify.com/platform/schedules)** — hourly/daily/weekly competitor sweeps.
- **[Webhooks](https://docs.apify.com/platform/integrations/webhooks)** — trigger downstream actions the moment a run finishes.

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

const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });

const run = await client.actor('scrapesage/apple-ads-library-scraper').call({
    searchQueries: ['Spotify'],
    countries: ['Germany', 'France'],
    includeAdVariations: true,
    maxResults: 200,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} App Store ads`);
```

### Integrate with any app

Connect the dataset to 5,000+ apps — no code required:

- **[Make](https://docs.apify.com/platform/integrations/make)** — multi-step automation scenarios.
- **[Zapier](https://docs.apify.com/platform/integrations/zapier)** — push new competitor ads straight into your CRM or ad-ops board.
- **[Slack](https://docs.apify.com/platform/integrations/slack)** — get pinged when a monitored advertiser launches new ads.
- **[Google Drive / Sheets](https://docs.apify.com/platform/integrations/drive)** — auto-export every run to a spreadsheet.
- **[Airbyte](https://docs.apify.com/platform/integrations/airbyte)** — pipe results into your data warehouse.
- **[GitHub](https://docs.apify.com/platform/integrations/github)** — trigger runs from commits or releases.

### Use with AI assistants (MCP)

The output is clean, LLM-ready JSON. You can call this actor from Claude, ChatGPT, or any agent framework through the **[Apify MCP server](https://docs.apify.com/platform/integrations/mcp)** — ask your assistant to "pull every App Store ad Duolingo runs in Germany and summarize their creative strategy" and let it run this scraper for you.

### Agent-ready: autonomous payments (x402 & Skyfire)

This actor is **agent-ready** — AI agents can discover it, run it, and **pay for it autonomously**, with no Apify account and no human in the loop. It uses [pay-per-event](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event) pricing and [limited permissions](https://docs.apify.com/platform/actors/development/permissions), so it qualifies for Apify's agentic-payment standards:

- **[x402](https://docs.apify.com/platform/integrations/x402)** — an open, HTTP-native payment protocol. Agents pay per run in USDC on the Base network directly through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) — no account, no API key.
- **[Skyfire](https://docs.apify.com/platform/integrations/skyfire)** — agent-to-service payments for fully autonomous AI-agent workflows.

Building an AI agent, MCP tool, or autonomous data pipeline? This scraper is ready to plug in and pay as it goes.

### More scrapers from scrapesage

Build a complete **ads-transparency intelligence stack** — every major ad platform, one dataset shape:

- **[Google Ads Transparency Scraper](https://apify.com/scrapesage/google-ads-transparency-scraper)** — who's advertising what on Google.
- **[Facebook Ad Library Scraper](https://apify.com/scrapesage/facebook-ad-library-scraper)** — Meta + Instagram ads with monitoring mode.
- **[TikTok Ad Library Scraper](https://apify.com/scrapesage/tiktok-ad-library-scraper)** — TikTok top ads & creative intelligence.
- **[LinkedIn Ad Library Scraper](https://apify.com/scrapesage/linkedin-ad-library-scraper)** — competitor B2B ads & creatives.
- **[Bing Ads Library Scraper](https://apify.com/scrapesage/bing-ads-library-scraper)** — Microsoft Advertising transparency.

And go deeper on the app economy:

- **[Apple App Store Scraper](https://apify.com/scrapesage/app-store-scraper)** — apps, reviews & top charts.
- **[Google Play Store Scraper](https://apify.com/scrapesage/google-play-scraper)** — Android apps, reviews & developer leads.
- **[Keyword Research Scraper](https://apify.com/scrapesage/keyword-research-scraper)** — Google, YouTube & Amazon keyword data.

### Tips

- **Who's bidding in my category?** `entitySearchQueries: ["fitness"]` → every advertised app/developer with "fitness" in the name, with live ad counts. Feed the interesting IDs back into `appIds`/`developerIds` for full pulls.
- **Competitor deep dive**: search the developer name (not the app) — you get ads for **all** their apps at once, then `includeAdVariations` for the full creative picture.
- **Cheap daily monitors**: `searchQueries` + `monitorMode` + a daily Schedule is the highest-signal, lowest-cost setup — you pay only for genuinely new ads.
- **Deep country sweeps**: the repository stops paginating around ~1,100–1,300 records per query. Browsing whole countries samples the top of the feed; for exhaustive coverage go app-by-app or developer-by-developer.
- **Longer windows find more**: an app that paused ads last month won't show in `LAST_90_DAYS` — flip to `LAST_YEAR` for the full history (dates included on every record).

### FAQ

**Where does the data come from?** From Apple's official **Ad Repository** (adrepository.apple.com), the transparency register Apple publishes under the EU Digital Services Act, using Apple's own documented public API. No login, no private data.

**Why EU only?** Apple's repository publishes Apple-delivered App Store ads with impressions *in the 25 covered EU countries* — that's what the DSA mandates. Global advertisers (Duolingo, Spotify, King, VPN apps…) all appear because they advertise in Europe; what you won't find is an ad shown *only* outside the EU.

**Which ads are included?** Apple-delivered advertising on the App Store: search-results ads (classic Apple Search Ads), Search-tab and Today-tab placements — the formats Apple sells through Apple Ads. Each record is one ad in one country.

**Does it show ad spend or impression counts?** Apple publishes impression *date ranges* (first/last impression, from which we derive `daysActive` and `isRecentlyActive`) and targeting-refinement flags — not spend or raw impression counts (no platform's DSA library publishes spend for non-political ads).

**How fresh is the data?** Apple publishes with a ~7-day delay; every record carries its exact `dataWindow`. Data reaches back up to one year (`datePreset: "LAST_YEAR"`).

**Can I monitor a competitor automatically?** Yes — that's the flagship use case. `monitorMode: true` + an Apify Schedule + a webhook = new-ad alerts. Monitor mode stores fingerprints in a key-value store and outputs only new/changed ads each run.

**Is scraping the Apple Ad Repository legal?** The repository is a public transparency register that exists precisely so ads can be inspected, and Apple documents its API for programmatic use. The actor collects no personal data. You're responsible for complying with applicable laws and terms in your use of the data.

**A field is null — why?** `subFormat` is only set by Apple for new format variations; `promotionalText` only exists when the app sets one; variation fields fill only with `includeAdVariations` on. Fields are `null` only when the source doesn't expose the data, never because the scraper skipped it.

### Need help?

Open an issue on the actor's **Issues** tab, or visit the [Apify help center](https://help.apify.com/). Feature requests are welcome — this actor is actively maintained.

# Actor input Schema

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

App or developer names to look up — e.g. "Duolingo", "Spotify", "King". Each name is resolved in Apple's Ad Repository register (apps + developers) and ALL their App Store ads are scraped.

## `appIds` (type: `array`):

Exact App Store app IDs (the number in apps.apple.com/…/id123456789 URLs) — scrapes all their ads directly.

## `developerIds` (type: `array`):

Exact App Store developer IDs (the number in apps.apple.com/…/developer/id123456 URLs) — scrapes ads of ALL that developer's apps.

## `entitySearchQueries` (type: `array`):

Search the register of advertised apps & developers instead — emits one record per match (name, type, ID, ads count, sample ads). Great for building lists of apps actively running Apple Search Ads (e.g. "vpn", "casino", "language").

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

App Store URLs — app pages (apps.apple.com/us/app/…/id123) or developer pages (apps.apple.com/us/developer/…/id456) — or bare numeric IDs. Auto-detected and scraped.

## `countries` (type: `array`):

Only ads delivered in these countries — ISO codes or names (e.g. "DE", "France"). Empty = all 25 covered EU countries. TIP: with countries as the ONLY input, the actor browses each country's whole ad feed.

## `datePreset` (type: `string`):

Impression window the repository reports on (data is published with a ~7-day delay).

## `placements` (type: `array`):

Keep only ads in these App Store placements. Empty = all placements.

## `includeAdVariations` (type: `boolean`):

Fetch each ad's variations: every language version (localized app name, subtitle, promotional text) with per-device creative assets, plus all app-icon variations (one extra request per ad).

## `includeEntityAdStats` (type: `boolean`):

In advertiser-directory mode, probe each app/developer's ads to add adsCount + sample ads (one extra request per record).

## `includeRestrictions` (type: `boolean`):

Also scrape Apple's advertising-restriction events (ads removed / accounts suspended, with reason, basis, affected placements & countries). Set this with no other input to get ONLY the restrictions feed.

## `restrictionActions` (type: `array`):

Which restriction actions to include. Empty = both.

## `maxEntitiesPerQuery` (type: `integer`):

How many matching apps/developers to scrape per name in searchQueries.

## `maxResults` (type: `integer`):

Maximum records (ads + directory + restrictions) to return. 0 = no limit (explicit opt-in; pair with a run timeout).

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

Per-app/per-country cap. 0 = no per-query cap (the repository itself stops paginating around ~1,100-1,300 records per query — use narrower countries to go deeper).

## `monitorMode` (type: `boolean`):

Track ads across runs in a key-value store and only output ads that are new or changed since the last run — perfect on an Apify Schedule for competitor new-ad alerts. Works alongside (not instead of) Apify Schedules: the Schedule triggers runs, monitor mode dedupes the output. Best with app/developer-scoped inputs and maxResults 0 so the full ad set is compared each run.

## `monitorStoreName` (type: `string`):

Named key-value store holding monitor state (lowercase letters, digits, hyphens). Use a different name per schedule if you run several monitors.

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

The Ad Repository is an official open Apple API — default datacenter proxies work and are the cheapest. Switch to RESIDENTIAL only if you ever see blocked requests.

## Actor input object example

```json
{
  "searchQueries": [
    "Duolingo"
  ],
  "datePreset": "LAST_90_DAYS",
  "includeAdVariations": false,
  "includeEntityAdStats": true,
  "includeRestrictions": false,
  "maxEntitiesPerQuery": 3,
  "maxResults": 100,
  "maxAdsPerQuery": 0,
  "monitorMode": false,
  "monitorStoreName": "apple-ads-library-monitor",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All scraped ad, app/developer directory and restriction records as JSON items in the 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": [
        "Duolingo"
    ],
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/apple-ads-library-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": ["Duolingo"],
    "maxResults": 100,
}

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

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": [
    "Duolingo"
  ],
  "maxResults": 100
}' |
apify call scrapesage/apple-ads-library-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=scrapesage/apple-ads-library-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Apple Ads Library Scraper - App Store Ads Transparency",
        "description": "See every Apple Search Ads campaign on the App Store. Scrape Apple's Ad Repository by app or developer: creatives, placements, targeting, impression dates, locale variations & new-ad monitoring. The Apple side of your ads transparency stack.",
        "version": "0.1",
        "x-build-id": "txaA00zLicGTrd98G"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/scrapesage~apple-ads-library-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-scrapesage-apple-ads-library-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/scrapesage~apple-ads-library-scraper/runs": {
            "post": {
                "operationId": "runs-sync-scrapesage-apple-ads-library-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/scrapesage~apple-ads-library-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-scrapesage-apple-ads-library-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "searchQueries": {
                        "title": "App or developer names",
                        "type": "array",
                        "description": "App or developer names to look up — e.g. \"Duolingo\", \"Spotify\", \"King\". Each name is resolved in Apple's Ad Repository register (apps + developers) and ALL their App Store ads are scraped.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "appIds": {
                        "title": "App IDs",
                        "type": "array",
                        "description": "Exact App Store app IDs (the number in apps.apple.com/…/id123456789 URLs) — scrapes all their ads directly.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "developerIds": {
                        "title": "Developer IDs",
                        "type": "array",
                        "description": "Exact App Store developer IDs (the number in apps.apple.com/…/developer/id123456 URLs) — scrapes ads of ALL that developer's apps.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "entitySearchQueries": {
                        "title": "Advertiser directory search",
                        "type": "array",
                        "description": "Search the register of advertised apps & developers instead — emits one record per match (name, type, ID, ads count, sample ads). Great for building lists of apps actively running Apple Search Ads (e.g. \"vpn\", \"casino\", \"language\").",
                        "items": {
                            "type": "string"
                        }
                    },
                    "startUrls": {
                        "title": "Start URLs",
                        "type": "array",
                        "description": "App Store URLs — app pages (apps.apple.com/us/app/…/id123) or developer pages (apps.apple.com/us/developer/…/id456) — or bare numeric IDs. Auto-detected and scraped.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "countries": {
                        "title": "Countries (EU)",
                        "type": "array",
                        "description": "Only ads delivered in these countries — ISO codes or names (e.g. \"DE\", \"France\"). Empty = all 25 covered EU countries. TIP: with countries as the ONLY input, the actor browses each country's whole ad feed.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "datePreset": {
                        "title": "Date window",
                        "enum": [
                            "LAST_90_DAYS",
                            "LAST_180_DAYS",
                            "LAST_YEAR"
                        ],
                        "type": "string",
                        "description": "Impression window the repository reports on (data is published with a ~7-day delay).",
                        "default": "LAST_90_DAYS"
                    },
                    "placements": {
                        "title": "Placements",
                        "type": "array",
                        "description": "Keep only ads in these App Store placements. Empty = all placements.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "APPSTORE_SEARCH_RESULTS",
                                "APPSTORE_SEARCH_TAB",
                                "APPSTORE_TODAY_TAB",
                                "APPSTORE_PRODUCT_PAGES"
                            ],
                            "enumTitles": [
                                "Search results",
                                "Search tab",
                                "Today tab",
                                "Product pages"
                            ]
                        }
                    },
                    "includeAdVariations": {
                        "title": "Include ad variations (locale creatives)",
                        "type": "boolean",
                        "description": "Fetch each ad's variations: every language version (localized app name, subtitle, promotional text) with per-device creative assets, plus all app-icon variations (one extra request per ad).",
                        "default": false
                    },
                    "includeEntityAdStats": {
                        "title": "Directory: include ad stats",
                        "type": "boolean",
                        "description": "In advertiser-directory mode, probe each app/developer's ads to add adsCount + sample ads (one extra request per record).",
                        "default": true
                    },
                    "includeRestrictions": {
                        "title": "Include advertising restrictions",
                        "type": "boolean",
                        "description": "Also scrape Apple's advertising-restriction events (ads removed / accounts suspended, with reason, basis, affected placements & countries). Set this with no other input to get ONLY the restrictions feed.",
                        "default": false
                    },
                    "restrictionActions": {
                        "title": "Restriction actions",
                        "type": "array",
                        "description": "Which restriction actions to include. Empty = both.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "ACTION_ADVERTISING_REMOVED",
                                "ACTION_ACCOUNT_SUSPENDED"
                            ],
                            "enumTitles": [
                                "Advertising removed",
                                "Account suspended"
                            ]
                        }
                    },
                    "maxEntitiesPerQuery": {
                        "title": "Max entities per name search",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "How many matching apps/developers to scrape per name in searchQueries.",
                        "default": 3
                    },
                    "maxResults": {
                        "title": "Max results (total)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum records (ads + directory + restrictions) to return. 0 = no limit (explicit opt-in; pair with a run timeout).",
                        "default": 100
                    },
                    "maxAdsPerQuery": {
                        "title": "Max ads per query",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Per-app/per-country cap. 0 = no per-query cap (the repository itself stops paginating around ~1,100-1,300 records per query — use narrower countries to go deeper).",
                        "default": 0
                    },
                    "monitorMode": {
                        "title": "Monitor mode (only new / changed ads)",
                        "type": "boolean",
                        "description": "Track ads across runs in a key-value store and only output ads that are new or changed since the last run — perfect on an Apify Schedule for competitor new-ad alerts. Works alongside (not instead of) Apify Schedules: the Schedule triggers runs, monitor mode dedupes the output. Best with app/developer-scoped inputs and maxResults 0 so the full ad set is compared each run.",
                        "default": false
                    },
                    "monitorStoreName": {
                        "title": "Monitor store name",
                        "type": "string",
                        "description": "Named key-value store holding monitor state (lowercase letters, digits, hyphens). Use a different name per schedule if you run several monitors.",
                        "default": "apple-ads-library-monitor"
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "The Ad Repository is an official open Apple API — default datacenter proxies work and are the cheapest. Switch to RESIDENTIAL only if you ever see blocked requests.",
                        "default": {
                            "useApifyProxy": true
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
