# Pinterest Boards Scraper (Pin Comments & Replies) (`simpleapi/pinterest-boards-scraper`) Actor

Collect actionable insights from Pinterest boards automatically. This scraper fetches board details, pins, images, videos, and engagement stats. Useful for competitive research, content strategy, and large-scale Pinterest data analysis.

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

## Pricing

from $2.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

### Pinterest Comments Scraper — Pin Threads, Reactions and Replies

Pinterest Comments Scraper reads a public Pinterest board, profile or pin and returns one row per pin — title, image, save count, board, pinner and outbound link — with the comment thread attached: verbatim text, commenter, reaction count, attached photos and each comment's own reply count. Turn on "Only pins with comments" and it drops every pin nobody talked about, turning a board into a reading list instead of a grid. Built for social listening teams, UGC researchers and community managers who need real customer language, not save counts.

### 🧭 What is Pinterest Boards Scraper (Pin Comments & Replies)?

It's a Pinterest comments scraper built on top of a full pin scraper: point it at a board URL, a profile URL or username, or a single pin URL or ID, and it returns every pin as a normalized JSON row with the comment thread nested underneath. No Pinterest account, login or API key is required — every request runs logged out, keyless, from a bare Apify datacenter exit.

- **Discovery by URL** — board (`/user/board/`), profile (`/user/` or a bare username), or a single pin (URL or numeric ID), one per line.
- **Core pin fields** — id, title, image variants, save/repin counts, board name, pinner username, outbound link and domain.
- **The comment thread** — verbatim text, commenter identity, reaction count, attached photos, and each comment's own reply count, attached as a nested `comments` array.
- **A discussion filter** — `commentedPinsOnly` keeps only pins with a real thread, with a scan ceiling so a silent multi-thousand-pin board can't run away with your run.
- **Optional enrichment** — creation date, share count, pinner follower count and board section, each gated behind its own input so you only pay for what you ask for.
- **Standard Apify dataset export** — JSON, CSV, Excel, HTML table, XML or RSS straight from the Console, or pulled via `apify-client`.

### 📊 What data can I extract with Pinterest Boards Scraper (Pin Comments & Replies)?

Every pin row carries content, media, engagement and board fields; the comment thread and board/section context are broken out below.

| Field | Example value | Use case |
| --- | --- | --- |
| `id` | `"1618549864585211"` | Pinterest's own pin ID, stable across runs |
| `type` | `"pin"` | `"error"` on a failed target — see [Output sample](#-output-sample) |
| `index` | `7` | Position of this row within its target |
| `pinUrl` | `"https://www.pinterest.com/pin/1618549864585211/"` | Canonical link back to the pin |
| `sourceUrl` | `"https://www.pinterest.com/HGTV/hgtv-dream-home/"` | The input URL this row came from |
| `title` / `gridTitle` | `"Walnut console table styling"` | Content title for a catalogue or content audit |
| `description` | `"Rich walnut finish, brass hardware, entryway styling."` | Longer copy for content review |
| `altText` | `"A walnut console table in a bright entryway"` | Accessibility text / image-SEO audits |
| `visualAnnotations` | `["furniture", "console table", "walnut"]` | Pinterest's own visual tags on the image |
| `imageUrl` / `images` | `[{"url": "...", "width": 736, "height": 1104, "quality": "736x", "extension": "jpg"}]` | Best-available still and every size variant returned |
| `dominantColor` | `"#a67b5b"` | Palette / swatch analysis |
| `hasVideo` / `videoDurationMs` / `videos` | `false` / `null` / `null` | Filters video pins; duration and renditions when present |
| `isIdeaPin` / `isRepin` | `false` / `true` | Content-type flags |
| `savesCount` (`repins`) | `4200` | Aggregated saves across every duplicate of the image — `null`, never `0`, when Pinterest sent nothing |
| `repinCount` | `12` | This pin's own save count — a different number from `savesCount` |
| `commentCount` / `shareCount` / `date` | `26` / `3` / `"2015-12-15T17:43:25Z"` | Only populated when `fetchPinDetails` is on |
| `externalLink` / `link` / `domain` | `"https://www.walmart.com/ip/..."` / same / `"walmart.com"` | Outbound destination for buyer-intent segmentation — `null` when `fetchLinkDetails` is off |
| `user` / `pinner` | `"HGTV"` / `{"id": "...", "username": "HGTV", "isVerifiedMerchant": false, "followerCount": 812000}` | Pinner identity; `followerCount` only with `fetchPinDetails` on |
| `nativeCreator` | `null` | Original creator when the pin was authored elsewhere |
| `scrapedAt` | `"2026-08-04T10:15:00Z"` | Run timestamp, UTC |

#### 🗣️ Comment thread data

Each pin row carries `hasComments`, `commentsCollected`, `commentCountReported` (Pinterest's own aggregated total) and `commentsTruncated`, plus the thread itself in `comments[]`:

| Field | Example value | Use case |
| --- | --- | --- |
| `id` / `type` | `"998877665544"` / `"aggregatedcomment"` | `aggregatedcomment` (written comment) or `userdiditdata` (a Pinterest "I tried it" post) — each keeps its text under a different key |
| `text` / `hasText` | `"Does this come in walnut? Mine arrived broken :("` / `true` | Verbatim — emoji and line breaks preserved exactly, never stripped |
| `createdAt` | `"2024-03-02T09:14:00Z"` | ISO 8601 UTC |
| `user` | `{"id": "...", "username": "jane_doe", "fullName": "Jane Doe", "isPrivateProfile": false}` | Commenter identity |
| `replyCount` | `2` | This comment's own reply count — reply text itself isn't retrievable, see FAQ |
| `reactionCount` | `5` | Sum of Pinterest's reaction types, or `like_count` on an "I tried it" post |
| `helpfulCount` / `isEdited` | `0` / `false` | Pinterest's "helpful" tally; edit flag (written comments only) |
| `mediaUrls` | `[]` | Photo attachments — populated on "I tried it" posts and sticker replies |

One concrete use case: a home-goods brand pulls `commentsCollected`, filters `hasText: true`, and reads every `text` value against its own board to catch "does it come in walnut" and "mine arrived broken" before they turn into support tickets — data saves counts never surface.

#### 🎯 Board and targeting data

The fields you segment and scope runs on: `boardName`, `board.{id,url,privacy,name}`, `boardInfo.{totalPins,boardFollowerCount,boardSectionCount,boardCollaboratorCount,boardIsCollaborative,boardCreatedAt,boardOwnerUsername}`, and — only when `includeBoardSections` is on — `sectionId` / `sectionTitle` / `sectionSlug`. `domain` segments pins by the merchant or site they link out to; `pinsDroppedByFilter` reports how many silent pins `commentedPinsOnly` has skipped on the current target so far.

### 🆚 How does Pinterest Boards Scraper (Pin Comments & Replies) differ from the official Pinterest API?

Pinterest's own API (v5) is built to manage the pins and boards **your own authenticated app account owns** — creating, listing and updating them — plus ads, catalog and analytics endpoints; it requires an approved developer app, an OAuth grant, and (per Pinterest's access-tier documentation) starts on a Trial tier limited to calls per day/app before a Standard tier unlocks per-minute/per-user limits (developers.pinterest.com, checked 2026-08-04). Its published endpoint list has no documented resource for reading another account's comment thread at all.

| Feature | Pinterest API v5 | This actor |
| --- | --- | --- |
| Read a board/profile you don't own | Not documented for arbitrary public accounts | ✅ works from any public URL or username |
| Comment thread on a pin | No comments-read endpoint in the published reference | ✅ verbatim text, reactions, reply counts |
| Access approval | Developer app review, OAuth, Trial → Standard tiers | ❌ none — paste URLs and run |
| Setup requirement | Register app, request scopes, get authorization | Apify Console or API call |
| Output shape | Raw per-endpoint API JSON | One normalized row per pin, export-ready |

#### ❓ Why doesn't the official Pinterest API return a stranger's comments?

Pinterest's v5 endpoints (`pins_get`, `pins_list`, `boards_list_pins`, and the rest) operate on content the authorizing account owns or manages — that's the whole point of OAuth scopes like `pins:read` and `boards:read`. There is no documented endpoint that lets an approved app pull the comment thread under someone else's public pin, because comments were never part of the content-management surface the API was built for. This actor covers that gap by reading the same public, logged-out `/resource/` endpoints the Pinterest website itself calls to render a pin page, gated on Pinterest's own aggregated comment counter rather than the unreliable per-pin one.

Use the official API when you're managing, publishing or reporting on pins and boards your own business account controls. Use this actor when you need to read what's already public on someone else's board, profile or pin — including what people said about it.

### 💡 How to use data extracted from Pinterest?

#### 📣 Social listening and community managers

Point the actor at your own brand's boards with `commentedPinsOnly: true` and a generous `maxPinsScannedPerUrl`, then read `comments[].text` on every pin that came back. It's the direct line to what customers actually say under a product pin — sizing complaints, "where can I buy this," damaged-in-shipping reports — that `savesCount` alone will never show you.

#### 🏢 Agencies and UGC partners

Run the same input across every client board on a schedule and compare `commentsCollected`, `commentCountReported` and `hasComments` side by side to benchmark which boards and pins are generating real engagement versus silent saves, then hand clients a discussion-density report instead of a vanity-metric screenshot.

#### 📊 Market and content research

Walk a category's high-traffic boards (recipe, DIY, product) with `fetchPinDetails` on to pull `date` and `shareCount` alongside the thread, and correlate comment density against `visualAnnotations` and `dominantColor` to see which visual styles and topics actually start a conversation, not just get saved.

#### 🤖 AI agents and automated pipelines

Feed `comments[].text` into a sentiment or intent classifier as part of a monitoring pipeline — the actor ships the raw verbatim text and structural fields (`replyCount`, `reactionCount`, `hasText`) and deliberately no computed judgement, so the agent's own model does the classifying on clean input.

### 🔼 Input sample

| Parameter | Required | Type | Description | Example value |
| --- | --- | --- | --- | --- |
| `urls` | Yes | array | Board URLs (`https://www.pinterest.com/<user>/<board>/`), profile URLs or bare usernames, and pin URLs or bare pin IDs. One per line. | `["https://www.pinterest.com/HGTV/hgtv-dream-home/"]` |
| `maxItems` | No | integer | Pin **rows** to return per target, 1–5000, default `10`. With `commentedPinsOnly` on, this counts pins you **keep**, not pins opened. | `25` |
| `includeComments` | No | boolean | Attach the comment thread as `comments[]`. Default `true`. Off returns plain pin rows with an empty array. | `true` |
| `maxCommentsPerPin` | No | integer | Comments per pin, 1–200, default `20`. Comments are read 50 per request; a longer thread is cut and flagged `commentsTruncated: true`. | `50` |
| `commentedPinsOnly` | No | boolean | Drop pins with an empty thread, default `true`. Ignored when `includeComments` is off. | `true` |
| `maxPinsScannedPerUrl` | No | integer | Ceiling on pins opened while hunting for commented ones, 0–20000, default `400`. `0` = no ceiling. | `500` |
| `fetchPinDetails` | No | boolean | Fills `date`, `commentCount`, `shareCount` and `pinner.followerCount`, default `false`. Reuses the same closeup request the comment engine already made. | `true` |
| `maxPinDetailFetches` | No | integer | Ceiling on the enrichment above, across the whole run, 0–5000, default `50`. `0` = no ceiling. | `25` |
| `includeBoardSections` | No | boolean | Stamps `sectionId` / `sectionTitle` / `sectionSlug` onto each pin, default `false`. | `false` |
| `fetchLinkDetails` | No | boolean | Fills `link` / `externalLink` / `domain`, default `true`. Off returns all three as `null`. | `true` |
| `proxyConfiguration` | No | object | Your own Apify proxy selection, honored exactly as configured. Default `{"useApifyProxy": false}`. | `{"useApifyProxy": false}` |

```json
{
  "urls": ["https://www.pinterest.com/HGTV/hgtv-dream-home/"],
  "maxItems": 25,
  "includeComments": true,
  "maxCommentsPerPin": 50,
  "commentedPinsOnly": true,
  "maxPinsScannedPerUrl": 500,
  "fetchPinDetails": true,
  "maxPinDetailFetches": 25,
  "includeBoardSections": false,
  "fetchLinkDetails": true,
  "proxyConfiguration": { "useApifyProxy": false }
}
```

**Common pitfall:** `maxItems` counts pins **kept**, not pins opened. With `commentedPinsOnly` on and a low `maxPinsScannedPerUrl`, a quiet board can exhaust its scan ceiling before it ever fills `maxItems` — the run log prints the real kept/dropped fraction, and if every opened pin comes back silent the run fails loudly instead of finishing on an empty dataset.

### 🔽 Output sample

One typed, normalized JSON row per pin, consistent across every target type (board, profile, pin). Export as JSON, CSV, Excel, HTML table, XML or RSS from the Apify Console or API — nested fields like `comments[]` flatten to indexed columns in CSV/Excel.

```json
{
  "type": "pin",
  "id": "1618549864585211",
  "index": 1,
  "pinUrl": "https://www.pinterest.com/pin/1618549864585211/",
  "sourceUrl": "https://www.pinterest.com/HGTV/hgtv-dream-home/",
  "title": "Walnut console table styling",
  "gridTitle": "Walnut console table",
  "description": "Rich walnut finish, brass hardware, entryway styling.",
  "altText": "A walnut console table in a bright entryway",
  "visualAnnotations": ["furniture", "console table", "walnut"],
  "imageUrl": "https://i.pinimg.com/736x/aa/bb/cc/table.jpg",
  "images": [
    { "url": "https://i.pinimg.com/736x/aa/bb/cc/table.jpg", "width": 736, "height": 1104, "quality": "736x", "extension": "jpg" }
  ],
  "dominantColor": "#a67b5b",
  "imageSignature": "abc123def456",
  "hasVideo": false,
  "videoDurationMs": null,
  "videos": null,
  "isIdeaPin": false,
  "isRepin": true,
  "repins": 4200,
  "savesCount": 4200,
  "repinCount": 12,
  "commentCount": 26,
  "shareCount": 3,
  "date": "2015-12-15T17:43:25Z",
  "externalLink": "https://www.walmart.com/ip/walnut-console-table/123456",
  "link": "https://www.walmart.com/ip/walnut-console-table/123456",
  "domain": "walmart.com",
  "boardName": "HGTV Dream Home",
  "sectionId": null,
  "sectionTitle": null,
  "sectionSlug": null,
  "board": {
    "id": "543216789012345",
    "url": "https://www.pinterest.com/HGTV/hgtv-dream-home/",
    "privacy": "public",
    "name": "HGTV Dream Home"
  },
  "boardInfo": {
    "boardName": "HGTV Dream Home",
    "boardDescription": "Every room from this year's Dream Home.",
    "boardUrl": "https://www.pinterest.com/HGTV/hgtv-dream-home/",
    "totalPins": 187,
    "boardId": "543216789012345",
    "boardPrivacy": "public",
    "boardFollowerCount": 812000,
    "boardSectionCount": 6,
    "boardCollaboratorCount": 0,
    "boardIsCollaborative": false,
    "boardCreatedAt": "2015-01-05T00:00:00Z",
    "boardOwnerUsername": "HGTV"
  },
  "user": "HGTV",
  "pinner": {
    "id": "223344556677",
    "fullName": "HGTV",
    "username": "HGTV",
    "imageUrl": "https://i.pinimg.com/280x280_RS/pinner.jpg",
    "isVerifiedMerchant": false,
    "followerCount": 812000
  },
  "nativeCreator": null,
  "scrapedAt": "2026-08-04T10:15:00Z",
  "hasComments": true,
  "commentsCollected": 2,
  "commentCountReported": 26,
  "commentsTruncated": false,
  "pinsDroppedByFilter": 4,
  "comments": [
    {
      "id": "998877665544",
      "type": "aggregatedcomment",
      "text": "Does this come in walnut? Mine arrived broken :(",
      "hasText": true,
      "createdAt": "2024-03-02T09:14:00Z",
      "user": {
        "id": "334455667788",
        "username": "jane_doe",
        "fullName": "Jane Doe",
        "imageUrl": "https://i.pinimg.com/280x280_RS/jane.jpg",
        "isPrivateProfile": false
      },
      "replyCount": 2,
      "reactionCount": 5,
      "helpfulCount": 0,
      "isEdited": false,
      "mediaUrls": []
    },
    {
      "id": "998877665599",
      "type": "userdiditdata",
      "text": "Made this look happen in my own entryway, love it!",
      "hasText": true,
      "createdAt": "2024-04-11T15:02:00Z",
      "user": {
        "id": "990011223344",
        "username": "home_by_amy",
        "fullName": "Amy R.",
        "imageUrl": "https://i.pinimg.com/280x280_RS/amy.jpg",
        "isPrivateProfile": false
      },
      "replyCount": 0,
      "reactionCount": 14,
      "helpfulCount": 3,
      "isEdited": null,
      "mediaUrls": ["https://i.pinimg.com/736x/dd/ee/ff/entryway.jpg"]
    }
  ]
}
```

A failed target leaves an **uncharged** accounting row instead of vanishing silently: `{"type": "error", "id": null, "sourceUrl": "...", "errorReason": "target_not_found", "errorMessage": "...", "scrapedAt": "..."}`. Filter these out with `type !== "error"` before counting or billing against results.

### 🎯 How do you filter and target specific pins?

Precision here comes from **which pins get opened, which survive, and how deep each thread goes** — there's no keyword search, so targeting starts at the URL level:

1. **Target scope** — a board URL scrapes one board; a profile URL or bare username walks every board that profile publishes, newest-pinned first; a pin URL or bare numeric ID scrapes exactly one pin regardless of `commentedPinsOnly`.
2. **Quality threshold** — `commentedPinsOnly` (default `true`) keeps only pins with a retrievable thread. Discussion density is a board property and it's low: measured live, `/HGTV/hgtv-dream-home/` kept 10 of 26 pins opened, `/officialflawliz/cherry-cola-lips/` kept 0 of 25, and a deep walk of `/marthastewart/easy-dinner-recipes/` kept 5 of 400.
3. **Volume controls** — `maxItems` caps rows **kept**; `maxPinsScannedPerUrl` caps pins **opened** while hunting for them (0 = no ceiling); `maxCommentsPerPin` caps comments per thread (1–200, cut threads are flagged `commentsTruncated`). These three interact: a tight scan ceiling on a quiet board can end the run before `maxItems` fills.
4. **Enrichment scope** — `fetchPinDetails` + `maxPinDetailFetches` decide how many pins additionally get `date`/`shareCount`/`pinner.followerCount`; `includeBoardSections` decides whether pins get tagged with their board section.

```json
{ "urls": ["https://www.pinterest.com/HGTV/hgtv-dream-home/"], "maxItems": 20, "commentedPinsOnly": true, "maxPinsScannedPerUrl": 2000 }
```

```json
{ "urls": ["https://www.pinterest.com/HGTV/"], "maxItems": 500, "includeComments": false }
```

```json
{ "urls": ["1618549864585211"], "includeComments": true, "maxCommentsPerPin": 200, "fetchPinDetails": true }
```

The first digs deep into one board for real discussion; the second walks an entire profile fast with comments off for pure metadata; the third pulls one pin's complete thread and full detail.

### ▶️ Want to try other Pinterest scrapers?

**Other Pinterest scrapers**

| Scraper | What it extracts |
| --- | --- |
| Pinterest Profile Scraper With Email & Website Contacts | Public Pinterest profile bios followed to email, phone and social handles on the linked website |
| Pinterest Ads Scraper — Performance Analytics | Pinterest Ads Library ads with flattened targeting and derived reach/engagement metrics |

**Comment and review scrapers on other platforms**

| Scraper | What it extracts |
| --- | --- |
| TikTok Shop Data Scraper: Reviews & Sentiment Analysis | TikTok Shop product reviews with sentiment scoring |
| Tripadvisor Review Scraper: Photo & Visual Content Filters | Tripadvisor reviews filtered by photo and visual content |

### ⚙️ How to extract Pinterest data programmatically

The actor runs as a standard Apify Actor: one API call starts it, one dataset endpoint returns structured JSON back — no separate signup, no Pinterest credentials.

#### Python example

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")

run = client.actor("<your-handle>/pinterest-boards-scraper-pin-comments-and-replies").call(
    run_input={
        "urls": ["https://www.pinterest.com/HGTV/hgtv-dream-home/"],
        "commentedPinsOnly": True,
        "maxCommentsPerPin": 50,
    }
)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item.get("type") == "error":
        continue
    print(item["title"], item["commentsCollected"])
    for comment in item.get("comments", []):
        print(" -", comment["text"])
```

#### Export to spreadsheets or CRM

Export the dataset as CSV or Excel from the Console (or `dataset().download_items(item_format="csv")`) and map `title` to a content/product column, `boardName` to a category or campaign column, `commentsCollected` / `commentCountReported` to an engagement column, and each `comments[].text` row to a feedback field for a spreadsheet pivot or CRM import.

### ⚖️ Is it legal to scrape Pinterest?

Yes. Every board, profile, pin and comment this actor reads is already public on pinterest.com — nothing requires a login, a password, or bypassing an access control, and the actor never authenticates as a Pinterest user. Pin metadata (title, image, save counts) is Pinterest's own public content. The comment thread is different: `user.username`, `user.fullName`, the avatar and the comment text are personal data about identifiable people, so GDPR, CCPA and equivalent regimes govern how you store, process and republish it once collected — not whether you may read it. Pinterest's own Terms of Service also govern automated access at scale; review them before a large or recurring run. Consult legal counsel for commercial applications involving bulk storage of personal data, particularly before republishing a comment that names or criticizes someone.

### ❓ Frequently asked questions

#### What happens if a pin is deleted or a board goes private after I've scraped it?

Nothing retroactive — the row you already collected stays in your dataset unchanged. If a target has vanished *before* the run reaches it, the actor logs an uncharged `type: "error"` row (`errorReason: "target_not_found"`) instead of silently skipping it, so a disappeared board or pin is always visible in the output.

#### Can I get comments along with saves, board and pinner info in the same run?

Yes — one row per pin carries both. Turn `includeComments` off and you get plain pin rows (save counts, board, pinner, link) with an empty `comments` array instead; there's no separate run needed for either.

#### How accurate is the comment count data?

`commentCountReported` reflects Pinterest's own **aggregated** comment counter, which this actor uses deliberately instead of the per-pin `comment_count` field: the two disagreed on 44 of 60 sampled pins on one board, with `comment_count` claiming 1–15 comments on 19 pins whose aggregated count — and retrievable comments — was actually zero. Thread recovery against Pinterest's declared total is lossy in the other direction too, since deleted and hidden comments stay in Pinterest's count; that's why `commentCountReported` and `commentsCollected` are shipped side by side rather than presented as one "completeness" number.

#### How many pins and comments can I get per run?

`maxItems` caps rows kept per target at 1–5000 (default 10). `maxCommentsPerPin` caps comments per thread at 1–200 (default 20); a longer thread is cut and flagged `commentsTruncated: true`, with `commentCountReported` still showing Pinterest's true total. `maxPinsScannedPerUrl` caps how many pins get opened while hunting for commented ones (0–20000, default 400, 0 = no ceiling) — this is what actually protects you from a silent multi-thousand-pin board.

#### How do I get only the pins people actually discussed?

Turn on `commentedPinsOnly` (the default). It drops any pin whose thread came back empty so the export reads like a discussion log rather than a board grid. Density varies hard by board — 10 of 26 pins kept on one board, 0 of 25 on another, 5 of 400 on a deep walk of a third — so pair it with a generous `maxPinsScannedPerUrl` on boards you expect to be mostly quiet.

#### ⚠️ Can I get the replies under each comment?

No. Reply bodies are not served to logged-out clients: seven dedicated Pinterest reply resources answer HTTP 404, and the comments endpoint silently re-serves the identical top-level page when asked for a reply thread — a toggle that changes nothing. This actor ships `replyCount` (each comment's own reply count) instead of a fake `includeReplies` option, because a toggle with no effect is worse than an absent feature.

#### Does this scraper work with Claude, ChatGPT and other AI agent frameworks?

Yes, as a standard HTTP-callable Apify Actor — any agent framework that can make an authenticated REST call (via `apify-client` or a raw API request) can start a run and read the dataset back as JSON, including piping `comments[].text` straight into a sentiment or classification tool.

#### What makes this different from a plain Pinterest scraper?

It treats the comment thread as the actual product instead of an afterthought: it reads text from the correct key depending on comment type (`aggregatedcomment` vs `userdiditdata`, which store text in different fields), gates on Pinterest's aggregated comment counter instead of the unreliable per-pin one, and reports a missing count as `null` rather than a false `0`. It also declines to ship a `comments[].replies` field that would silently return duplicate data, and doesn't attach a sentiment score or spam filter to comment text — spam is real Pinterest content and is returned unfiltered.

#### Can I use this without a Pinterest account or API key?

Yes. Every request runs logged out and keyless — no Pinterest login, password, cookie or developer app is needed. You only need an Apify account to run the actor; a proxy is optional and off by default, since Pinterest's public endpoints answered every request in testing without one.

### Conclusion

Pinterest Comments Scraper turns a board, profile or pin into structured JSON: the full pin record — image, saves, board, pinner, outbound link — plus the comment thread attached correctly across both of Pinterest's comment shapes, gated on the one counter Pinterest itself doesn't fake. It's built for social listening teams, UGC researchers, agencies and AI pipelines that need what people actually said under a pin, not just how many times it was saved. Reply bodies stay out because Pinterest doesn't serve them logged out — everything else ships as measured, with real nulls instead of false zeros. Start a run from the Apify Console or API with a single board URL to see the thread on your own content.

# Actor input Schema

## `urls` (type: `array`):

Board URLs (https://www.pinterest.com/<user>/<board>/), profile URLs or bare usernames, and pin URLs or bare pin IDs. One per line. Comment density varies enormously by board — a recipe or product board carries discussion, a mood board usually does not.

## `maxItems` (type: `integer`):

How many pin ROWS to return per target (1–5000). With '🗣️ Only pins with comments' on, this counts the pins you KEEP, not the pins opened — so a cap of 20 returns 20 commented pins, however many silent ones had to be opened to find them.

## `includeComments` (type: `boolean`):

Attach the comment thread to each pin row as a nested `comments` array — verbatim text, commenter identity, date, reactions, attached photos, and each comment's own reply count. Turn it off and the actor returns plain pin rows with an empty `comments` array.

## `maxCommentsPerPin` (type: `integer`):

Comments are read 50 per request. Threads longer than this are cut and the row is flagged `commentsTruncated: true`; `commentCountReported` still shows Pinterest's own total for the thread, so a cut is always visible.

## `commentedPinsOnly` (type: `boolean`):

Drop pins whose thread came back empty, so the export is a reading list rather than a grid. Density is a board property and it is low: measured live, /HGTV/hgtv-dream-home/ kept 10 of 26 pins opened, /officialflawliz/cherry-cola-lips/ kept 0 of 25, and a deep walk of /marthastewart/easy-dinner-recipes/ kept 5 of 400. Ignored when the comment fetch above is off.

## `maxPinsScannedPerUrl` (type: `integer`):

Ceiling on how many pins are opened while hunting for commented ones. It stops a silent 8,000-pin board from being read end to end. 0 = no ceiling. The log warns when the ceiling, rather than the board, ended the run.

## `fetchPinDetails` (type: `boolean`):

Fills `date` (ISO 8601), `commentCount`, `shareCount` and `pinner.followerCount` on the pin row. These four are null without it. It reuses the SAME closeup request the comment engine already made, so with comments on it is effectively free.

## `maxPinDetailFetches` (type: `integer`):

Ceiling on the enrichment above, across the whole run. Pins past the ceiling are still returned, with those four fields null. 0 = no ceiling.

## `includeBoardSections` (type: `boolean`):

Walks the board's sections and stamps `sectionId` / `sectionTitle` / `sectionSlug` onto each pin. Pins that sit outside every section keep a null section — on a 1,200-pin board about 52 genuinely do.

## `fetchLinkDetails` (type: `boolean`):

Fills `link` / `externalLink` / `domain` with the destination each pin points at. Turn it off to return all three as null.

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

Your own proxy selection is honored exactly as configured — groups, country and custom proxy URLs all reach the fetch layer.

## Actor input object example

```json
{
  "urls": [
    "https://www.pinterest.com/HGTV/hgtv-dream-home/"
  ],
  "maxItems": 10,
  "includeComments": true,
  "maxCommentsPerPin": 20,
  "commentedPinsOnly": true,
  "maxPinsScannedPerUrl": 60,
  "fetchPinDetails": false,
  "maxPinDetailFetches": 50,
  "includeBoardSections": false,
  "fetchLinkDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All scraped items in the Actor's default dataset.

## `threads` (type: `string`):

Same dataset, narrowed to each pin's comment thread.

## `enrichment` (type: `string`):

Same dataset, narrowed to pin detail and board-section fields.

# 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 = {
    "urls": [
        "https://www.pinterest.com/HGTV/hgtv-dream-home/"
    ],
    "maxItems": 10,
    "maxCommentsPerPin": 20,
    "maxPinsScannedPerUrl": 60,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("simpleapi/pinterest-boards-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 = {
    "urls": ["https://www.pinterest.com/HGTV/hgtv-dream-home/"],
    "maxItems": 10,
    "maxCommentsPerPin": 20,
    "maxPinsScannedPerUrl": 60,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("simpleapi/pinterest-boards-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 '{
  "urls": [
    "https://www.pinterest.com/HGTV/hgtv-dream-home/"
  ],
  "maxItems": 10,
  "maxCommentsPerPin": 20,
  "maxPinsScannedPerUrl": 60,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call simpleapi/pinterest-boards-scraper --silent --output-dataset

```

## MCP server setup

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