# Pinterest Ads Library Scraper - EU Ads Repository (`automation_craft/pinterest-ads-library-scraper`) Actor

Scrape Pinterest's public EU Ads Repository: promoted Pins by country, advertiser, dates, category, gender and age, with the advertiser name and landing link on each ad, reach bands, targeting and moderation status. 30 countries, 12 months, many advertisers per run, new ads only memory. Pay per ad.

- **URL**: https://apify.com/automation_craft/pinterest-ads-library-scraper.md
- **Developed by:** [Automation Craft](https://apify.com/automation_craft) (community)
- **Categories:** Marketing, Social media, E-commerce
- **Stats:** 1 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

### Pinterest Ads Library Scraper - EU Ads Repository

Get **Pinterest ads** from Pinterest's public EU Ads Repository as clean rows: every promoted Pin by country, advertiser, date window, category, gender and age, with the advertiser name and the landing link on each ad, the days it ran, the countries, the reach bands, the targeting and the moderation status. 30 countries (the 27 EU states plus Norway, Turkey and Brazil), the last 12 months, many advertisers and countries in one run, a memory that makes a daily watch pay only for new ads, no login, no API key, no proxy, no browser. You pay per ad, plus a small fee per search the repository answers; duplicates, unknown names, misses, coverage rows and the summary are free.

### Quick start

1. Pick the **countries** (one, several or ALL) and the date window (**startDate** and **endDate**; default the last 7 days; longer ranges are cut into 31 day slices for you).
2. Optional: **advertiserNames** (the repository's own names such as `TEMU DE` or `IKEA Deutschland`; case and accents do not matter). Set **advertiserNameMatch** to `contains` to search every advertiser whose name contains your text. Or paste **adIds** (pin ids or repository URLs) to fetch specific ads.
3. Optional filters: **categories**, **genders**, **ageBuckets**, **maxDaysSinceLastShown** (3 keeps the ads still running).
4. Set **maxAds** (default 100) and run. Export the dataset as JSON, CSV or Excel, or call the Actor from the API, n8n, Make or a schedule.
5. For a daily watch give a **memoryName**: the next run skips every ad already delivered under that name, free.

The default (prefilled) run reads Germany for the last 3 days and stops at 20 ads: about 5 seconds and 1.8 cents.

### What you get

One `ad` row per distinct ad. Fill rates were measured on 2,636 promoted Pin rows delivered by this Actor's builds 0.1.2 and 0.1.11 (the same code for names and links) on the Apify platform on 2026-10-06 (Germany, Austria and Norway, several advertisers and windows) and on 397 detail records of the feasibility probe of 2026-10-05.

| Field | What it is | Fill |
|---|---|---|
| `pinId`, `adUrl` | the ad's pin id (a string) and its page in the repository | 100% |
| `advertiserName`, `advertiserNames`, `advertiserNameStatus` | the advertiser as the repository names it, from the ad detail (the list pages carry no name) | 2,036 of 2,052 asked (99.2%); the 16 others are ads the repository holds no name for (disapproved ads), delivered free |
| `title`, `description` | the promoted Pin's text | 99.7% |
| `imageUrl`, `videoUrl` | the creative | 99.9%, video on about 2% |
| `landingUrl`, `landingDomain`, `landingLinkStatus` | where the ad sends the viewer, from the pin itself | 1,812 of 2,052 asked (88%); 237 pins (11.5%) had been deleted from Pinterest since the archive kept the ad (`pin_deleted`); the probe of 2026-10-05 saw 20% deleted on an older sample |
| `startDate`, `endDate`, `daysShown`, `daysSinceLastShown` | first and last day shown and the days between; the repository's dates run about two days behind the live state | 100% |
| `countries`, `countryCodes` | every country the ad ran in, as names and ISO codes | 99.3% |
| `reachEu`, `reachByCountry` | the EU reach band and the band per country (bands of 10,000 users; 93% of ads sit in `0 - 10000`) | 100% |
| `ageBuckets`, `genders` | the targeting (`18+`, `FEMALE`, `MALE`, `UNSPECIFIED` and finer buckets where set) | 99.3% |
| `audienceListTypes` | audience lists used: `VISITOR`, `USER_LIST`, `ACTALIKE`, `ENGAGEMENT` | 47% |
| `interests`, `regions`, `metros`, `postalCodes`, `devices`, `internetServiceProviders` | finer targeting, as the repository gives it | under 1% each (the archive is thin here) |
| `keywordsUsed`, `negativeKeywordsUsed`, `isCommercial`, `isLocalInventory`, `hasExcludedLocations` | targeting and content flags | 99.3% |
| `reviewStatus`, `statementOfReasons`, `violationSource`, `violationDecisionMeans` | moderation: `DISAPPROVED` ads carry Pinterest's reasons | about 1 in 150 ads |
| `isVerifiedMerchant`, `usesPinterestAi`, `destinationUrls`, `dynamicImages` | detail fields the repository sets on some ads | sparse |
| `pinCreatedAt`, `siteName` | the pin's creation date and the landing site's name, from the pin | on every pin that still exists (88%) |
| `pinnerName`, `pinnerUsername`, `pinnerUrl`, `pinnerFollowers`, `pinnerDomain`, `pinBoard` | the advertiser's Pinterest account, only with `includeAdvertiserAccount` (some advertisers are individual creators) | on every pin that still exists when asked |
| `adSource` | `pinterest` for a promoted Pin, `third_party` for an ad Pinterest serves for another network (title, image, advertiser, a numeric country code, no pin) | 900 third party rows of 3,536 in the platform runs, nearly all from Norway |
| `query` | the country, advertiser, filters and date slice that returned the ad | 100% |

Every run also writes free rows:

- one **`coverage`** row per query (country x advertiser x filters x 31 day slice): `pagesWalked`, `rowsSeen`, `distinctAds`, `repeatedRows`, `adsDelivered`, `adsBilled`, `knownSkipped`, `queryCharged`, `stopReason` (`end_of_results`, `page_budget`, `max_ads`, `charge_limit`, `server_error`, `rate_limit_budget`, `bad_request`, `blocked`, `unexpected_answer`, `aborted`, `timeout`), `complete`;
- **`status`** rows: `advertiser_not_found` (with the names Pinterest suggests), `advertiser_no_ads_in_window`, `ad_not_found`, `ad_not_recent` (an id outside `maxDaysSinceLastShown`), `invalid`, `query_failed`, `skipped`, `memory_free`;
- one **`summary`** row with every counter, the requests made and the billing facts.

### How much does it cost to scrape Pinterest ads?

| Event | FREE | BRONZE | SILVER | GOLD |
|---|---|---|---|---|
| **Ad** (one ad row delivered with the data above) | $0.80 per 1,000 | $0.80 per 1,000 | $0.70 per 1,000 | $0.60 per 1,000 |
| **Query** (one search the repository answered: a country, advertiser, filter and date slice, with or without ads; or one ad id found) | $0.30 per 1,000 | $0.30 per 1,000 | $0.30 per 1,000 | $0.30 per 1,000 |
| Actor start (once per run) | $0.002 | $0.002 | $0.002 | $0.002 |

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, "$0.30 / 1,000" on the Query row means one search costs 0.03 cents. Worked examples at Bronze: the prefilled run (one search, 20 ads) costs $0.0183; 1,000 ads from one search cost $0.8023; a daily watch of one advertiser in one country that finds nothing new costs $0.0023 (the start and one search); the same watch over all 30 countries costs about $0.011 (Norway counts one search per day). Nothing else is charged: duplicates across pages, queries and runs, ads already in your memory, ads whose advertiser name the repository does not hold, advertiser names the repository does not have (checked before any search runs), ad ids it does not know, searches it did not answer, coverage rows and the summary are free. The repository answers the Apify platform directly, so no proxy traffic is added to your bill.

### Input

| Field | Meaning | Default |
|---|---|---|
| `countries` | repository countries to search: ISO codes, names, or `ALL` for all 30; Norway is read one day at a time (a Norwegian week is seven searches) | `["DE"]` |
| `startDate`, `endDate` | the window, `YYYY-MM-DD`, `today`, `yesterday` or `N days` (counted back from the end date); an ad is returned when its run overlaps the window; ranges over 31 days are sliced | last 7 days |
| `advertiserNames` | advertisers to search, one per line, as the repository names them | none (every advertiser) |
| `advertiserNameMatch` | `exact` (the repository's own filter) or `contains` (every advertiser whose name contains the text, through Pinterest's own lookup) | `exact` |
| `adIds` | pin ids or repository URLs to fetch; given alone, only these ads are fetched | none |
| `categories`, `genders`, `ageBuckets` | the repository's filters (25 categories, 3 genders, 7 age buckets); several values become several searches, each ad delivered once | none |
| `maxDaysSinceLastShown` | keep only ads last shown within N days of today (3 keeps the running ads); third party ads carry no date and are left out when it is set | none |
| `maxAds` | most ads delivered and charged in one run | 100 |
| `maxPagesPerQuery` | pages of 100 per query before the walk stops and the coverage row says `page_budget` | 50 |
| `includeAdvertiserName` | fetch the detail of every ad (the only place with the advertiser name); off is faster and nameless | true |
| `includeLandingLink` | fetch the pin of every ad (landing link, pinner account, creation date); about 1 in 11 pins of a recent window has been deleted since | true |
| `includeThirdPartyAds` | deliver the third party ads the repository archives | true |
| `includeAdvertiserAccount` | add the advertiser's Pinterest account (name, username, profile URL, followers, verified domain, board) to each ad; off because some advertisers are individual creators | false |
| `memoryName` | a plain name; ads delivered under it before are skipped free | none |
| `resetMemory` | forget the memory before this run | false |
| `proxyConfiguration` | optional; the repository needs none, and the RESIDENTIAL group is replaced by the datacenter pool | off |

These alias keys are accepted too (`country`, `advertiserName`, `advertiser_name`, `markets`, `start_date`, `campaignStartDate`, `maxResults`, `maxItems`, `limit`, `category`, `age`, `gender`, `pinIds`, `startUrls`), so an existing JSON input can be pasted. A value that cannot be used as given (an unknown country, a date like `2026-09-31`, a cap of 0) ends as one free `invalid` row and no paid work.

### How the walk works, and what "complete" means

The repository lists a window one day at a time, 100 ads per page, repeats ads across pages and never says how many ads a query has. Pinterest also allows 20 list calls and 200 detail calls per minute per address; the Actor stays under both on one address and waits when asked. So a large advertiser (TEMU DE has about 5,000 ads active on a single day) or an unfiltered country can run to thousands of pages. Each query stops at `maxPagesPerQuery` and its coverage row says so (`complete: false`, `stopReason: page_budget`); the Actor never claims to have every ad of such a query. An advertiser plus a short window is the reliable unit, and that is what a daily watch with a `memoryName` does: new ads only, charged once, forever.

If the Apify platform restarts a run (a migration to another server), the ads delivered before the restart stay delivered and every row after it is free: a restarted run never charges.

### Memory across runs

Give every scheduled run the same `memoryName` (for example `temu-de-daily`). The Actor keeps the ids of the ads it delivered under that name in a key value store of its own and skips them free on the next run (`knownSkipped` on the coverage row). An ad delivered with its advertiser name is remembered; an ad delivered free because the repository held no name for it is not, so it comes back when it can be billed. One run at a time per name: the memory is locked by the running run (an exclusive platform lock), a second run on a busy name delivers free and remembers nothing, and if the memory cannot be opened, locked, read or saved, the run delivers everything free and says so in a `memory_free` row. `resetMemory` forgets the memory before the run.

### What this Actor does NOT do

- It does not promise every ad of a large advertiser or an unfiltered country: the repository lists a window day by day without a total; the coverage row tells you how far each query got.
- It does not return spend, impression counts, a payer, or demographics beyond age and gender: the repository publishes none of them.
- It does not flag an ad as active: the repository's end dates run about two days behind; use `daysSinceLastShown` and `maxDaysSinceLastShown`.
- It does not return the landing link of a pin deleted from Pinterest since the archive kept the ad (about 1 in 11 ads of a recent window, 1 in 5 on older ads); the row says `pin_deleted`.
- It does not cover the US or the UK: the repository is the EU Digital Services Act archive (27 EU states plus Norway, Turkey and Brazil); US and GB are refused by Pinterest.
- It does not read Norway in one piece: the repository answers a server error for any Norwegian window longer than one day, so Norway is read one day at a time (seven searches for a week).
- It does not add the advertiser's Pinterest account to the rows unless `includeAdvertiserAccount` is on: some advertisers are individual creators.
- It does not look up more than 20 unknown ad ids in a row: after 20 misses the remaining ids are skipped with a free row (misses are free; this bounds the work a wrong list can cause).
- It does not look up unknown advertiser names without limit either: each name is checked right before its first search, and a run may hit 10 names the repository does not know or cannot confirm (a probing search counts once more), plus 3 more for every search it has billed; when that allowance is spent the remaining names are skipped in one free row that lists them, and no search runs for them. A name the lookup cannot confirm (its answer was capped at 100 names without the exact one, or failed) gets one probing search, at most 5 such probes per run: records confirm it, no record ends its searches with a free row.
- It does not need, and does not use, a Pinterest login, a developer key, a residential proxy or a browser.
- It does not pass platform usage to you: the price is the events above.
- It does not monitor changes to an ad (an ad's end date moves every day it runs); the memory delivers new ads only.

### FAQ

#### Does Pinterest have an ad library like Facebook's Ad Library?

Yes, for the EU. Pinterest's Ads Repository is its Digital Services Act archive: every ad shown in the 27 EU states plus Norway, Turkey and Brazil during the last 12 months, with its creative, dates, countries, a reach band and basic targeting. This Actor turns a search of it into rows. There is no US or UK version; US and GB are refused by the repository.

#### Which countries does the Pinterest Ads Repository cover?

30: Austria, Belgium, Bulgaria, Croatia, Cyprus, Czech Republic, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Ireland, Italy, Latvia, Lithuania, Luxembourg, Malta, Netherlands, Norway, Poland, Portugal, Romania, Slovakia, Slovenia, Spain, Sweden, Turkey and Brazil. Give any number of them, or ALL; an ad shown in several of your countries is delivered and charged once.

#### How do I see a competitor's ads on Pinterest?

Put the advertiser's repository name in `advertiserNames` (case and accents do not matter) and pick the countries and dates. If you only know part of the name, set `advertiserNameMatch` to `contains` and the Actor searches every advertiser whose name contains your text, as Pinterest's own lookup lists them (up to 10 texts per run in this mode). An unknown name costs nothing and comes back as a free row with the names Pinterest suggests.

#### Can I see how much a competitor spends on Pinterest ads?

No. The repository publishes no spend, no impression counts and no payer. It gives a reach band per country and for the EU (most ads sit in the lowest band, 0 to 10,000 users), the days the ad ran, the countries and the age and gender targeting. The Actor returns exactly those.

#### Does it return every ad of an advertiser?

It returns every ad the repository lists for your query, one row each, and a free coverage row per query that says how many pages were walked, how many distinct ads came back and why the walk stopped. The repository lists a window one day at a time, repeats ads across pages and never says how many ads a query has, so large advertisers and unfiltered countries can run to thousands of pages; each query stops at `maxPagesPerQuery` (default 50) and says so. An advertiser plus a short window is the reliable unit.

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

Least privilege: it reads its input and writes its own run's dataset and key value store; with a `memoryName` it also creates and uses one named key value store of its own for that memory. It touches nothing else in your account.

### Use it from the API

```bash
curl -X POST "https://api.apify.com/v2/acts/automation_craft~pinterest-ads-library-scraper/runs?token=YOUR_TOKEN&waitForFinish=120" \
  -H "Content-Type: application/json" \
  -d '{"countries": ["DE", "AT"], "advertiserNames": ["TEMU DE"], "startDate": "7 days", "maxAds": 200}'
```

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('automation_craft/pinterest-ads-library-scraper').call({
    countries: ['FR'], advertiserNames: ['ikea'], advertiserNameMatch: 'contains', startDate: '30 days', maxAds: 500, memoryName: 'ikea-fr-weekly',
});
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/pinterest-ads-library-scraper").call(run_input={
    "adIds": ["https://ads.pinterest.com/ads-repository/4594867985295070848/"],
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item["type"] == "ad":
        print(item["advertiserName"], item["landingUrl"])
```

### Changelog

- 0.1 (2026-10-06): first release. Repository API with the rate rule respected on one address, advertiser name and landing link per ad, many countries and advertisers per run, name lookup with candidates, ad id lookup, 31 day slicing, memory across runs, coverage and status rows.

### More data tools by Automation Craft

Ad libraries: [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), [Instagram Ads Library Scraper - Creatives, Video](https://apify.com/automation_craft/instagram-ads-library-scraper), [Google Ads Transparency Scraper - Decoded Creatives](https://apify.com/automation_craft/google-ads-transparency-scraper), [Google Ads Library Scraper - Competitor Ads, No Login](https://apify.com/automation_craft/google-ads-library-scraper), [TikTok Ads Library Scraper: EU Ads, No Login](https://apify.com/automation_craft/tiktok-ads-library-scraper), [TikTok Creative Center Scraper: Top Ads, No Login](https://apify.com/automation_craft/tiktok-creative-center-scraper), [LinkedIn Ad Library Scraper: Ads by Company](https://apify.com/automation_craft/linkedin-ad-library-scraper), [YouTube Ads Scraper - Video Ads by Advertiser](https://apify.com/automation_craft/youtube-ads-scraper).

Other data: [LinkedIn Company Scraper - Details, No Login](https://apify.com/automation_craft/linkedin-company-scraper), [Yahoo Finance Scraper: Quotes, History, Financials](https://apify.com/automation_craft/yahoo-finance-scraper).

# Changelog

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

# Actor input Schema

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

Repository countries to search. ALL searches all 30 in one run. Country names such as Germany are accepted too. Each country is searched on its own; an ad found in several is delivered and charged once. Norway is read one day at a time (the repository answers a server error for longer Norwegian windows), so a Norwegian week is seven searches.

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

First day of the window, YYYY-MM-DD, or a number of days back from the end date such as 30 days. Default: 6 days before the end date (a 7 day window). An ad is returned when its run overlaps the window. Windows longer than 31 days are cut into 31 day slices automatically, newest first; the repository keeps 12 months.

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

Last day of the window, YYYY-MM-DD, today or yesterday. Default: today.

## `advertiserNames` (type: `array`):

One advertiser per line. With exact matching the name must equal a repository advertiser name (an unknown name costs nothing and comes back as a free row with the names Pinterest suggests; a run may hit 10 unknown or unconfirmed names plus 3 per billed search, then skips the rest in one free row; a name the lookup cannot confirm gets one probing search, at most 5 per run). With contains matching every advertiser whose name contains the text is searched (ikea gives IKEA Deutschland, IKEA France and the rest).

## `advertiserNameMatch` (type: `string`):

exact: the repository's own exact name filter. contains: expand each name (at most 10 per run) through Pinterest's advertiser lookup to every advertiser whose name contains it, then search each of them (the rows carry both the typed text and the resolved name).

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

Look up specific ads: pin ids or repository URLs such as https://ads.pinterest.com/ads-repository/4594867985295070848/, one per line. An id the repository does not know costs nothing and comes back as a free row. Given on its own (no countries or advertisers), only these ads are fetched.

## `categories` (type: `array`):

Pinterest's ad categories (verticals). Leave empty for all.

## `genders` (type: `array`):

Only ads targeted at these genders. Leave empty for all.

## `ageBuckets` (type: `array`):

Only ads targeted at these age groups. Leave empty for all.

## `maxDaysSinceLastShown` (type: `integer`):

Deliver only ads whose last shown day is at most this many days before today. The repository's dates run about two days behind the live state, so 3 keeps the ads still running and drops the ended ones. Ads without a last shown day (the third party ads) are left out when this is set. Leave empty for every ad of the window, running or ended.

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

Most ads delivered (and charged) in one run, across all countries and advertisers. Default 100 when the field is left empty.

## `maxPagesPerQuery` (type: `integer`):

The repository lists 100 ads per page and never says how many a query has; large advertisers and unfiltered countries can run to thousands of pages. Each query (country x advertiser x filters x 31 day slice) stops after this many pages and its coverage row says so. Default 50 (5,000 rows).

## `includeAdvertiserName` (type: `boolean`):

Fetch the ad detail for every ad (the only place the repository names the advertiser). Off: faster and the rows carry no advertiser name.

## `includeLandingLink` (type: `boolean`):

Fetch the pin for every ad: the landing URL and domain, the pinner account, the pin creation date. About 1 in 11 pins of a recent window (1 in 5 of older ads) has been deleted from Pinterest since; those rows say pin_deleted.

## `includeThirdPartyAds` (type: `boolean`):

The repository also archives ads Pinterest serves for third party networks (title, image, advertiser, a numeric country code, no pin). They appear as rows with adSource third_party.

## `includeAdvertiserAccount` (type: `boolean`):

Add the advertiser's Pinterest account to each ad: account name, username, profile URL, follower count, verified domain, board. Off by default: some advertisers are individual creators, so this is personal data. Needs the landing link switch on (both come from the pin).

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

A plain name for this watch, for example temu-de-daily. Ads delivered under it in earlier runs are skipped free. Leave empty for no memory.

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

Forget every ad remembered under the memory name before this run (every ad in the window counts as new again).

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

Optional Apify proxy. Leave off for the container address.

## Actor input object example

```json
{
  "countries": [
    "DE"
  ],
  "startDate": "3 days",
  "advertiserNames": [],
  "advertiserNameMatch": "exact",
  "adIds": [],
  "categories": [],
  "genders": [],
  "ageBuckets": [],
  "maxAds": 20,
  "maxPagesPerQuery": 50,
  "includeAdvertiserName": true,
  "includeLandingLink": true,
  "includeThirdPartyAds": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# 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 = {
    "countries": [
        "DE"
    ],
    "startDate": "3 days",
    "advertiserNames": [],
    "advertiserNameMatch": "exact",
    "adIds": [],
    "categories": [],
    "genders": [],
    "ageBuckets": [],
    "maxAds": 20,
    "maxPagesPerQuery": 50,
    "includeAdvertiserName": true,
    "includeLandingLink": true,
    "includeThirdPartyAds": true,
    "includeAdvertiserAccount": false,
    "resetMemory": false,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/pinterest-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 = {
    "countries": ["DE"],
    "startDate": "3 days",
    "advertiserNames": [],
    "advertiserNameMatch": "exact",
    "adIds": [],
    "categories": [],
    "genders": [],
    "ageBuckets": [],
    "maxAds": 20,
    "maxPagesPerQuery": 50,
    "includeAdvertiserName": True,
    "includeLandingLink": True,
    "includeThirdPartyAds": True,
    "includeAdvertiserAccount": False,
    "resetMemory": False,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("automation_craft/pinterest-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 '{
  "countries": [
    "DE"
  ],
  "startDate": "3 days",
  "advertiserNames": [],
  "advertiserNameMatch": "exact",
  "adIds": [],
  "categories": [],
  "genders": [],
  "ageBuckets": [],
  "maxAds": 20,
  "maxPagesPerQuery": 50,
  "includeAdvertiserName": true,
  "includeLandingLink": true,
  "includeThirdPartyAds": true,
  "includeAdvertiserAccount": false,
  "resetMemory": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call automation_craft/pinterest-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/pinterest-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/3c5bTjuHl65uK30uF/builds/iPavJhb6N5jeJhQJW/openapi.json
