# Zalando Ads Library Scraper - Sponsored Products (`automation_craft/zalando-ads-library-scraper`) Actor

Scrape the Zalando Ads Library, the public EU ad repository of every sponsored product on Zalando, by search term, sponsor or ad id. One row per distinct ad, charged once: sponsor, product title in up to 44 languages, image, period, 26 markets, reach, targeting. JSON, CSV, API.

- **URL**: https://apify.com/automation_craft/zalando-ads-library-scraper.md
- **Developed by:** [Automation Craft](https://apify.com/automation_craft) (community)
- **Categories:** Marketing, E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 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

### Zalando Ads Library Scraper - Sponsored Products

**Scrape the Zalando Ads Library**, the public EU ad repository (Digital Services Act) of every sponsored product shown on Zalando's shops: about 19 million ads, 26 markets, product titles in up to 44 languages. Search by term, by sponsor (the legal entity that paid) or by ad id, filter by market and period, and get one row per distinct ad with the sponsor, the product, the image, the days it ran, the markets, the reach and the targeting. Each ad is charged once; every miss is a free row.

The archive's own search box times out on words with no ad and on rare words (its 30 second limit). This Actor answers both in seconds through a second query shape, lists a rare brand completely, and tells you in a free row when even that fails.

### Quick start

1. Open the Actor, keep the prefilled input (`searchTerms: ["nike"]`, 20 ads) and press Start, or give your own search terms, sponsor names or ad ids.
2. Narrow the search with markets (DE, FR, NL, PL, ...), a period (`startDate`, `endDate`, or `activeOnly` for ads running now) and the languages you want the product title in.
3. Set `maxAds` (100 when left out), and `memoryName` for a scheduled run that should deliver only new ads.
4. Read the dataset: `ad` rows, one `coverage` row per search, free `status` rows for misses, one `summary` row with every counter.

### What you get

One `ad` row per distinct ad (fill rates measured on 2026-10-08 on the archive's first 2,000 ads in id order, a random sample since the ids are random hex, 1,000 of them with every field):

| Field | What it holds | Fill |
|---|---|---|
| `adId`, `adUrl` | the archive's 32 character id and the archive page opened on it | 100 percent |
| `sponsor` | the legal entity that paid, as the archive names it (NIKE Retail B.V., Falke KGaA, Next Germany GmbH) | 100 percent (475 distinct in 2,000 ads) |
| `title`, `titleLanguage` | the product title in the first of your languages the ad has (English when none is given) | 100 percent; English on 98.8, German on 98.3 |
| `text`, `textLanguage`, `textEqualsTitle` | the ad text in the same language (equal to the title on 93.5 percent of ads) | 99.7 percent |
| `titles`, `texts` | with `languages: ["all"]`: every translation as an object, up to 44 languages per ad (most ads carry 23 to 25, about 2 percent only one) | on request |
| `languagesAvailable` | how many languages the archive carries the title in | 100 percent |
| `image` | the product image the ad shows (img01.ztat.net, jpg or png) | 100 percent |
| `periodStart`, `periodEnd`, `periodEndRaw` | the first and the last day shown (the archive stores the day after the last day as an exclusive bound: that raw value is `periodEndRaw`) | 100 percent |
| `daysShown`, `daysSinceEnd`, `isActive` | days from the first to the last day; days since the last day; true when the last day lies within two days of the run day (the archive publishes with a lag of a day or two) | 100 percent; about 7 percent of ads run now |
| `markets`, `marketNames`, `marketCount` | the markets the ad was shown in, codes and names (one or several of 26; 43 percent of ads run in more than one) | 100 percent |
| `reach` | recipients (total) as the archive counts them (median 246, 90th percentile 5,124, up to 1.3 million) | 100 percent |
| `targetingParameters`, `targetingLabels` | the archive's targeting parameters (contextual, personal, browsing_purchase, category_interest, demographic, device, geography, account, search) and the archive page's own words for them | 100 percent (contextual on every ad, personal on nearly every ad) |
| `visibilityId` | the archive's visibility information id; the ads of one booking share it (12.5 percent of ads share theirs) | 100 percent |
| `matchedIn` | where every word of your search text appears literally on the ad: sponsor, title, text (empty when only the archive's stemmed search matched it) | on search rows |
| `source`, `search`, `scrapedAt` | how the row was found (search, sponsor, ad_id, sample), the search that found it, the read time | 100 percent |

A `coverage` row per search: the archive's total when counted, the query shape used (`mode`), pages and rows read, candidates, ads delivered and charged, ads a memory or an earlier search already held, rows dropped by the sponsor check or the exact words option, archive timeouts, the stop reason, `complete`, seconds. Free `status` rows: `no_result`, `archive_timeout`, `sponsor_not_found`, `ad_not_found`, `invalid`, `lookup_failed`, `skipped`, `memory_free`. A `summary` row last, always, with the counters, the requests by kind, the exit country and what was charged.

### How much does it cost to scrape the Zalando Ads Library?

| Event | FREE | BRONZE | SILVER | GOLD |
|---|---|---|---|---|
| Ad (one distinct ad delivered) | $0.80 per 1,000 | $0.80 per 1,000 | $0.70 per 1,000 | $0.60 per 1,000 |
| Actor start (once per run, per GB of memory; a 256 MB run pays one) | $0.01 | $0.01 | $0.01 | $0.01 |

Platinum and Diamond plans pay the Gold price. The Store pricing card shows these same prices per 1,000 events: "$0.80 / 1,000" on the Ad row means one ad costs 0.08 cents. Example: 1,000 ads of one brand cost $0.81 at Bronze (1,000 ads plus the start); a scheduled run that finds 3 new ads costs $0.0124.

Free: a search with no result, a search the archive could not answer inside its 30 second limit, an ad id the archive does not have, a sponsor name no ad carries, a count, every page read, a repeated ad, an ad an earlier search of the run delivered, an ad a named memory already knows, a row the sponsor check or `exactWords` dropped, coverage rows, status rows, the summary. A run whose named memory cannot be opened, or that the platform restarted, delivers the rest free and says so; a memory that stops saving in the middle of a run frees the ads from that batch on, and the summary names the reason. The start fee of a run stands in every case.

Unpaid work is bounded: a run spends at most 120 seconds plus 1.5 seconds per ad charged on calls that end without a charge (absent words, unknown ids, sponsors no ad carries, counts, failed calls); past that the remaining inputs are listed in one free `skipped` row. A word with no ad costs about 4 seconds, so a list of twenty unknown brands is answered in full.

### Input

| Field | Meaning |
|---|---|
| `searchTerms` | One search text per line. The archive's search covers the product title, the ad text and the sponsor name in every language: whole words, every word must match, English stemming, and a word starting with your text matches too (the archive's own box wraps the text in stars; so does the Actor, unless your text carries an operator: `"nike air"` for a phrase, `nike \| adidas` for either, `-` or `!` for not). Up to 200 per run. |
| `sponsors` | One sponsor per line: a brand word (`nike`) or the legal entity (`NIKE Retail B.V.`). The name is searched and only ads whose sponsor holds every word of it (whole words, capitals aside) are delivered; the rest of the pages read is dropped free. Up to 200. |
| `adIds` | Ad ids (32 characters) or archive URLs, one per line, looked up 100 at a time; an id the archive does not have is a free row. Up to 5,000. |
| `markets` | Keep ads shown in at least one of these markets: AT, BE, HR, CZ, DK, EE, FI, FR, DE, HU, IE, IT, LV, LT, LU, NL, NO, PL, PT, RO, SK, SI, ES, SE, CH, GB (country names work too). Every market when left out. |
| `startDate`, `endDate` | The window the ad ran in (at least one day of it): YYYY-MM-DD, a month as YYYY-MM, today, yesterday, or `30 days` back from the end. Open ended when left out. |
| `activeOnly` | Only ads running now: ads whose period reaches the archive's latest day (it publishes with a lag of a day or two). |
| `languages` | The codes you want the title and text in, in order of preference (`en-GB`, `de-DE`, `fr-FR`, `nl-NL`, `pl-PL`, `it-IT`, `es-ES`, `sv-SE`, `da-DK`, ...), or `all` for every translation as an object. English when left out. |
| `sortBy` | `archive` (the archive's own order, the fastest, the one that walks a large result to its end) or `newest` (latest start date first; the archive sorts the whole result, several seconds per page on a large one). `newest` is the default when a memory name is given. A rare word (a few thousand ads or fewer) is the exception: since October 2026 the archive answers it only in its own relevance order, so its ads come in that order whichever sort you pick. |
| `exactWords` | Deliver only rows where your words appear literally (the archive's stemming also matches Jack for Jacke and Levi for levis); the other rows are dropped free. Off when left out. |
| `countResults` | Ask the archive how many ads match each search (2 to 30 seconds, free; above about 150,000 matches it may time out). Off when left out. |
| `maxAds`, `maxAdsPerSearch`, `maxPagesPerSearch` | The caps: 100 ads per run when left out (up to 200,000); no cap per search; 200 archive pages of up to 2,000 rows per search. |
| `memoryName`, `resetMemory` | A plain name for a scheduled run that should deliver only ads it has not delivered before (see the FAQ); `resetMemory` forgets everything under the name first. |
| `proxyCountry` | The exit country of the one residential session every run uses (the archive answers EU, EEA and UK addresses only): DE when left out, the next country of the list when the proxy has no exit there. |

Without any target (`{}`) the run returns the first ads of the archive inside your markets and dates, capped by `maxAds`.

#### How the archive's limit is handled

The archive answers every query inside 30 seconds or not at all, and its own query plan walks the whole archive for a word with no ad or with fewer than a few thousand ads among 19 million. This Actor first reads a small slice of the archive (about a second) to see how common the word is: a common word is walked with the archive's plain query (100 rows a page, the most the archive answers per call); a rare word is read through a second query shape that makes the archive use its text index, so a brand with 80 ads comes back complete in a few seconds and a word with no ad is settled in three small calls. Narrow filters do not make a search faster (the archive scans more rows per matching ad), so a rare word with a narrow window can still run into the limit: the coverage row then says `archive_timeout`, nothing is charged for that search, and the other searches of the run go on.

### What this Actor does not do

- It does not read the shop: no product prices, sizes, stock, reviews, or the position of a sponsored slot on a live search page. The archive records the ad (who paid, what product, where, how long, how many recipients), not the page it appeared on.
- It does not return the ad creative beyond the product image: the archive carries one product image and, for most ads, the product title as the text; brand campaign ads (about 6 percent) carry a short headline and a call to action instead. No body copy, no video.
- It does not return spend: the archive publishes reach (recipients), not money.
- It does not return an advertiser page or profile, and no impressions per market: the archive names the sponsor's legal entity and gives one reach count per ad with the list of markets.
- It does not search by sponsor on the archive's side: the archive has no sponsor filter, so a sponsor search is a text search of the name plus a whole word check of every row's sponsor, and a sponsor whose name shares no word with its ads' titles can only be found by its name.

### API

```bash
curl -X POST "https://api.apify.com/v2/acts/automation_craft~zalando-ads-library-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms": ["nike"], "markets": ["DE", "AT"], "startDate": "30 days", "maxAds": 200}'
```

```javascript
const { ApifyClient } = require('apify-client');
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('automation_craft/zalando-ads-library-scraper').call({ sponsors: ['NIKE Retail B.V.'], languages: ['de-DE', 'en-GB'], maxAds: 500 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const ads = items.filter((x) => x.type === 'ad');
```

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("automation_craft/zalando-ads-library-scraper").call(run_input={"searchTerms": ["adidas running"], "activeOnly": True, "maxAds": 100})
ads = [x for x in client.dataset(run["defaultDatasetId"]).iterate_items() if x["type"] == "ad"]
```

### FAQ

#### Does Zalando have an ad library?

Yes. Under the EU Digital Services Act Zalando publishes a sponsored content archive, the ad repository behind en.zalando.de/ads-repository, with every sponsored product ad shown on its shops: about 19 million ads with the sponsor, the product, the period, the markets, the reach and the targeting. This Actor reads that archive.

#### How can I see competitor ads on Zalando?

Put the brand word into `searchTerms` (nike finds the product titles and the sponsor NIKE Retail B.V.), or the sponsor's name into `sponsors` for only that legal entity's ads. Every row carries the product, the image, the days it ran, the markets and the reach, so you see what a competitor sponsors, where and for how long.

#### What are Zalando Sponsored Products and who is the sponsor?

Sponsored Products are the paid product placements on Zalando's catalogue pages. The archive names the sponsor as the legal entity that paid, for example NIKE Retail B.V. or Falke KGaA; a brand can appear under several entities and a distributor can sponsor another brand's products. The `sponsor` field holds the name as the archive writes it.

#### Which markets and languages does the archive cover?

26 markets (Germany, Austria, Switzerland, the Netherlands, Belgium, France, Italy, Spain, Portugal, Poland, the Nordics, the Baltics, Ireland, the UK and more), one or several per ad, and the product title in up to 44 languages per ad (most ads carry 23 to 25, a few only one). Filter by market, ask for the title in the languages you read, or all of them at once.

#### Can I monitor a brand and pay only for new ads?

Yes: schedule the same input with a `memoryName`. Ads delivered under that name are remembered in a key value store this Actor creates in your account and skipped, free, on later runs. A memory run reads the newest ads first and stops at the first page it already delivered once an earlier run under that name that was charging normally (not delivering free) walked the search to its end; until then each run carries on past the known ads to the next older ones, up to its cap, and charges them. So give a monitor a search it can finish and that stays the same from run to run: a date window with fixed dates, or a `maxAds` above the brand's ad count on the first run. (`activeOnly` also keeps the search small, the ads running now, but its window moves every day, so each run re-reads those few pages and skips the known ads free.) A run that finds nothing new then costs the start fee and a few seconds. A second run on one name while another is still running, or a memory that cannot be opened, makes that run deliver its ads free and remember nothing (the first run goes on as normal), and a status row says so; a memory that stops saving in the middle of a run makes the ads from that batch on free (the ads already delivered stay charged and remembered) and the summary row names the reason. The start fee stands in every case. A monitor of a rare word re-reads all of that word's ads on every run (the archive cannot sort a rare word by date), skipping the known ones free; when one run reaches roughly 5,000 to 8,000 known ads of rare words it stops early with a free status row and leaves its later searches for the next run, so split a very large rare word monitor over several memory names.

#### Why does this Actor run with limited permissions?

Least privilege: it reads only its own input, dataset and key value stores, plus the named memory store it creates itself. It needs nothing else from your account.

### More data tools by Automation Craft

- [Amazon Ad Library Scraper - EU Ads & Impressions](https://apify.com/automation_craft/amazon-ad-library-scraper)
- [Pinterest Ads Library Scraper - EU Ads Repository](https://apify.com/automation_craft/pinterest-ads-library-scraper)
- [Microsoft Ads Library Scraper - Competitor Ads](https://apify.com/automation_craft/microsoft-ads-library-scraper)
- [Bing Ads Library Scraper - Advertisers, Ad Copy](https://apify.com/automation_craft/bing-ads-library-scraper)
- [Meta Ad Library Scraper - All Placements, Filters](https://apify.com/automation_craft/meta-ads-library-scraper)
- [Facebook Ads Library Scraper - Page Ads, No Login](https://apify.com/automation_craft/facebook-ads-library-scraper)
- [Google Ads Transparency Scraper - Decoded Creatives](https://apify.com/automation_craft/google-ads-transparency-scraper)
- [TikTok Ads Library Scraper: EU Ads, No Login](https://apify.com/automation_craft/tiktok-ads-library-scraper)
- [LinkedIn Ad Library Scraper: Ads by Company](https://apify.com/automation_craft/linkedin-ad-library-scraper)
- [Snapchat Ads Library Scraper: EU Ads Gallery](https://apify.com/automation_craft/snapchat-ads-library-scraper)

### Changelog

- 0.1 (2026-10-08): first release.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation_craft/zalando-ads-library-scraper/changelog.md

# Actor input Schema

## `searchTerms` (type: `array`):

One search text per line, for example nike or adidas running. Each returns the archive's ads whose title, text or sponsor holds every word, walked page by page until the end or your caps. A word with no ad comes back as a free row. A rare word, which the archive's own search box cannot list inside its 30 second limit, is read through a second query shape and listed completely; when even that meets the limit, the search comes back as a free archive_timeout row. If a later page of a search meets the limit, the ads already delivered for it stay charged and its coverage row says archive_timeout. Up to 200 per run.

## `sponsors` (type: `array`):

One sponsor per line, for example Nike or NIKE Retail B.V. or Falke KGaA. The sponsor is the legal entity that paid for the ad as the archive names it. The name is searched and only ads whose sponsor name holds every word of it (whole words, capitals aside) are delivered; the other ads of the pages read are dropped free. A name no sponsor carries comes back as a free row. Up to 200 per run.

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

One per line: an ad id (32 characters, for example 00005109f9bb75b14e2532c23370c63b) or an archive URL that carries one (https://sponsored-content-archive.zalando.com/?lang=en-GB\&fullText=00005109f9bb75b14e2532c23370c63b). Ads are looked up 100 at a time; each ad found comes back as one row and is charged as one Ad. An id the archive does not have costs nothing and comes back as a free row. Up to 5,000 per run.

## `markets` (type: `array`):

Keep ads shown in at least one of these markets. Leave empty for every market. Through the API send ISO codes (DE, FR, NL, PL, ...) or the country names the archive uses (Germany).

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

First day of the window: YYYY-MM-DD, a month as YYYY-MM (its first day), or a number of days, weeks or months back from the end date, such as 30 days. An ad is returned when it ran on at least one day of the window. When both dates are left out, the whole archive is searched.

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

Last day of the window: YYYY-MM-DD, a month as YYYY-MM (its last day), today or yesterday. Open ended when left out.

## `activeOnly` (type: `boolean`):

Keep only ads running now: ads whose period reaches the archive's latest day (it publishes with a lag of a day or two). The archive lists every ad currently running and the ads that ended since about April 2025. Off when the field is left out.

## `languages` (type: `array`):

The archive carries the product title and the ad text in up to 44 languages per ad (most ads 23 to 25). Give the codes you want on the title and text fields, in order of preference (en-GB, de-DE, fr-FR, nl-NL, pl-PL, it-IT, es-ES, sv-SE, da-DK, ...), or all to get every translation as an object. English when the field is left out. The archive's search itself always covers every language.

## `sortBy` (type: `string`):

archive: the archive's own order (the cheapest, the one that walks a large result to its end). newest: ads with the latest start date first (the archive sorts the whole result, several seconds per page on a large one). Through the API send archive or newest. When the field is left out: archive, or newest when a memory name is given (new ads come first, so a scheduled run can stop at the ads it already delivered, once a run under that memory name that was charging normally walked the search to its end; see memoryName).

## `exactWords` (type: `boolean`):

The archive's search stems words in English (Jacke also finds Jack, levis finds Levi). Every row carries matchedIn, where your words appear literally (sponsor, title, text). Switch this on to deliver only rows where they appear literally; the other rows are dropped free. Off when the field is left out.

## `countResults` (type: `boolean`):

Ask the archive how many ads match each search (the coverage row's libraryTotal). A count takes the archive 2 to 30 seconds and is not charged; above about 150,000 matches it may run into the archive's 30 second limit and comes back as timed out. Off when the field is left out.

## `maxAds` (type: `integer`):

The run stops when this many ads were delivered. 100 when the field is left out; up to 200,000.

## `maxAdsPerSearch` (type: `integer`):

A cap for each search term and each sponsor. 0 or empty: no cap per search.

## `maxPagesPerSearch` (type: `integer`):

A search stops after reading this many pages of 2,000 rows from the archive. 200 when the field is left out (400,000 rows); up to 2,000.

## `memoryName` (type: `string`):

A plain name, for example nike watch. Ads delivered under this name are remembered in a key value store this Actor creates in your account; on later runs with the same name they are skipped and not charged, and the walk (newest first) stops at the first page of ads an earlier run delivered once a run under this name that was charging normally walked the search to its end (until then each run carries on to the next older ads up to its cap; give a monitor a search it can finish and that stays the same from run to run: a date window with fixed dates, or a cap above the brand's ad count; the activeOnly window moves daily, so it is re-read each run, known ads skipped free). Two runs on one name at the same time: the second one delivers its ads free and remembers nothing. A memory that cannot be opened makes the run deliver its ads free; one that stops saving mid run makes the ads from that batch on free. The start fee stands in every case.

## `resetMemory` (type: `boolean`):

Forget everything stored under the memory name before the run, so every ad counts as new again.

## `proxyCountry` (type: `string`):

The archive answers addresses in the EU, the EEA and the UK only, so every run uses one Apify residential session in this country (and moves to the next country of the list when the proxy has no exit there). Germany when the field is left out.

## Actor input object example

```json
{
  "searchTerms": [
    "nike"
  ],
  "languages": [
    "en-GB"
  ],
  "maxAds": 20
}
```

# Actor output Schema

## `items` (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 = {
    "searchTerms": [
        "nike"
    ],
    "languages": [
        "en-GB"
    ],
    "maxAds": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/zalando-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 = {
    "searchTerms": ["nike"],
    "languages": ["en-GB"],
    "maxAds": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation_craft/zalando-ads-library-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 '{
  "searchTerms": [
    "nike"
  ],
  "languages": [
    "en-GB"
  ],
  "maxAds": 20
}' |
apify call automation_craft/zalando-ads-library-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation_craft/zalando-ads-library-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/fF0CTRVIGxQFLd8Ek/builds/7j6jUZpQ7qOJwb1Hr/openapi.json
