Pinterest Scraper — Pins, Boards & Profiles avatar

Pinterest Scraper — Pins, Boards & Profiles

Pricing

from $0.85 / 1,000 result delivereds

Go to Apify Store
Pinterest Scraper — Pins, Boards & Profiles

Pinterest Scraper — Pins, Boards & Profiles

Search Pinterest or collect pins from public boards, profiles and pin URLs. Returns the flat Automation Lab-compatible pin shape with images, saves, hashtags, creator and board details. $1 per 1,000 delivered results. No login or API key.

Pricing

from $0.85 / 1,000 result delivereds

Rating

0.0

(0)

Developer

Meka.im

Meka.im

Maintained by Community

Actor stats

0

Bookmarked

10

Total users

6

Monthly active users

12 hours ago

Last modified

Share

Pinterest Scraper

Collect pins by Pinterest search query, public board, public profile, or individual pin URL. The v0.2 output is the flat Automation Lab-compatible pin shape: image URLs, the observed saves compatibility value, hashtags, creator and board details, and source provenance.

The Actor reads Pinterest's public web resources through HTTP. It does not need a Pinterest login, cookies, an API key, or a browser.

Version and compatibility

  • v0.1 remains the legacy source version. The complete old entrypoint is preserved as src/main-v1.mjs, and its nested v1 row shape remains in src/contract.mjs and src/product.mjs. Existing users of the legacy input and nested Dataset must pin the retained v0.1 build 0.1.11.
  • v0.2 is the current live default and a breaking input/output contract. Build 0.2.1 from src/main.mjs runs the flat Automation Lab contract in src/automation-runner.mjs.
  • Publishing v0.2 does not delete older Actor source versions. However, preserving v0.1 source does not keep unpinned latest consumers on the old contract: latest now points to v0.2.1. Calls that need the nested v1 Dataset must pin build 0.1.11.

Compatibility covers input names and the flat row fields. It does not promise that a separate live run returns the same pins, numeric values, or timestamp text as another Actor. Pinterest rotates search results and may expose different counters by request path and time.

Quick start

Search for pins:

{
"searchQueries": ["minimalist kitchen design"],
"maxPins": 25
}

Collect a profile, a board, and specific pins together:

{
"boardUrls": ["https://www.pinterest.com/username/board-name/"],
"profileUrls": ["https://www.pinterest.com/username/"],
"pinUrls": ["https://www.pinterest.com/pin/123456789/"],
"maxPins": 50
}

Start with a small maxPins value, inspect the dataset, and increase it after checking relevance and cost.

Input

The v0.2 input has six fields:

FieldTypeDefaultMeaning
searchQueriesstring[][]Pinterest search terms. Each query can return up to maxPins pins.
boardUrlsstring[][]Public Pinterest board URLs, including the owner username in the path.
profileUrlsstring[][]Public Pinterest profile URLs. Profile pins also receive profile metadata.
pinUrlsstring[][]Individual public Pinterest pin URLs.
maxPinsinteger50Maximum pins from each query, board, or profile. Range: 1 to 1,000; the editor prefill is 5.
proxyobjectUS residential Apify proxyProxy settings; see below.

At least one source is required. Sources retain input order: searches, then boards, profiles, and pin URLs. Duplicate canonical sources are processed once. Empty strings and malformed Pinterest URLs fail validation before any proxy or Pinterest request is made.

Proxy behavior

The default is the same effective route as the Automation Lab input:

{
"useApifyProxy": true,
"groups": ["RESIDENTIAL"],
"countryCode": "US"
}

groups becomes the Apify proxy group list and countryCode is passed to the Apify proxy. The Actor asks the proxy configuration for a new URL for every HTTP attempt. If a proxy configuration is present but cannot produce a URL, the run fails instead of silently connecting directly.

Use "proxy": { "useApifyProxy": false } to connect directly when no custom proxy URLs are supplied. Custom proxyUrls can be supplied instead. They are used through undici.ProxyAgent, and each request receives a fresh URL from the configuration.

A hosted 256 MB smoke run whose submitted input omitted the proxy field completed 1/1 row; its stored INPUT contains the default US residential RESIDENTIAL settings, and its residential transfer byte counter was positive. See the ../../validation/pinterest-online-release-2026-10-20/README.md.

The transport accepts only these Pinterest resource names:

  • BaseSearchResource
  • PinResource
  • UserResource
  • UserPinsResource
  • UserActivityPinsResource
  • BoardResource
  • BoardFeedResource

Each resource has a fixed Pinterest handler. Request origins, paths, headers, and redirects are managed by the Actor. Product code cannot turn an input URL into an arbitrary request destination.

Profile collection uses UserPinsResource with field_set_key: detailed, so public saved pins are included even when a profile has no pins it created, and same-response SEO text can fill a missing title without an additional PinResource request. If that resource fails, the source fails without a silent fallback to the creation-only activity feed. Board collection continues to request field_set_key: grid_item, because the observed detailed board feed does not provide usable pin IDs. createdAt is filled only from the returned pin's raw.created_at.

Output

Every Dataset row is a Pinterest pin. The base fields are:

id, title, description, url, imageUrl, thumbnailUrl, altText, domain, link, saves, pinnerUsername, pinnerName, pinnerFollowers, boardName, boardUrl, dominantColor, createdAt, isVideo, hashtags, sourceTypes.

Additional provenance fields appear when their source matched:

  • sourceUrls for board, profile, and pin URL sources.
  • sourceQueries for search sources.
  • profileUrl, profileUsername, profileName, profileFollowers, and profilePinCount for a profile source.

Example:

{
"id": "1020839440598637528",
"title": "Small Japandi Kitchen Ideas",
"description": "Warm wood, calm colors, and a compact layout.",
"url": "https://www.pinterest.com/pin/1020839440598637528/",
"imageUrl": "https://i.pinimg.com/originals/5d/67/cc/example.png",
"thumbnailUrl": "https://i.pinimg.com/236x/5d/67/cc/example.jpg",
"altText": "A small kitchen with wooden cabinets",
"domain": "Uploaded by user",
"link": null,
"saves": 2,
"pinnerUsername": "example",
"pinnerName": "Example",
"pinnerFollowers": 336,
"boardName": "Kitchen Ideas",
"boardUrl": "https://www.pinterest.com/example/kitchen-ideas/",
"dominantColor": "#ae957e",
"createdAt": "Wed, 04 Mar 2026 22:41:54 +0000",
"isVideo": false,
"hashtags": ["#kitchenideas"],
"sourceTypes": ["search"],
"sourceQueries": ["small kitchen"]
}

The row has no nested pin, creator, media, or schema object, and no entity_type field. isVideo reports whether Pinterest marks the pin as video. No video file URL is claimed in this contract.

saves is an observed Automation Lab compatibility field sourced from reaction_counts['1']. A missing value becomes the integer 0 placeholder. It is not a verified total saves or repins count, and the product does not use repin_count or aggregatedStats.saves for this field.

Title and description fallbacks

For each pin, title uses the first non-empty trimmed string from raw.title, raw.grid_title, raw.rich_metadata.title, then raw.seo_title. description uses the first non-empty trimmed string from raw.description, raw.rich_metadata.description, then raw.seo_description. raw.rich_metadata is accepted only from the same raw Pin object and only when it is a non-array object. Hashtags are extracted from the resolved description.

seo_title and seo_description are Pinterest website-generated SEO text. Their use does not claim that they are the author's original title or description. Image alt text, HTML metadata tied to another pin, and synthesized text are not used. Search, board, and profile feeds can omit PinResource-level text, and the Actor does not add per-pin network requests for opaque e1_... feed IDs. When every supported same-pin value is absent or invalid, title and description remain empty; non-empty text is not guaranteed for every row.

After source collection, de-duplication, and maxResults selection, the product can issue one PinResource lookup for a selected feed row when its numeric ID is missing a title or description and an explicit pinUrls source has not already fetched that same Pin. The response ID must match the request. The lookup fills only empty text fields, preserves existing text and all other row fields, and recalculates hashtags only when the description is filled. Fully populated rows, unselected rows, opaque e1_... IDs, and explicit Pin sources are skipped. A later duplicate raw record may fill missing text before this stage, avoiding a lookup.

Lookups run with at most three concurrent requests. Starting 30 seconds after this stage begins, no further lookups are started; requests already in flight still follow the transport's existing retry and 30-second timeout behavior, so total run duration can exceed 30 seconds. Optional lookup failures, mismatched IDs, malformed details, and candidates skipped at the launch deadline do not change Dataset rows, source failure status, or delivery billing.

The fallback is a backward-compatible 0.2.x bugfix. It does not change the six-field input, the flat row fields, or the version in .actor/actor.json.

Board output URLs accept underscore-prefixed slugs, percent-encoded +, and Unicode slugs while still requiring a Pinterest host, no credentials or custom port, exactly two decoded path segments, and a safe username. Decoded slash, backslash, control characters, and ./.. traversal are rejected, as are malformed encodings and foreign hosts. The slug is safely encoded when rebuilding the output URL. This affects output normalization only and does not widen input URL validation.

Missing text is returned as an empty string when Pinterest does not expose it, unless the field is documented as nullable. Numeric counters preserve Pinterest's reported value, including zero. createdAt preserves the timestamp text returned by Pinterest.

Pagination, deduplication, and recovery

The product follows Pinterest bookmarks until each source reaches its per-source maxPins limit, the source ends, or the overall delivery budget is reached. It completes source collection before writing rows so a pin found by several inputs is delivered once with merged sourceTypes and source provenance.

Dataset rows are the identity ledger. On a resumed run, the Actor reads every Dataset page and skips IDs already present. The STATE record also stores contract version and a hash of the input so a dataset cannot be silently reused with different input.

Rows are written before the delivery event is charged. A resumed run does not bill an existing row again. If the remaining charge budget is zero, no proxy or Pinterest request is made.

If finite budget collection skips pins because maxResults was reached, the run is marked budget-exhausted so a later run with more budget can continue. A complete result that merely equals the available budget, without a skipped pin, remains completed.

Run summary

OUTPUT records:

  • contractVersion: 2
  • status: completed, partial, budget-exhausted, or failed
  • requested, delivered, deliveredThisAttempt, and failed
  • textEnrichment when the product reports it, containing only the non-negative safe integer counters attempted, filledTitles, filledDescriptions, failed, skippedOpaque, and skippedBudget
  • budget and recovery flags where relevant

A source failure with other successful sources produces partial. If every source fails, the run fails. A successful-looking empty result is also treated as a failure.

Pricing

Pricing remains $0.001 per delivered row, or $1.00 per 1,000 rows. Duplicate rows, failed lookups, and resumed rows already in the Dataset do not emit another result-delivered event.

API example

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });
const run = await client.actor('meka.im/pinterest-scraper').call({
searchQueries: ['minimalist kitchen design'],
maxPins: 50,
proxy: {
useApifyProxy: true,
groups: ['RESIDENTIAL'],
countryCode: 'US',
},
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Validation status

On 2026-10-20, hosted runs of this Actor on build 0.2.1 and competitor build 0.1.39 received the same fixed ten Pin URLs, maxPins: 10, and proxy: false. Both returned the same 10 IDs in the same order. The input/output contract passed: 210/210 field checks were valid, field order matched 10/10 rows, and there were no unknown or missing fields. Observed types matched in 207/210 cells; the three differences were legal link string/null values.

Full value identity did not pass. Only 77/210 values were strictly equal and 133 differed, so the evidence records compatibilityPass: true, valuesEqual: false, and overall pass: false. After trimming, this Actor had non-empty titles on 8/10 rows and descriptions on 7/10; the reference had 9/10 and 9/10. This Actor had pinner, board, and createdAt data on 10/10 rows, the reference on 1/10, and this Actor marked 2/10 pins as video versus 0/10. More non-empty values do not by themselves prove better semantic accuracy.

The earlier source audit did not fetch the pages during this online comparison. Its per-row evidence remains the old anonymous public HTML embedded Relay JSON captured at 2026-10-20 08:50 UTC, and is partial. This release evidence covers only the fixed ten-Pin sample; earlier search, board, and profile smoke checks are not a complete production acceptance.

The usageTotalUsd values are platform infrastructure records. The owner's Actor usage is not a customer price and is not directly comparable with the reference run's $0.04. The recorded 5,222 ms and 10,223 ms spans are one-shot observations, not an SLA.

The transport tests cover asynchronous proxy URLs, proxy configuration failures, retries, response validation, body cleanup, and response-schema checks. Runner tests cover billing order, partial source failure, dataset pagination, completed-state recovery, budget exhaustion, and resume deduplication. See docs/pinterest-automation-compat.md, the ../../validation/pinterest-online-release-2026-10-20/README.md, and the ../../validation/pinterest-automation-compat-2026-10-20/README.md.

This Actor is an independent tool. It is not affiliated with, endorsed by, sponsored by, or certified by Pinterest, Inc. "Pinterest" and related marks belong to their respective owners and are used only to identify the public source this Actor reads. You are responsible for using the data in compliance with applicable law and the source website's terms.