# Pinterest Scraper · Exact Saves for Search, Boards & Profiles (`thequietstack/pinterest-scraper`) Actor

Pinterest scraper for keyword search, boards, profiles and pin URLs. Returns the exact save count Pinterest shows on each pin (not repin\_count), saves per day, flat CSV-ready rows, filters for minimum saves and date. No login, no residential proxy, pay only per pin written.

- **URL**: https://apify.com/thequietstack/pinterest-scraper.md
- **Developed by:** [TheQuietStack](https://apify.com/thequietstack) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 pins

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 · Exact Saves for Search, Boards & Profiles

Scrape Pinterest pins by **keyword search**, **board URL**, **profile** or **pin URL**. Every pin becomes one flat, CSV-ready row with the **exact save count Pinterest shows on the pin**, saves per day, repins, reactions, comments, image, outbound link, board, pinner and an ISO creation date. No login, no Pinterest account, no cookies, no residential proxy.

### Why this scraper

- **The real save count, also for search results.** Pinterest's search results do not include how often a pin was saved. This Actor fetches each search hit's own pin data to get the number shown on the pin, so search, boards and profiles all come back with the same `saves` field. The run summary says per source where each count came from (`savesFromFeed`, `savesFromPinPage`).
- **Saves are not repins.** Pinterest has two different counters. `repin_count` is often a small fraction of the saves: on pin 99360735500167749 it is 4,835 against 101,743 saves (measured 24 Sep 2026). You get both, in separate columns, so you never rank pins by the wrong number.
- **Find the winners, not just the pins.** `savesPerDay` (saves ÷ days since the pin was created) shows what is taking off right now instead of what is merely old. Sort each source by `saves`, `savesPerDay` or `newest`, or keep only pins above `minSaves` or newer than `sinceDate`.
- **Flat rows.** One level, no nested JSON: drops straight into Sheets, Excel or Airtable.
- **You only pay for pins you get.** Filtered pins, ads (promoted pins), duplicates across sources and inputs that fail are never charged. `maxPins` is a hard cap on the run and therefore on the bill. A source that returns nothing says why in the run summary instead of coming back empty.
- **No residential proxy needed.** Pinterest answered every request from Apify's own IPs (341 of 341 in the test run below), so runs stay cheap and nothing is billed to you as proxy traffic.

### Input example

```json
{
    "searchTerms": ["minimalist desk setup", "vegan meal prep"],
    "boardUrls": ["https://www.pinterest.com/marthastewart/american-made/"],
    "profileUrls": ["bhg"],
    "pinUrls": ["https://www.pinterest.com/pin/99360735500167749/"],
    "maxPinsPerSource": 200,
    "maxPins": 1000,
    "minSaves": 50,
    "sinceDate": "2026-01-01",
    "sortBy": "savesPerDay"
}
```

Any country domain works (`de.pinterest.com`, `pinterest.co.uk`, ...), and so do `pin.it` short links.

### Output example

```json
{
    "pinId": "99360735500167749",
    "url": "https://www.pinterest.com/pin/99360735500167749/",
    "title": "Next stop: Pinterest!",
    "description": "Love my Pinterest t-shirt!",
    "imageUrl": "https://i.pinimg.com/originals/a7/66/56/a76656e966b1958f568d63c3f1c05aec.jpg",
    "imageWidth": 640,
    "imageHeight": 478,
    "link": "http://www.flickr.com/photos/kentbrew/6851755809/",
    "domain": "flickr.com",
    "saves": 101743,
    "savesPerDay": 19.94,
    "repinCount": 4835,
    "reactions": 4,
    "comments": 35,
    "shares": 23,
    "isVideo": false,
    "videoUrl": null,
    "isPromoted": false,
    "board": "Adventures at Pinterest",
    "boardUrl": "https://www.pinterest.com/kentbrew/adventures-at-pinterest/",
    "pinner": "kentbrew",
    "pinnerName": "Kent Brewster",
    "pinnerFollowers": 4589,
    "createdAt": "2012-10-04T21:50:37.000Z",
    "ageDays": 5102.1,
    "hashtags": [],
    "altText": null,
    "dominantColor": "#e77b60",
    "sourceType": "pin",
    "source": "pinUrls",
    "rank": 1,
    "scrapedAt": "2026-09-24T00:00:00.000Z"
}
```

| Field | Meaning |
|---|---|
| `saves` | The save count Pinterest shows on the pin, at scrape time |
| `savesPerDay` | `saves` ÷ age in days (minimum 1 day), 2 decimals |
| `repinCount` | Pinterest's separate repin counter, not the same as saves |
| `reactions`, `comments`, `shares` | As Pinterest reports them (`shares` only where Pinterest hands it out) |
| `link`, `domain` | Where the pin leads; empty for pins uploaded without a link |
| `pinnerFollowers` | Follower count of the account that saved the pin, where Pinterest includes it |
| `createdAt`, `ageDays` | ISO 8601 UTC; age at scrape time |
| `sourceType`, `source`, `rank` | How the pin was found (`search`, `board`, `profile`, `pin`) and its position there |

The run summary (`SUMMARY` in the key-value store) lists per source: pins written, fetched, where the save counts came from, filtered out by reason, pages, why paging stopped, and HTTP status counts for the whole run.

### Tested

Run on the Apify platform on 24 Sep 2026: one keyword, one board, one profile, 300 pins each requested. **893 pins written, 341 requests, all HTTP 200, no proxy.** Three pins checked by hand against their pin pages: saves, repins, board and pinner matched exactly.

### Honest limits

- Only what Pinterest shows logged out: public pins, boards and profiles. Secret boards, private profiles and comment texts are not included.
- **Search needs one extra request per pin** for the exact save count (turn off `exactSaves` for speed; `saves` then stays empty for search hits). Board and profile pins already carry saves.
- A board can return a few pins less than its pin counter says (293 of 299 on the test board): Pinterest counts pins it no longer serves.
- Some pins have no title; `title` is empty then rather than made up.
- `sortBy` orders the pins collected per source; it does not make Pinterest return a different set.
- Counts are a snapshot at scrape time.

### Pricing (pay per event)

- Actor start: tiny flat fee per run
- Per pin written to the dataset. No charge for filtered pins, promoted pins, duplicates, or sources that return nothing.

# Actor input Schema

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

Pinterest pin search, same as typing into pinterest.com. Search results do not contain save counts, so each pin's own data is fetched to get the exact number (see 'Exact save counts').

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

https://www.pinterest.com/<user>/<board>/ (any country domain, pin.it short links work).

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

https://www.pinterest.com/<user>/ or just the username. Returns the pins on that profile, newest first.

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

https://www.pinterest.com/pin/<id>/ or the numeric ID. One row per pin with full detail.

## `maxPinsPerSource` (type: `integer`):

Stops each source after this many written pins.

## `maxPins` (type: `integer`):

The run stops here, whatever the sources say. You are charged per written pin only, so this is also your spending cap.

## `exactSaves` (type: `boolean`):

Board and profile feeds already include saves. Search results do not; with this on, each search hit's own pin data is fetched to get the save count Pinterest shows on the pin. Off = faster, saves stay empty for search hits.

## `minSaves` (type: `integer`):

Filtered pins are not written and not charged.

## `sinceDate` (type: `string`):

YYYY-MM-DD. Filtered pins are not written and not charged.

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

Sorts the pins collected per source before writing them.

## `skipPromoted` (type: `boolean`):

Promoted pins are skipped and not charged.

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

Not needed: Pinterest answered from Apify's plain IP. Turn on the datacenter proxy only if you see HTTP 429 in the run summary.

## Actor input object example

```json
{
  "searchTerms": [
    "minimalist desk setup",
    "vegan meal prep"
  ],
  "boardUrls": [
    "https://www.pinterest.com/marthastewart/american-made/"
  ],
  "profileUrls": [
    "marthastewart"
  ],
  "pinUrls": [
    "https://www.pinterest.com/pin/99360735500167749/"
  ],
  "maxPinsPerSource": 100,
  "maxPins": 1000,
  "exactSaves": true,
  "sortBy": "pinterest",
  "skipPromoted": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `pins` (type: `string`):

One flat row per pin: title, description, image, outbound link, exact saves, saves per day, repins, reactions, comments, board, pinner, ISO created date.

## `summary` (type: `string`):

Per keyword/board/profile: pins written, fetched, where the save count came from, filtered out, why paging stopped, HTTP status counts.

# 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": [
        "minimalist desk setup"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("thequietstack/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 = { "searchTerms": ["minimalist desk setup"] }

# Run the Actor and wait for it to finish
run = client.actor("thequietstack/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 '{
  "searchTerms": [
    "minimalist desk setup"
  ]
}' |
apify call thequietstack/pinterest-scraper --silent --output-dataset

```

## MCP server setup

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