# Pinterest Ad Library Scraper — Ad Search & Export (`devilscrapes/pinterest-ad-library-scraper`) Actor

Export ad records from Pinterest's public Ads Repository — pin id, title, image, date range, countries, genders, age buckets, and EU reach. Filter by country, date window, advertiser name, gender, and ad vertical. Covers EU27, Brazil, and Turkey. Deduplicated rows, no login required.

- **URL**: https://apify.com/devilscrapes/pinterest-ad-library-scraper.md
- **Developed by:** [DevilScrapes](https://apify.com/devilscrapes) (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

Pay per event

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

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

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

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

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

# README

<div align="center">
  <img src=".actor/icon.svg" width="160" alt="Devil Scrapes mark" />

## Pinterest Ad Library Scraper

**💰 $3.20 / 1 000 ads**  ·  pay only for results  ·  no credit card to try

*Captchas are our cardio — this one just needed pacing, not muscle.* 😈

Search Pinterest's public **Ads Repository** by country and date window and get every matching ad back as clean, deduplicated rows — pin id, title, image, date range, countries, genders, age buckets, and EU reach. No Pinterest login or API key needed.

</div>

***

> **Quick answer:** The **Pinterest Ad Library Scraper** searches Pinterest's public Ads Repository by country and date range and returns every matching ad as structured, deduplicated data — pin id, title, creative image, delivery date window, targeted countries/genders/age buckets, and EU reach count. No Pinterest developer account or API key is required. Pricing is pay-per-result — **$3.20 per 1 000 ads landed**, no subscription, no card required to try it. Coverage is **EU27, Brazil, and Turkey** — this is not a global or US ad library.

### 🎯 What this scrapes

Pinterest's Ads Repository is its public transparency registry for ads running across the EU, Brazil, and Turkey. This Actor searches it by country and date window — optionally narrowed by advertiser name, gender, or ad vertical — and walks Pinterest's own pagination cursor to pull every matching ad.

Per ad you get:

| Field | Type | Notes |
|---|---|---|
| `pin_id` | string | Pinterest's stable id for this pin — our dedup key |
| `title` | string | Pin title |
| `image_link` | string | Creative image URL |
| `start_date` / `end_date` | string | Ad delivery window, `YYYY-MM-DD` |
| `countries` | array | Countries this ad ran in, as Pinterest's own full names (e.g. `"Germany"`, not `"DE"`) |
| `genders` | array | Gender targeting buckets reported |
| `age_buckets` | array | Age targeting buckets reported |
| `user_count_eu` | string | Reported EU reach as a bucketed range, e.g. `"0 - 10000"` |
| `query_country` | string | The country your search used |
| `advertiser_name` | string | Echo of your filter, when set |
| `scraped_at` | string | ISO-8601 UTC timestamp |

### 🔥 What we handle for you

- 🛡️ **We rotate browser fingerprints** (curl-cffi impersonation — Chrome and Firefox) on every page, even though this endpoint's limiter is request-based, not fingerprint-based — a cheap hedge against Pinterest tightening that later.
- 🧱 **We back off when Pinterest rate-limits.** Its Ads Repository allows roughly 20 pages before a sliding-window `429` — we pause 45 seconds and resume from the exact same pagination cursor, never losing your place or failing the run.
- 🧊 **We deduplicate every row.** Pinterest repeats close to a third of records across pages; we track unique pin ids incrementally so your dataset count is always the true number of unique ads, never `pages × page size`.
- 🔁 **We retry with exponential backoff** on server errors and network hiccups, honoring `Retry-After` — up to 5 attempts per page.
- 💰 **You pay only for results that land.** No data → no charge (only the small `actor-start` warm-up fee).

### 💡 Use cases

- **Competitor ad monitoring** — track what a competitor brand is currently running on Pinterest in your target EU/BR/TR market.
- **Ad creative research** — pull dozens to hundreds of live pin titles and images for a market/date window to inform your own creative testing.
- **Brand protection** — search your own brand name via `advertiser_name` to spot unauthorized advertisers.
- **Market research** — gauge Pinterest ad activity for a vertical across the EU, Brazil, and Turkey.
- **Agency reporting** — export a client's (or a competitor's) live Pinterest ad set straight to a spreadsheet.
- **AI / RAG ingestion** — feed titles and creative image URLs into a vector store for creative-trend analysis.

### ⚙️ How to use it

1. **Click "Try for free"** at the top of the page.
2. **Set a start date** (`YYYY-MM-DD`) — required. This is the beginning of the delivery window you want to search.
3. **Set a country** — required, ISO-3166 alpha-2 (e.g. `DE`, `FR`, `BR`). The Ads Repository only covers EU27, Brazil, and Turkey.
4. *(Optional)* Narrow the search with an end date, advertiser name, gender, or ad vertical.
5. **Run.** Each unique ad is one row in the dataset; export to JSON, CSV, or Excel from the Storage tab.

The first run on a new account uses $5 of free Apify credit — that's roughly **1 500 ads** at our pricing.

### 📥 Input

The schema lives in `.actor/input_schema.json`. The fields:

| Field | Type | Required | Default | Notes |
|---|---|:--:|---|---|
| `start_date` | string | yes | — | `YYYY-MM-DD`, repository window start |
| `country` | string | yes | — | ISO-3166 alpha-2 (e.g. `DE`); uppercased automatically |
| `end_date` | string | no | `null` | `YYYY-MM-DD`, repository window end |
| `advertiser_name` | string | no | `null` | Free-text advertiser filter, no autocomplete |
| `gender` | string | no | `null` | Optional passthrough filter |
| `ad_vertical` | string | no | `null` | Optional passthrough filter |
| `maxResults` | integer | no | `500` | Cap on unique deduplicated rows |
| `maxPages` | integer | no | `20` | Soft ceiling on pagination round-trips (never a hard-fail) |
| `proxyConfiguration` | proxy config | no | no proxy | This endpoint returns 200 with zero proxy by default |

`start_date` and `country` are both required — the Actor fails fast if either is missing, before any network call or charge.

**Proxy defaults to none, on purpose.** Pinterest's Ads Repository answers with a plain 200 with zero proxy involved, so we don't force a residential tier you'd pay for and not need. If you opt into Apify Proxy anyway, we pin the exit country to your `country` input — a floating exit could otherwise return a plausible-looking result set for the wrong market.

#### Example input

```json
{
  "start_date": "2026-08-01",
  "country": "DE",
  "maxResults": 100,
  "maxPages": 5,
  "proxyConfiguration": { "useApifyProxy": false }
}
```

### 📤 Output

Every row is one unique ad. Example:

```json
{
  "pin_id": "1074427839201234567",
  "title": "Summer sale — 30% off sneakers",
  "image_link": "https://i.pinimg.com/originals/ab/cd/ef/example.jpg",
  "start_date": "2026-08-01",
  "end_date": "2026-08-31",
  "countries": ["Germany", "France", "Brazil"],
  "genders": ["FEMALE", "MALE"],
  "age_buckets": ["25-34", "35-44"],
  "user_count_eu": "100000 - 500000",
  "query_country": "DE",
  "advertiser_name": null,
  "scraped_at": "2026-09-13T10:15:00+00:00"
}
```

Export options once the run finishes:

- **JSON** — full payload
- **CSV / Excel** — for analyst spreadsheets
- **JSONL** — line-delimited, easy to stream into a warehouse
- **API** — fetch programmatically via `GET /v2/datasets/{id}/items`; webhook on `ACTOR.RUN.SUCCEEDED` for live pipelines

### 💰 Pricing

Pay-per-event. You pay for what you get, nothing for what you ask for:

| Event | Price | When charged |
|---|---:|---|
| `actor-start` | **$0.20** | Base fee, once per run (warm-up, input validation) |
| `ad-result` | **$0.003** | Per unique `pin_id` written to the dataset |

**Examples**:

| Pull | Cost |
|---|---:|
| 100 ads | $0.50 |
| 1 000 ads | $3.20 |
| 10 000 ads | $30.20 |

### 🚧 Limitations

- **Coverage is EU27, Brazil, and Turkey — not global or US.** Pinterest's own Ads Repository doesn't publish for other markets, so we don't fabricate results for them. If you need US Pinterest ad data, this Actor isn't the right tool.
- **~33% of raw records repeat across pages.** We absorb this with incremental dedup, so your dataset's row count is always the true unique count — but it means the source itself isn't clean, and a `maxPages` sized too small can undercount if the overlap lands unevenly.
- **The rate-limit window means a large `maxPages` run can take longer than `maxPages × 5s`.** If Pinterest rate-limits mid-run, we pause 45 seconds and resume — the run still finishes, just not on the fastest possible clock.
- **No advertiser-name autocomplete.** `advertiser_name` is a free-text filter with no validation against Pinterest's own advertiser list — the lookup endpoint that would provide that requires Pinterest authentication we don't have and don't attempt to bypass.
- **No public per-ad URL.** Unlike some other ad libraries, Pinterest's Ads Repository doesn't expose a deep link back to a public page for each ad, so we don't invent one.

### ❓ FAQ

**Is this legal?**

Yes. Pinterest's Ads Repository is a public transparency registry Pinterest operates for EU DSA and related regulatory requirements. We search only what the public endpoint exposes, at a paced rate, with no login wall or paywall involved.

**Do I need a Pinterest developer account or API key?**

No. This Actor works entirely against the public Ads Repository endpoint — no app registration, no OAuth, no access token.

**Why does my result count sometimes look lower than expected?**

Two reasons: your `maxPages`/`maxResults` caps, and the ~33% cross-page duplicate rate the endpoint itself produces, which we dedupe out rather than count twice.

**Can I search a specific advertiser?**

Yes — set `advertiser_name` to a free-text value. There's no autocomplete against Pinterest's own advertiser list (that lookup requires Pinterest authentication), so match it as closely as you can to how the brand appears on Pinterest.

**How do I schedule this to run automatically?**

Apify Console → Schedules → attach this Actor → set your cron. Weekly is plenty; ad libraries don't turn over fast enough to need more.

**What integrations does this Actor support?**

- **Schedule** — Apify Console → Schedules for recurring monitoring.
- **Webhooks** — register `ACTOR.RUN.SUCCEEDED` to fire a downstream pipeline.
- **API** — `POST /v2/acts/DevilScrapes~pinterest-ad-library-scraper/run-sync-get-dataset-items` for a single synchronous pull.
- **Make / Zapier** — every Apify Actor surfaces as a node out of the box.

### 💬 Your feedback

Spotted a bug, missing field, or want a new feature? Open an issue on the [Apify Store listing](https://apify.com/DevilScrapes/pinterest-ad-library-scraper) — we read every one.

Built by **Devil Scrapes** — Apify Actors with attitude. PPE, transparent pricing, no junk fields.

# Actor input Schema

## `start_date` (type: `string`):

Repository window start, <code>YYYY-MM-DD</code>. Required.

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

ISO-3166 alpha-2 market to search, e.g. <code>DE</code>. Required. Also pins the proxy exit if Apify Proxy is enabled. The Ads Repository covers EU27, Brazil, and Turkey only — not a global/US ad library.

## `end_date` (type: `string`):

Repository window end, <code>YYYY-MM-DD</code>. Optional — omit to search open-ended.

## `advertiser_name` (type: `string`):

Optional free-text advertiser filter. No autocomplete/validation against Pinterest's advertiser list.

## `gender` (type: `string`):

Optional passthrough gender filter, as accepted by the Ads Repository.

## `ad_vertical` (type: `string`):

Optional passthrough ad-vertical filter, as accepted by the Ads Repository.

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

Cap on unique deduplicated pin rows written to the dataset.

## `maxPages` (type: `integer`):

Soft ceiling on bookmark-cursor pagination round-trips — never a hard-fail condition. At ~25 rows/page and ~5s/page pacing, the default covers a few minutes of fetch time before dedup.

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

Apify Proxy. The Ads Repository returns 200 with zero proxy, so this defaults to no proxy. If you opt in, the exit country is pinned to <em>Country</em> above — a geo-random exit can otherwise return a plausible but wrong-market result set.

## Actor input object example

```json
{
  "start_date": "2026-08-01",
  "country": "DE",
  "end_date": null,
  "advertiser_name": null,
  "gender": null,
  "ad_vertical": null,
  "maxResults": 500,
  "maxPages": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

Full set of scraped ads — one item per unique pin. Streamed JSON via the Apify dataset API.

## `datasetItemsCsv` (type: `string`):

Same data, CSV export. Drop straight into a spreadsheet or warehouse loader.

## `datasetView` (type: `string`):

Open the run's dataset in the Console with the Overview view applied.

# 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 = {
    "start_date": "2026-08-01",
    "country": "DE",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/pinterest-ad-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 = {
    "start_date": "2026-08-01",
    "country": "DE",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/pinterest-ad-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 '{
  "start_date": "2026-08-01",
  "country": "DE",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call devilscrapes/pinterest-ad-library-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,devilscrapes/pinterest-ad-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/L6HDbNZ0QhYzAgBgf/builds/k0rdbWKCa356dLFV9/openapi.json
