# Pinterest Scraper — Pins, Boards, Search, Products (`dottti/pinterest-scraper`) Actor

Public Pinterest pins from keyword search, boards, sections, profiles and pin links. No login. Images in all sizes, video, outbound link and domain, saves, board and pinner info, product price when shown. Only-new alert mode. Status row per input; failed inputs are free.

- **URL**: https://apify.com/dottti/pinterest-scraper.md
- **Developed by:** [Dottti](https://apify.com/dottti) (community)
- **Security:** Limited permissions
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

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?

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 Scraper: Pins, Boards, Search, Products

Get public Pinterest pins from keyword searches, boards, board sections, profiles and single pin links. Each pin comes back as one flat row: title, description, outbound link and domain, image links in four sizes, video links, save and repin counts where Pinterest shows them, product price when Pinterest shows it, plus the board and the account that saved it.

The actor needs no Pinterest account, no cookies and no browser. It reads the same public data that Pinterest shows to a logged-out visitor.

### Who uses it

- **E-commerce teams** who check which products, shops and domains show up for a keyword, and how pins link out to stores.
- **Marketing and content teams** who track their own boards and competitors' boards and profiles on a schedule.
- **Trend researchers** who collect the top pins for a list of keywords, in any language, with the rank of each pin.
- **AI pipelines** that need clean JSON with image links, alt text and descriptions.

### What you put in

| Field | Example | What you get |
|---|---|---|
| Search keywords | `boho living room`, `ديكور غرفة نوم` | Pins in Pinterest's order. `position` 1 is the top result. |
| Board links | `https://www.pinterest.com/IKEAUSA/living-rooms/` or a section `.../sephora/makeup/eyes/` | One board row and the board's pins. |
| Profiles | `ikeausa` or `https://www.pinterest.com/marthastewart/` | One profile row and the pins the account created, newest first. |
| Pin links | `https://www.pinterest.com/pin/252834966578398817/`, a `pin.it` link, or the pin number | The full pin. |

`Max pins per input` caps each keyword, board and profile. Pinterest pages 25 pins at a time.

### What you get

Every row has a `type` field.

- `pin`: `pinId`, `pinUrl`, `title`, `description`, `altText`, `link`, `domain`, `createdAt` (ISO 8601, UTC), `dominantColor`, `imageUrl` (original size) with `imageWidth` and `imageHeight`, `imageUrl736`, `imageUrl474`, `imageUrl236`, `isVideo`, `videoUrl` (MP4), `videoHlsUrl`, `videoDurationSec`, `saveCount`, `repinCount`, `commentCount`, `reactionCount`, `hashtags`, `topics`, `isPromoted`, `richSiteName`, product fields (`isProduct`, `productName`, `productBrand`, `productPrice`, `productCurrency`, `productAvailability`, `productInStock`), board fields (`boardId`, `boardName`, `boardUrl`), pinner fields (`pinnerUsername`, `pinnerFullName`, `pinnerFollowerCount`, `pinnerProfileUrl`), and where the row came from (`sourceType`, `sourceInput`, `searchQuery`, `position`).
- `profile`: username, name, about, website, follower count, following count, pin count, board count, video pin count, monthly views, profile image. Follower lists are never collected.
- `board`: name, link, description, pin count, follower count, section count, category, owner, cover image.
- `status`: one row for each input that returned nothing or failed (missing account, missing board, bad link, blocked). Status rows are free.

#### Pin links for search and board pins

Logged out, Pinterest hides the real pin number in search results and board feeds. It shows a masked id such as `e1_AfqPShx...` instead, and a link built from it does not open. So:

- Pins from profiles, board sections and pin links always have a real `pinUrl`.
- Pins from boards get a real `pinUrl` for the newest 50 pins of the board. Older board pins keep the masked id.
- Pins from search keep the masked id. `pinUrl` is `null` and `pinIdIsMasked` is `true`. Every other field is filled.

A masked id stays the same between runs, so you can use it to remove duplicates and for alerts.

#### Counts and product data

- Search results from Pinterest carry no save count. `saveCount` is `null` for search pins. Board, profile and pin rows have it.
- Turn on **Add full pin details** to fetch each board and profile pin's own data. This adds repin count, comment count, the MP4 video link and product data. It costs one extra request per pin, so the run takes longer. The price per row stays the same.
- Logged out, Pinterest shows a product price on few pins. When it does, `productPrice` and `productCurrency` are filled. When it does not, they are `null`. The actor never guesses a price.

### Examples from real runs (28 October 2026)

Input:

```json
{
  "searchQueries": ["boho living room", "ديكور غرفة نوم", "summer dress", "kitchen organization"],
  "boardUrls": [
    "https://www.pinterest.com/IKEAUSA/living-rooms/",
    "https://www.pinterest.com/sephora/makeup/eyes/",
    "https://www.pinterest.com/marthastewart/appetizers-and-hors-doeuvres-recipes/"
  ],
  "profileUrls": ["ikeausa", "https://www.pinterest.com/sephora/", "https://www.pinterest.com/anthropologie/"],
  "pinUrls": [
    "https://www.pinterest.com/pin/252834966578398817/",
    "https://www.pinterest.com/pin/24277285508518252/",
    "98938523062369812",
    "https://www.pinterest.com/pin/1096908053030636037/",
    "https://www.pinterest.com/pin/48061921672808523/"
  ],
  "maxPinsPerInput": 100
}
```

Result: 1,011 rows (1,005 pins, 3 profiles, 3 boards), 15 of 15 inputs ok, 59 requests, 24 seconds.

A search pin (long text shortened here):

```json
{
  "type": "pin",
  "pinId": "e1_AfqPShyOOUMVVH8R2i7raEnUIwAdqygH0ZSgYO_8xlMFQEnbZzxH",
  "pinIdIsMasked": true,
  "pinUrl": null,
  "title": "Kitchen Cabinet Organization Ideas | Mug & Bowl Storage",
  "description": "Make your kitchen cabinets look organized, functional, and beautiful with these easy kitch...",
  "altText": "the shelves are filled with dishes and cups",
  "link": "https://amzn.to/4AEZe0X",
  "domain": "amzn.to",
  "createdAt": "2026-10-05T20:12:50.000Z",
  "dominantColor": "#b6a292",
  "imageUrl": "https://i.pinimg.com/originals/0e/b8/b4/0eb8b4e1d33fe4a7c5eab2f927290894.png",
  "imageWidth": 1000,
  "imageHeight": 1500,
  "imageUrl236": "https://i.pinimg.com/236x/0e/b8/b4/0eb8b4e1d33fe4a7c5eab2f927290894.jpg",
  "isVideo": false,
  "saveCount": null,
  "reactionCount": 17,
  "boardName": "Organization",
  "boardUrl": "https://www.pinterest.com/abbieshomefinds/organization/",
  "pinnerUsername": "abbieshomefinds",
  "sourceType": "search",
  "searchQuery": "kitchen organization",
  "position": 1
}
```

A board pin with its real id:

```json
{
  "type": "pin",
  "pinId": "252834966578271852",
  "pinIdIsMasked": false,
  "pinUrl": "https://www.pinterest.com/pin/252834966578271852/",
  "title": "Irresistible Accent Chairs",
  "link": "https://www.ikea.com/us/en/rooms/living-room/gallery/a-modern-living-room-with-a-timeless-...",
  "domain": "ikea.com",
  "createdAt": "2026-09-10T20:08:52.000Z",
  "saveCount": 1,
  "repinCount": 0,
  "richSiteName": "IKEA",
  "boardName": "Living Rooms",
  "pinnerUsername": "IKEAUSA",
  "sourceType": "board",
  "position": 1,
  "maskedPinId": "e1_AfqPShxTfbi0cisT88HXzJMeG50QfLi9VeS2iGQrXH5YLalfchQd"
}
```

A video pin from a pin link:

```json
{
  "type": "pin",
  "pinId": "24277285508518252",
  "pinUrl": "https://www.pinterest.com/pin/24277285508518252/",
  "title": "Red Sequin Mini Dress Outfit",
  "domain": "anthropologie.com",
  "isVideo": true,
  "videoUrl": "https://v1.pinimg.com/videos/iht/expMp4/76/7c/9f/767c9f21af3290c9fb7bb119529c2367_720w.mp4",
  "videoHlsUrl": "https://v1.pinimg.com/videos/iht/hls/76/7c/9f/767c9f21af3290c9fb7bb119529c2367.m3u8",
  "videoDurationSec": 5.7,
  "saveCount": 0,
  "repinCount": 0,
  "commentCount": 0,
  "boardName": "On My Way",
  "pinnerUsername": "anthropologie",
  "pinnerFollowerCount": 1941347
}
```

A board row:

```json
{
  "type": "board",
  "boardId": "252835035269372768",
  "name": "Living Rooms",
  "url": "https://www.pinterest.com/IKEAUSA/living-rooms/",
  "pinCount": 1202,
  "followerCount": 667519,
  "sectionCount": 6,
  "category": "home_decor",
  "ownerUsername": "IKEAUSA",
  "lastPinnedAt": "2026-10-27T21:41:12.000Z"
}
```

A status row (free):

```json
{
  "type": "status",
  "input": "IKEAUSA/nope-board-xyz",
  "kind": "board",
  "status": "not_found",
  "pins": 0,
  "error": "Pinterest says: Board not found. The account, board or pin may be private, removed, or the link is wrong.",
  "charged": false
}
```

Status values: `ok` (only in the run summary), `no_results`, `not_found`, `invalid_input`, `blocked`, `api_error`, `cut_by_cost_limit`, `skipped_cost_limit`.

### Alerts: only new pins

Turn on **Only new pins (alert mode)** and schedule the actor. The first run delivers everything and saves a baseline. Each later run delivers only pins that the same keyword, board, profile or pin did not return before. You pay only for new rows. Use a different **Alert state name** for each watchlist. The state lives in the named key-value store `pinterest-scraper-state`.

### How to schedule

1. Save your input as a task in Apify Console.
2. Open **Schedules**, create a schedule (for example every day at 08:00) and add the task.
3. Turn on alert mode if you want only new pins each time.
4. Connect the dataset to email, Slack, Google Sheets or a webhook with an Apify integration.

### Run summary

The `RUN_SUMMARY` record in the run's key-value store lists the status of every input, rows by type, average time per input type, requests, bytes and the proxy tier that was used.

### Pricing

You pay per result: **$1.00 per 1,000 rows** (pins, profiles and boards). Status rows are free. Failed inputs cost nothing. Platform usage is included in the price.

Set a maximum cost per run in Apify Console. When the limit is reached, the actor stops cleanly and marks the remaining inputs as `skipped_cost_limit`.

### Limits

- Public data only. Private boards, secret boards and deleted pins return a `not_found` status row.
- Real pin links are missing for search pins and for board pins older than the newest 50 (see above).
- Search results have no save count. Product prices appear only when Pinterest shows them logged out, which is rare.
- Follower and following lists are never collected.
- Profile pins are the pins the account created, newest first. Pins the account saved from others are not listed.
- Pinterest can change its web app at any time. The actor reads the current app version from Pinterest's own page at the start of each run and reports any failure as a status row.

### Proxy

By default the actor first runs with no proxy, moves to Apify datacenter proxy if Pinterest blocks, and uses residential proxy only as the last step. You can turn off the residential step or set your own proxy under **Advanced**.

# Actor input Schema

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

Keywords to search on Pinterest, in any language. Examples: boho living room, ديكور غرفة نوم, summer dress. You can also paste a Pinterest search link. You get the pins in Pinterest's order (position 1 = top result).

## `boardUrls` (type: `array`):

Pinterest boards or board sections. Examples: https://www.pinterest.com/IKEAUSA/living-rooms/, https://www.pinterest.com/sephora/makeup/eyes/ or IKEAUSA/living-rooms. You get one board row and its pins.

## `profileUrls` (type: `array`):

Pinterest usernames or profile links. Examples: ikeausa, https://www.pinterest.com/marthastewart/. You get one profile row (name, website, follower count, pin count, monthly views) and the pins the account created, newest first. Follower lists are never collected.

## `pinUrls` (type: `array`):

Single pins. Examples: https://www.pinterest.com/pin/252834966578398817/, a pin.it short link, or just the pin number. You get the full pin with saves, repins, comments count, video and product data when shown.

## `maxPinsPerInput` (type: `integer`):

Most pins to return for each keyword, board or profile. Pinterest pages 25 pins at a time.

## `searchType` (type: `string`):

Pins returns all pin types. Videos returns only video pins.

## `includePinDetails` (type: `boolean`):

For board and profile pins, fetch each pin's own page data too: repin count, comment count, MP4 video link, hashtags and product price when shown. One extra request per pin, so runs take longer. Search pins and pin links already include what Pinterest shows logged out.

## `includeSourceDetails` (type: `boolean`):

Adds one row per profile (name, about, website, follower count, pin and board counts, monthly views) and one row per board (name, description, pin count, follower count, owner). Each counts as one result.

## `onlyNew` (type: `boolean`):

Remembers which pins each keyword, board, profile and pin returned last time and delivers only new pins on the next run. Schedule the actor to get alerts. The first run delivers everything and saves the baseline. Profile and board rows are skipped in this mode. You pay only for new rows.

## `stateName` (type: `string`):

Name of the saved state for Only new pins. Use a different name for each watchlist or schedule.

## `maxConcurrency` (type: `integer`):

How many keywords, boards, profiles or pins to fetch at once.

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

Leave empty for the automatic ladder: no proxy first, then Apify datacenter, then residential only if Pinterest blocks. Set a proxy here to force it.

## `autoProxyFallback` (type: `boolean`):

Move to a proxy when Pinterest blocks direct requests.

## `allowResidentialFallback` (type: `boolean`):

Residential proxy costs more platform credit. Turn off to stop at datacenter.

## `maxRetries` (type: `integer`):

Retries per request with growing waits when Pinterest answers 429 or 5xx.

## Actor input object example

```json
{
  "searchQueries": [
    "boho living room"
  ],
  "maxPinsPerInput": 20,
  "searchType": "pins",
  "includePinDetails": false,
  "includeSourceDetails": true,
  "onlyNew": false,
  "stateName": "default",
  "maxConcurrency": 3,
  "autoProxyFallback": true,
  "allowResidentialFallback": true,
  "maxRetries": 4
}
```

# Actor output Schema

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

All rows. Filter by the type field.

## `runSummary` (type: `string`):

Status per input, rows by type, requests, bytes and proxy tier used.

# 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": [
        "boho living room"
    ],
    "maxPinsPerInput": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("dottti/pinterest-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": ["boho living room"],
    "maxPinsPerInput": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("dottti/pinterest-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "boho living room"
  ],
  "maxPinsPerInput": 20
}' |
apify call dottti/pinterest-scraper --silent --output-dataset

```

## MCP server setup

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