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

13

Total users

6

Monthly active users

7 days ago

Last modified

Security

Limited permissions

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.5 from source 55680eb4 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.5. 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": 5
}

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.

The post-promotion default-latest smoke, run QPzEH87UjCVdhjDJM, used build 0.2.5 with 256 MB and omitted proxy from the submitted input. It completed 1/1 row; the stored INPUT contains the default US residential RESIDENTIAL settings, and its residential transfer counter was positive. See the ../../validation/pinterest-text-modes-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, even when the successful sources return no rows. If every source fails and no usable rows were collected, the run fails. If rows from earlier pages or sources remain, the run stays partial and delivers them. An explicit completed summary with zero failures may return zero delivered rows and complete without a charge when its requested count matches the normalized target count; this count is the product's target count, not its returned row count. Missing or inconsistent summaries remain failed. A partial source failure remains partial, including when no rows were returned.

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

Current 0.2.5 four-mode acceptance

On 2026-10-20, eight successful hosted runs compared this Actor's build 0.2.5 (JYgg9RL1uCt7l8unI) with Automation Lab build 0.1.39 (qK0Bfz3UwIYSnhhGA). Each mode had one run per Actor:

  • fixed: 10 Pins
  • search: 3 queries with 5 rows each
  • board: 3 boards with 5 rows each
  • profile: 3 profiles with 5 rows each

Both sides returned 55 records in total, all 55 exact string IDs joined, and all eight runs succeeded. The paired cases used the same stored inputs, 512 MB, and explicit proxy: false.

All four modes passed the flat-row contract: 1,230/1,230 contract cells were valid, with zero invalid cells, unknown fields, or missing fields. Board order differed; the other three orders matched. Full value equality did not pass in any mode. A compatible contract therefore does not imply equal values or equal feed ordering.

ModeTotal rowsTitle ours/referenceDescription ours/reference
Fixed1010/910/9
Search1514/1414/14
Board1510/1012/12
Profile1515/1015/10

Pinner, board, and createdAt were non-empty on 10/10 fixed rows here versus 3/10 in the reference. The reference matched the collection on those counts in the other modes. This is availability evidence, not proof that every non-empty value is semantically better.

All four 0.2.5 runs had OUTPUT.status: completed and failed: 0. The optional text stage attempted and filled descriptions on 5 profile rows, failed on none, and added no delivery charge. Search and board skipped 2 and 5 opaque IDs respectively.

The current evidence artifacts are:

  • ../../validation/pinterest-text-modes-2026-10-20/inputs.json
  • ../../validation/pinterest-text-modes-2026-10-20/run-summary.json
  • ../../validation/pinterest-text-modes-2026-10-20/comparison-report.json
  • ../../validation/pinterest-text-modes-2026-10-20/web-report.json
  • ../../validation/pinterest-text-modes-2026-10-20/incident.json
  • ../../validation/pinterest-text-modes-2026-10-20/agent-routing.json

Anonymous public HTML independently matched title, description, and original-image URL on 25/25 numeric close-up Pins from the fixed and profile results. The nine source pages returned HTTP 200, but anonymous search HTML exposed no result Pin entities, and board pages supplied less per-row text. This does not verify all 55 rows from the web or constitute a complete authenticated rendered-DOM check.

Version 0.2.4 is not the live build. Its four verification runs failed after writing valid Datasets because OUTPUT.textEnrichment was missing from the strict published key-value schema. It was rolled back to 0.2.3. The incident audit inspected 82 run metadata records to cover the window; only four runs fell inside it, all of them this task's validation runs. There were no other-user runs or failures in that window. After PR #687 added an Ajv test for the actual schema, 0.2.5 passed the four-mode canary and was promoted. The complete release record is ../../validation/pinterest-text-modes-2026-10-20/README.md.

Historical 0.2.1 comparison

The measurements in the remainder of this section are the older 0.2.1 fixed-ten-Pin record. They are retained as dated history and are not the current 0.2.5 result.

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.

That historical source audit did not fetch the pages during its 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-text-modes-2026-10-20/README.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.