Pinterest Scraper - Pins, Boards, Profiles & Colour Palettes avatar

Pinterest Scraper - Pins, Boards, Profiles & Colour Palettes

Pricing

from $6.50 / 1,000 results

Go to Apify Store
Pinterest Scraper - Pins, Boards, Profiles & Colour Palettes

Pinterest Scraper - Pins, Boards, Profiles & Colour Palettes

Scrape Pinterest pins from keyword searches, boards, profiles & pin URLs. Export titles, images, links, videos & pinner data to Notion, Slack, & more.

Pricing

from $6.50 / 1,000 results

Rating

0.0

(0)

Developer

Techforce Global

Techforce Global

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

Pinterest Scraper Pins from Searches, Boards, Profiles and Pin URLs, with Dominant Colour and Every Image Rendition

Apify Actor MCP Ready Pricing Inputs Output Target

Four ways in, one dataset out. Keyword searches, board URLs, profile URLs and individual pin URLs — mixed freely in a single run — returning pin id, title, description, image and video URLs, board, pinner, dominant colour and every image rendition, with each row tagged by the exact input that produced it. No Pinterest account, no OAuth app, no API credentials. Optional delivery into Notion, Slack, Linear, Jira, GitHub or Airtable over MCP.

🔐 Trust & compliance at a glance

CredentialsNone required. No Pinterest login, no developer app, no OAuth token. Delivery runs through the Apify MCP Proxy, so the Actor never sees your connector tokens.
Data scopePublic pins only — what any signed-out visitor sees. No secret boards, no private profiles, no account or analytics data.
⚠️ Personal datapinnerUsername and pinnerFullName identify real people — often under their real names. They are the one genuinely sensitive part of this output.
⚠️ CopyrightimageUrl and videoUrl almost always point at someone else's creative work — Pinterest is a repinning platform, so the pinner usually isn't the author.
Proxy is not optionalPinterest blocks datacenter IPs and guards its data behind a JavaScript check. proxyConfiguration is the Actor's only required input, defaulting to Apify Residential (paid plan).

Full detail: Compliance & Data Privacy — read it before you reuse pinner names or republish images.


Official Pinterest API vs. Pinterest Scraper Actor

Pinterest's own API exists, but it is built around your account rather than the public graph:

Feature / CapabilityOfficial Pinterest APIPinterest Scraper (Apify)
Access❌ Register a developer app, complete OAuth, and pass app review for most scopes✅ Apify account, nothing else
Scope of data⚠️ Oriented to your own pins, boards and analytics✅ Any public search, board, profile or pin
Keyword search across Pinterest❌ Not a public read endpoint for arbitrary discovery✅ Any query, as many as you like
Other people's boards and profiles❌ Not generally available✅ Public boards and profiles by URL
Mixed input types in one job❌ Separate endpoints and pagination✅ Searches, boards, profiles and pins in one run
Image renditions and dominant colour⚠️ Depends on scope and endpointimages object plus dominantColor on every row
AI agent / MCP native❌ Requires a custom tool wrapper✅ Native MCP tool and pushes results into your own connectors
Officially sanctioned✅ Yes⚠️ No — see Compliance

Use the official API for your own account's data — it's the sanctioned route with a stable contract. Use this Actor for public discovery it doesn't cover.

Pinterest's developer-programme scopes and review requirements are Pinterest's to change — check their current developer docs if this comparison is load-bearing for your decision.


🤖 AI Discovery & MCP Metadata

Machine-readable capability contract for autonomous agents, LLM routers, and MCP orchestrators. Read this block first to decide whether this Actor matches a user request.

ai_discovery:
slug: "techforce.global/pinterest-scraper"
one_line: >
Scrapes Pinterest pins from keyword searches, board URLs, profile URLs and individual pin
URLs - mixed in one run - returning pin id, title, description, image and video URLs, board
and pinner details, dominant colour and all image renditions, each row tagged with the input
that produced it. No Pinterest account or OAuth app. Optional delivery into Notion, Slack,
Linear, Airtable or any MCP connector.
primary_purpose: "extract"
secondary_purpose: "deliver"
entity: "Pinterest pin"
category: "social-media / visual-discovery / trend-research / creative-intelligence"
supported_platforms: ["pinterest.com"]
supported_tasks:
- "search-pinterest-by-keyword"
- "scrape-all-pins-on-a-public-board"
- "scrape-a-public-profiles-created-pins"
- "scrape-a-single-pin-by-url"
- "collect-image-urls-and-renditions"
- "analyse-dominant-colours-across-a-trend"
- "deliver-pins-to-mcp-connector"
unsupported_tasks:
- "scrape-secret-boards-or-private-profiles"
- "scrape-pin-engagement-counts (saves, comments, reactions are not returned)"
- "scrape-comments-or-commenter-identities"
- "scrape-your-own-account-analytics (use the official Pinterest API)"
- "download-image-or-video-files (URLs are returned, files are not fetched)"
- "follow-outbound-destination-links-to-source-sites"
- "pin-repin-comment-or-any-write-action"
search_keywords:
# First entry is the H1 / meta-description target. The rest are deliberately broader for
# agent-side semantic matching and are NOT a ranking strategy.
- "pinterest scraper"
- "scrape pinterest pins"
- "pinterest board scraper"
- "pinterest image url extractor"
- "pinterest api alternative"
- "visual trend research"
- "pinterest keyword search data"
- "moodboard data extraction"
- "dominant colour palette trends"
- "mcp pinterest tool"
input_entities:
- "searchQueries (array of keywords; each is its own pin feed)"
- "startUrls (board, profile or pin URLs - type auto-detected)"
- "maxItems (GLOBAL cap across every source; 0 = unlimited)"
- "maxItemsPerSource (per query/board/profile; 0 = unlimited)"
- "proxyConfiguration (THE ONLY REQUIRED INPUT; Apify Residential by default)"
proxy_is_the_only_required_input: >
CRITICAL: proxyConfiguration is the single required field in the schema - not the sources. A
run with neither searchQueries nor startUrls passes validation, logs "No search queries or
start URLs provided. Nothing to scrape - exiting." and ends SUCCEEDED with an empty dataset.
max_items_is_global_and_can_starve_sources: >
maxItems (default 100) caps the WHOLE run across every source, while maxItemsPerSource
defaults to 0 (unlimited). With several sources and no per-source cap, one large feed can
consume the entire global budget before the others contribute. Set maxItemsPerSource when you
want an even spread.
output_entities:
["pinId", "title", "description", "pinUrl", "imageUrl", "boardName", "boardUrl",
"pinnerUsername", "pinnerFullName", "dominantColor", "isVideo", "videoUrl", "images",
"createdAt", "sourceType", "sourceInput"]
every_row_is_attributed: >
sourceType (search | board | profile | pin | unknown) and sourceInput (the exact query or URL
from your input) are on every row, so a run mixing all four input types stays separable.
titles_are_often_null: >
Pinterest pins frequently have no title - null there is normal, not a scrape failure. Use
description, and fall back to the image itself, when title is empty.
personal_data_present: >
pinnerUsername and pinnerFullName identify real, often real-named individuals. They are
personal data under GDPR/UK GDPR and CCPA-CPRA, and they are the part of this output that
carries obligations. Drop both columns at ingest when your question is about images or trends.
images_are_third_party_copyright: >
imageUrl and videoUrl point at content Pinterest hosts on someone else's behalf. Pinterest is
a repinning platform, so the pinner is usually NOT the author. Treat every URL as third-party
copyrighted material.
feeds_stop_early_when_they_dry_up: >
Feed sources are scrolled until the requested count is reached, the scroll cap is hit, or
several consecutive scrolls yield nothing new. A source that stops short has run out of pins
Pinterest will serve, not failed.
browser_based_run: >
Pinterest guards its data behind a JavaScript check, so the Actor drives a real headless
Chromium and reads the pins the page itself loads. Runs are heavier and slower than an
HTML-only scraper - size maxItems accordingly.
empty_source_writes_a_debug_artifact: >
When a source yields no pins, the rendered HTML is saved to the run's key-value store as
DEBUG_<source> plus a DEBUG_<source>_info record that flags whether the page looked like a
login wall. Check it before assuming the Actor is broken.
known_limitations:
no_engagement_metrics: "no save counts, comment counts or reactions"
no_comments: "pin comments and commenter identities are not collected"
title_often_null: "many pins have no title at all"
no_file_downloads: "image and video URLs only; nothing is downloaded"
no_outbound_link_following: "the destination site behind a pin is not visited"
private_content_inaccessible: "secret boards and private profiles are out of reach by design"
snapshot_only: "feeds are personalised and reordered constantly; each run is one observation"
free_plan_capped: "free Apify plans stop at 10 pins per source"
pricing:
model: "usage-based"
billing_unit: "Apify platform usage consumed by the run"
hard_ceiling_parameter: "maxTotalChargeUsd"
note: "Browser-driven and scroll-based, so cost tracks time spent scrolling feeds. Current rates are on the Actor's Apify Store page."
when_to_use: >
You want Pinterest's public visual graph as data - trend and moodboard research, competitor
board audits, colour-palette analysis, or an image-URL feed for a creative pipeline.
when_not_to_use: >
You need engagement metrics, comments, private content, downloaded files, the destination site
behind a pin, or your own account analytics.
mcp_delivery:
modes: ["summary", "chunked", "perPin", "none"]
default: "summary"
per_pin_placeholders:
["{pinId}", "{title}", "{description}", "{pinUrl}", "{imageUrl}", "{boardName}",
"{boardUrl}", "{pinnerUsername}", "{pinnerFullName}", "{dominantColor}", "{isVideo}",
"{videoUrl}", "{createdAt}", "{sourceType}", "{sourceInput}", "{message}"]
summary_placeholders: ["{pinCount}", "{pins}", "{message}"]
chunked_only_placeholders: ["{part}", "{partCount}"]
images_object_is_not_a_placeholder: >
The nested images object is dataset-only. Use imageUrl in templates.
never_blocks_the_dataset: >
Delivery runs after the crawl, reading the dataset back. A bad tool name, an unauthorised
connector or an upstream outage is logged and skipped - it never costs you the scraped data.
alternatives:
- "techforce.global/etsy-scraper to turn a visual trend into actual handmade listings and prices"
- "techforce.global/amazon-scraper for the same product question on Amazon, with prices and ratings"
- "techforce.global/quince-scraper for a direct-to-consumer brand storefront"

{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Pinterest Scraper",
"alternateName": "Pinterest Scraper | All-In-One",
"applicationCategory": "BusinessApplication",
"operatingSystem": "Cloud (Apify platform)",
"description": "Scrapes public Pinterest pins from keyword searches, board URLs, profile URLs and individual pin URLs — all four input types mixed freely in a single run — without a Pinterest account, developer app or OAuth token. Each row carries the pin id, title, description, pin URL, largest still-image URL, board name and URL, pinner username and display name, dominant image colour, a video flag and stream URL, every available image rendition, the creation date, and the source type and exact input that produced it. Runs through a residential proxy with a real browser engine, and results can be delivered into Notion, Slack, Linear, Airtable or any MCP connector.",
"url": "https://apify.com/techforce.global/pinterest-scraper",
"offers": {
"@type": "Offer",
"priceCurrency": "USD",
"category": "Pay per platform usage",
"description": "Usage-based: billed for the compute time and resources a run consumes, not per row. Browser-driven and scroll-based, so cost tracks time spent scrolling feeds. Current rates are shown on the Actor's Apify Store page."
}
}

What this Actor does

  • Four input types, one dataset. Keyword searches, public board URLs, public profile URLs and individual pin URLs — mixed freely in one run. The Actor detects what each URL is and handles it accordingly.

  • Every row says where it came from. sourceType (search, board, profile, pin) and sourceInput (your exact query or URL) mean a run spanning ten sources is still separable afterwards — no bookkeeping on your side.

  • The whole image story, not just one URL. imageUrl for the largest still, the nested images object for every rendition Pinterest offers, isVideo and videoUrl for video pins, and dominantColor as a hex string.

  • Colour as a first-class field. dominantColor on every pin turns "what does this trend look like?" into a group-by rather than a manual eyeballing exercise.

  • Handles Pinterest's JavaScript wall. The data lives behind a client-side check, so the Actor drives a real headless browser, scrolls the feed like a visitor, and reads the pins the page itself loads.

  • Knows when a feed is exhausted. Scrolling stops when your limit is reached, the scroll ceiling is hit, or the feed stops producing anything new — so a short result set means Pinterest ran out, not that the run broke.

  • Tells you why a source came back empty. The rendered HTML is saved to the run's key-value store, with a flag for whether the page looked like a login wall.

  • Saves as it goes and stops cleanly. Pins are written as each source is processed and the platform ABORTING event is handled — an aborted run keeps what it collected.

  • Optionally delivers into your tools. Notion, Slack, Linear, Jira, GitHub, Airtable or anything else you've authorised, in four delivery shapes.


When to use it — and when not to

ScenarioFit
Visual trend research on a keyword✅ Strong — searchQueries
Auditing a competitor's public board✅ Strong — board URL
Everything a public profile has created✅ Strong — profile URL
Pulling one specific pin's data✅ Strong — pin URL
Colour-palette and moodboard analysis✅ Strong — dominantColor + images
Building an image-URL feed for a creative pipeline✅ Strong
Mixing searches, boards and profiles in one job✅ Strong — all four types, one dataset
Attributing every row to its source✅ Strong — sourceType + sourceInput
Results in Notion / Slack / Airtable✅ Strong — native MCP delivery
Exactly maxItems pins every time⚠️ Feeds stop when Pinterest stops serving new pins
An even split across many sources⚠️ Set maxItemsPerSourcemaxItems alone is global
Titles on every row⚠️ Many pins genuinely have none; title is null
Save counts, comments or reactions❌ No engagement metrics are returned
Comment text or commenter identities❌ Not collected
Secret boards or private profiles❌ Public content only
Downloading the images or videos❌ URLs only; files are never fetched
Following the destination link behind a pin❌ The source site is not visited
Your own account's analytics❌ Use the official Pinterest API
Pinning, repinning, commenting❌ Read-only

⚡ Execution Rules (Avoid Common Agent Failures)

  1. proxyConfiguration is the only required input — the sources are not. A run with neither searchQueries nor startUrls passes validation, logs No search queries or start URLs provided. Nothing to scrape - exiting. and ends SUCCEEDED with an empty dataset. Never read itemCount: 0 as a crash.

  2. maxItems is global; maxItemsPerSource defaults to unlimited. With five searches and maxItems: 100, one busy feed can consume the whole budget before the others contribute. Set maxItemsPerSource whenever you want an even spread.

  3. Keep the residential proxy. Default is {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}. Pinterest blocks datacenter IPs and guards its data behind a JavaScript check; residential groups need a paid Apify plan.

  4. title is null far more often than you'd expect. Many pins simply have none. Fall back to description, and treat a null title as normal rather than a parse failure.

  5. Every row carries sourceType and sourceInput. Use them instead of running one source per job just to keep results separable.

  6. pinnerUsername and pinnerFullName are personal data. They identify real people, often by real name. If your question is about images or trends, drop both columns at ingest — see Compliance.

  7. imageUrl and videoUrl are almost always someone else's work. Pinterest is a repinning platform; the pinner is usually not the author. A URL in your dataset is not a licence.

  8. The images object is nested and dataset-only. It is not available as a delivery placeholder — use imageUrl in connector templates.

  9. Feeds stop when they dry up. Scrolling ends at your limit, at the scroll ceiling, or after several consecutive scrolls with nothing new. Fewer pins than requested is normal for niche queries and small boards.

  10. A single pin URL yields exactly one row. Use board or profile URLs when you want breadth.

  11. Nothing is downloaded. You get URLs. Fetching the files is your pipeline's job — and a separate copyright decision.

  12. Empty source? Look in the key-value store. A source with no pins writes DEBUG_<source> (the rendered HTML) and DEBUG_<source>_info, which flags whether Pinterest served a login wall.

  13. deliveryMode defaults to summary. perPin sends one connector call per pin — a 500-pin run is 500 calls. Prefer chunked for long lists into Notion.

  14. Free Apify plans stop at 10 pins per source. That's a smoke test, not a data pull.

dependencies:
- rule: "proxyConfiguration is required by the schema; searchQueries / startUrls are not"
on_violation: "a sourceless run ends SUCCEEDED with an empty dataset and a warning in the log"
- rule: "maxItems caps the whole run; maxItemsPerSource caps each source"
note: "set both when you have several sources and want a fair spread"
- rule: "delivery requires mcpConnector AND mcpTool"
on_violation: "delivery is skipped with a warning; every dataset row is still written"
- rule: "mcpArguments must reference {message} for the rendered template to appear anywhere"
on_violation: "message body is empty; the tool is still called"
- rule: "chunked mode exposes {part} and {partCount}"
note: "put them in the page/message title or every part looks identical"
- rule: "mcpConnector only resolves when the Actor runs on the Apify platform"
on_violation: "local runs log 'APIFY_MCP_PROXY_URL is not set' and skip delivery"
authentication:
actor_input: none
platform: "Apify API token required for API / SDK / MCP invocation; paid plan required for residential proxy groups"
target_site: "no Pinterest account, developer app or OAuth token required (public pins only)"

📥 Input Contract

.actor/input_schema.json is authoritative — if this page disagrees with the schema files, the schema files win.

ParameterTypeRequiredDefaultNotes
searchQueriesarray<string>see noteEach keyword is scraped as its own pin feed
startUrlsarraysee noteBoard, profile or pin URLs. Type is auto-detected
maxItemsinteger⬜ No100Total across every source. 0 = unlimited
maxItemsPerSourceinteger⬜ No0 (unlimited)Per query / board / profile
proxyConfigurationobjectYesApify ResidentialThe one required field. Leave it enabled.

proxyConfiguration is the only required entry in the schema. Supplying no sources is therefore valid input — and produces an empty, successful run. Always pass at least one of searchQueries or startUrls.

How each start URL is classified

URL shapeDetected asWhat you get
https://www.pinterest.com/pin/<id>/pinThat single pin — exactly one row
https://www.pinterest.com/<user>/<board>/boardThe pins on that public board
https://www.pinterest.com/<user>/profileThat profile's created pins
Anything else on the domainunknownAttempted as a feed; check sourceType on the rows

Regional domains and trailing query strings are tolerated. Secret boards and private profiles are inaccessible by design — they aren't visible to a signed-out visitor, and this Actor never signs in.

Delivery (optional)

ParameterTypeDefaultDescription
mcpConnectorstring""A connector you've authorised on your Apify account — Notion, Slack, Linear, Jira, GitHub, Airtable, or any MCP-compatible connector. Leave empty for dataset-only runs.
deliveryModestring (enum)"summary"summary (one call listing all pins) · chunked (split across calls) · perPin (one call per pin) · none.
mcpToolstring""Tool to call — create_page, send_message, create_issue. Required when a connector is set; run once and the log lists the connector's tools.
mcpArgumentsobject{}Arguments for the tool. String leaves support {placeholder} tokens.
mcpMessageTemplatestring""Template rendered and exposed to mcpArguments as {message}.

Placeholders by mode:

ModePlaceholders
summary{pinCount} {pins} (a text list of every pin) {message}
chunkedthe same, plus {part} {partCount}{pins} holds one part
perPin{pinId} {title} {description} {pinUrl} {imageUrl} {boardName} {boardUrl} {pinnerUsername} {pinnerFullName} {dominantColor} {isVideo} {videoUrl} {createdAt} {sourceType} {sourceInput} {message}

Null values render as an empty string, and isVideo renders as true/false. The nested images object is not exposed as a placeholder — it's dataset-only. chunked keeps each call under roughly 60,000 characters so Notion and similar services don't reject the payload.


📤 Output Contract & Data Structure

One dataset row per pin, written as each source is processed. Every row carries the same 16 keys; nullable fields come back null, never "N/A".

FieldTypeNullableMeaning
pinIdstringyesPinterest's pin identifier. The stable key for joining runs and de-duplicating
titlestringyesPin title. Null is very common — many pins have none
descriptionstringyesDescription as written by the pinner
pinUrlstringyesCanonical pin page URL
imageUrlstringyesLargest available still image. Third-party copyrighted content in most cases
boardNamestringyesBoard the pin sits on
boardUrlstringyesURL of that board
pinnerUsernamestringyesHandle of the account that pinned it. Personal data
pinnerFullNamestringyesDisplay name, often a real person's name. Personal data
dominantColorstringyesDominant image colour as a hex string — useful for palette and trend work
isVideobooleannoWhether the pin is a video rather than a still
videoUrlstringyesVideo stream URL when isVideo is true, otherwise null
imagesobjectyesAll image renditions keyed by size. Nested — dataset-only, not a delivery placeholder
createdAtstringyesWhen the pin was created, as Pinterest reports it
sourceTypestringyesHow it was reached: search, board, profile, pin or unknown
sourceInputstringyesThe exact query or URL from your input that produced this pin

sourceType and sourceInput are what make mixed runs usable. Scrape three searches and two boards in one job, then split the dataset by sourceInput afterwards.

Example output object

{
"pinId": "1234567890123456789",
"title": null,
"description": "Warm minimal home office — oak desk, linen blind, brass lamp",
"pinUrl": "https://www.pinterest.com/pin/1234567890123456789/",
"imageUrl": "https://i.pinimg.com/originals/ab/cd/ef/abcdef1234567890.jpg",
"boardName": "Home Office Ideas",
"boardUrl": "https://www.pinterest.com/someuser/home-office-ideas/",
"pinnerUsername": "someuser",
"pinnerFullName": "Sam Rivera",
"dominantColor": "#c8a882",
"isVideo": false,
"videoUrl": null,
"images": {
"170x": { "url": "https://i.pinimg.com/170x/ab/cd/ef/abcdef1234567890.jpg", "width": 170, "height": 255 },
"474x": { "url": "https://i.pinimg.com/474x/ab/cd/ef/abcdef1234567890.jpg", "width": 474, "height": 711 },
"orig": { "url": "https://i.pinimg.com/originals/ab/cd/ef/abcdef1234567890.jpg", "width": 1000, "height": 1500 }
},
"createdAt": "2026-04-11T08:22:19",
"sourceType": "search",
"sourceInput": "home office ideas"
}

Values illustrate shape and formatting — the pin, board and person are invented. Note title: null, which is the normal case on Pinterest, and that pinnerFullName is a real person's name in live data.

What a successful run looks like

  • Status: SUCCEEDED
  • Dataset: one row per pin, in crawl order, up to maxItems
  • Log: Starting Pinterest scrape (browser engine): N source(s)…, a per-scroll scroll N, captured X pins line per feed, a per-source finish line, then Scrape complete. Total pins pushed: N
  • Zero results is also a success. No sources supplied, a login wall, or a query with no pins all return an empty dataset with SUCCEEDED. Check the log.
  • DEBUG_* records in the key-value store mean a source produced nothing — the rendered HTML and a looksLikeLogin flag are saved there for inspection.
  • Fewer pins than maxItems is normal for niche queries and small boards.

Dataset views

ViewShows
PinsImage, title, description, pin URL, board, pinner, video flag, source type and input
Media & ColourImage, title, dominant colour, video flag and URL, creation date, link
Source & AttributionSource type and input, pin id, title, pinner handle and name, board, links

▶️ Invocation & Integration

Authenticate every call with Authorization: Bearer <APIFY_TOKEN>.

Apify Console

Open the Actor pageInput tab → type search queries and/or paste board, profile or pin URLs → set maxItems and (for several sources) maxItemsPerSource → leave the residential proxy on → Start.

Model Context Protocol (MCP)

claude mcp add --transport http apify \
"https://mcp.apify.com?tools=techforce.global/pinterest-scraper"

Then ask your agent for "the dominant colours trending for minimalist kitchens on Pinterest".

Python (apify-client)

import os
from collections import Counter
from apify_client import ApifyClient
client = ApifyClient(os.getenv("APIFY_TOKEN"))
run = client.actor("techforce.global/pinterest-scraper").call(run_input={
"searchQueries": ["minimalist kitchen", "warm minimal interior"],
"maxItems": 200,
"maxItemsPerSource": 100, # keeps one busy feed from eating the budget
"deliveryMode": "none",
"proxyConfiguration": {"useApifyProxy": True, "apifyProxyGroups": ["RESIDENTIAL"]},
})
pins = list(client.dataset(run["defaultDatasetId"]).iterate_items())
if not pins:
raise SystemExit("Nothing scraped — check the log and any DEBUG_* key-value records.")
# Every row knows which input produced it.
print(Counter(p["sourceInput"] for p in pins))
# Colour trend per query — this is what dominantColor is for.
for query in {p["sourceInput"] for p in pins}:
colours = Counter(p["dominantColor"] for p in pins
if p["sourceInput"] == query and p.get("dominantColor"))
top = ", ".join(f"{c} ×{n}" for c, n in colours.most_common(5))
print(f"{query:28} {top}")
# title is often null — fall back to description.
for p in pins[:5]:
label = p.get("title") or (p.get("description") or "")[:60] or "(no text)"
print(f'{label:62} {p["pinUrl"]}')

JavaScript / TypeScript (apify-client)

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('techforce.global/pinterest-scraper').call({
startUrls: [
{ url: 'https://www.pinterest.com/someuser/home-office-ideas/' },
{ url: 'https://www.pinterest.com/someuser/' },
],
maxItems: 300,
maxItemsPerSource: 150,
deliveryMode: 'none',
proxyConfiguration: { useApifyProxy: true, apifyProxyGroups: ['RESIDENTIAL'] },
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
// Split a mixed run by where each pin came from.
const bySource = items.reduce<Record<string, any[]>>((acc, p) => {
(acc[p.sourceType] ??= []).push(p);
return acc;
}, {});
console.log(Object.entries(bySource).map(([t, v]) => `${t}: ${v.length}`).join(', '));
// The images object holds every rendition — pick the size you actually need.
for (const p of items.slice(0, 5)) {
const thumb = p.images?.['474x']?.url ?? p.imageUrl;
console.log(`${p.isVideo ? '▶' : '▣'} ${p.dominantColor ?? '—'} ${thumb}`);
}
// If you keep these rows, you are storing personal data — see Compliance.
const anonymised = items.map(({ pinnerUsername, pinnerFullName, ...rest }) => rest);
console.log(`${anonymised.length} rows without pinner identity`);

cURL — synchronous (waits, returns the dataset)

curl -X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \
-d '{
"searchQueries": ["home office ideas"],
"maxItems": 50,
"deliveryMode": "none",
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}' \
'https://api.apify.com/v2/acts/techforce.global~pinterest-scraper/run-sync-get-dataset-items'
# 1. Start with a hard spend limit
curl -X POST -H 'Content-Type: application/json' \
-H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \
-d '{ "searchQueries": ["travel photography"], "maxItems": 1000, "maxItemsPerSource": 500,
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] } }' \
'https://api.apify.com/v2/acts/techforce.global~pinterest-scraper/runs?maxTotalChargeUsd=10'
# 2. Poll, then 3. fetch the dataset when SUCCEEDED
curl -H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' 'https://api.apify.com/v2/actor-runs/<runId>'
curl -H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \
'https://api.apify.com/v2/datasets/<DATASET_ID>/items?clean=true&format=json'

Mixing all four input types in one run

{
"searchQueries": ["scandinavian living room", "japandi interior"],
"startUrls": [
{ "url": "https://www.pinterest.com/someuser/home-office-ideas/" },
{ "url": "https://www.pinterest.com/someuser/" },
{ "url": "https://www.pinterest.com/pin/1234567890123456789/" }
],
"maxItems": 500,
"maxItemsPerSource": 100,
"deliveryMode": "none",
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}

Five sources, one dataset, maxItemsPerSource keeping the split even. Filter afterwards on sourceInput to get each source's pins back.

Colour-trend research — the cheap configuration

{
"searchQueries": ["autumn wedding palette"],
"maxItems": 300,
"maxItemsPerSource": 300,
"deliveryMode": "none",
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}

One deep feed, then group by dominantColor downstream. No pinner columns needed — drop them at ingest and the dataset stops being personal data.

With MCP delivery — a pin digest into Notion

{
"searchQueries": ["home office ideas"],
"maxItems": 200,
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] },
"mcpConnector": "<your-authorized-notion-connector>",
"mcpTool": "create_page",
"deliveryMode": "chunked",
"mcpMessageTemplate": "Pinterest pins (part {part}/{partCount}):\n\n{pins}",
"mcpArguments": {
"parent": { "page_id": "<YOUR_NOTION_PAGE_ID>" },
"title": "Pinterest pins (part {part}/{partCount})",
"content": "{message}"
}
}

chunked is the right default for long pin lists — put {part}/{partCount} in the title or every page looks identical. Avoid perPin unless you genuinely want one record each.


⚠️ Autonomous Agent Error Handling & Resolution Matrix

Read this first: nothing about the content fails the run. Missing sources, a login wall and an exhausted feed all end SUCCEEDED while the log carries the reason. An agent that checks run status alone will read an empty dataset as success-with-data — check the row count, the log, and any DEBUG_* records.

The CONDITION labels are documentation handles for observable states; this Actor writes no error code into the dataset.

ConditionWhat you observeCauseDeterministic agent action
NO_SOURCES_PROVIDEDSUCCEEDED, empty dataset; log: No search queries or start URLs provided. Nothing to scrape - exiting.Both source inputs empty — the schema only requires the proxyModify Input: supply searchQueries or startUrls.
LOGIN_WALL_OR_BLOCKEmpty dataset; DEBUG_<source>_info shows looksLikeLogin: truePinterest served a sign-in gate — usually a datacenter IPModify Input: residential proxy, then retry.
SOURCE_YIELDED_NOTHINGLog: No pins found for <source> + DEBUG_<source> recordsPrivate/secret content, a dead URL, or a query with no pinsInspect the saved HTML. Verify the URL opens signed-out.
ONE_SOURCE_ATE_THE_BUDGETSome sources contributed nothingmaxItems is global and maxItemsPerSource defaults to unlimitedModify Input: set maxItemsPerSource.
FEWER_PINS_THAN_MAXITEMSDataset smaller than requestedThe feed stopped producing new pins, or the scroll ceiling was hitExpected. Broaden the query or add sources.
TITLE_IS_NULLMost rows have no titlePinterest pins frequently have noneExpected. Fall back to description.
NO_ENGAGEMENT_METRICSNo save or comment counts anywhereNot collected by this ActorFix expectation. Out of scope.
IMAGES_NOT_IN_TEMPLATE{images} renders empty in a connector messageThe nested object is dataset-onlyModify Input: use {imageUrl}.
SINGLE_ROW_FROM_PIN_URLA pin URL produced one rowBy designExpected. Use board/profile URLs for breadth.
PRIVATE_CONTENT_MISSINGA board or profile returned nothingSecret boards and private profiles aren't visible signed-outDo not retry. Public content only.
UNKNOWN_SOURCE_TYPERows carry sourceType: "unknown"The URL didn't match a known Pinterest shapeModify Input: use a canonical pin/board/profile URL.
NO_FILES_DOWNLOADEDYou expected images on diskOnly URLs are returnedFix expectation, and read Compliance before fetching them.
RUN_SLOWLong wall-clock for a modest pin countBrowser-driven, scroll-based crawlingExpected. Lower maxItems, or accept the time.
FREE_PLAN_CAPPED10 pins per source; log: Free plan detected - capping results to 10 pins per source.Free Apify planUpgrade the plan.
CONNECTOR_CALL_STORMHundreds of connector callsperPin sends one call per pinModify Input: switch to chunked or summary.
CONNECTOR_TOOL_NOT_FOUNDLog: Tool 'x' is not available on this connector. Available tools: …Wrong mcpTool name (empty is logged separately)Modify Input: copy an exact name from that log line. Dataset unaffected.
CONNECTOR_UNREACHABLELog: Could not reach the connector: … or APIFY_MCP_PROXY_URL is not setConnector not authorised, or running locallyAuthorise it, or apify push and run on the platform. Data already saved.
AUTH_INVALIDHTTP 401Missing or malformed APIFY_TOKENAbort & prompt user for a valid token.
RATE_LIMITED_APIFYHTTP 429Apify API rate / concurrency limits — not PinterestRetry: exponential backoff (2s, 4s, 8s).
SYNC_TIMEOUTHTTP 408 on the sync endpointRun exceeded the synchronous ceilingReconfigure: async POST /runs + polling.

Provenance: every log line, status and dataset condition above is taken from this Actor's own source and verified against it. The three HTTP rows describe the Apify API transport layer, not this Actor — confirm them against the Apify API reference before wiring them into automated retry logic.


🗣️ Natural Language → Actor Mapping

A user says…IntentConstructed Actor input
"Find Pinterest pins about X"Keyword search{"searchQueries":["X"],"maxItems":100}
"What's trending for X right now?"Trend snapshot{"searchQueries":["X"],"maxItems":300} then group by dominantColor
"Scrape this board"Board audit{"startUrls":[{"url":"<board url>"}]}
"Everything this account has pinned"Profile sweep{"startUrls":[{"url":"<profile url>"}]}
"Get the data for this one pin"Single pin{"startUrls":[{"url":"<pin url>"}]}
"Compare three moodboards"Multi-sourceThree board URLs + maxItemsPerSource to keep the split even
"What colours dominate this aesthetic?"Palette analysisSearch, then aggregate dominantColor
"Just the image URLs"Asset feedScrape, then read imageUrl or a size from images
"Only video pins"Format filterScrape, then filter isVideo: true
"Which of my searches found this pin?"AttributionRead sourceInput / sourceType — already on every row
"Send today's pins to Notion"Scrape + deliverAbove, plus mcpConnector, mcpTool, deliveryMode: "chunked"
"It returned nothing"Empty resultCheck a source was supplied, the proxy is residential, and the DEBUG_* records
"How many saves does this pin have?"Engagement❌ Not collected
"What do the comments say?"Comments❌ Not collected
"Download these images for me"Files❌ URLs only — and see Compliance before fetching
"Show me this secret board"Private content❌ Public content only
"Pin this to my board"Write action❌ Read-only

Should NOT route here: engagement metrics — saves, reactions, comment counts · comment text or commenter identities · secret boards or private profiles · your own account analytics (use the official Pinterest API) · downloading image or video files · the destination site behind a pin · pinning, repinning or any write action · non-Pinterest platforms — for shoppable equivalents see Etsy Scraper or Amazon Product Scraper.


🧭 Agent Execution & Routing Logic

Does the user want PUBLIC PINTEREST pins as data?
├── NO → wrong Actor.
│ handmade / vintage listings → Etsy Scraper
│ Amazon products + prices → Amazon Product Scraper
│ a DTC brand storefront → Quince Scraper
│ their own Pinterest analytics → official Pinterest API
└── YES
├── What do they have? (mix freely; at least ONE is needed at runtime even
│ though the schema only marks proxyConfiguration required)
│ ├── a topic → searchQueries
│ ├── a board URL → startUrls (board)
│ ├── a profile URL → startUrls (profile)
│ └── one pin URL → startUrls (pin → exactly one row)
├── ALWAYS keep the residential proxy (paid plan required)
├── Size the run
│ ├── maxItems → GLOBAL across every source (0 = unlimited)
│ ├── maxItemsPerSource → SET THIS when there are several sources,
│ │ or one busy feed takes the whole budget
│ └── feeds stop early when Pinterest stops serving new pins
├── Does the question involve PEOPLE or IMAGES?
│ ├── images / trends → drop pinnerUsername + pinnerFullName at ingest
│ └── people → you are processing personal data; see Compliance
├── What is the actual question?
│ ├── what's trending → search + count repeats across sourceInput
│ ├── palette → group by dominantColor
│ ├── asset feed → imageUrl, or pick a size from images
│ ├── video only → filter isVideo
│ └── board audit → board URL, read boardName/boardUrl
└── Should results land in another app?
├── yes → mcpConnector + mcpTool + {message} in mcpArguments
│ long list → chunked ({part}/{partCount} in the title)
│ digest → summary (default) · record each → perPin
└── no → deliveryMode "none", or leave mcpConnector empty
[Execute Actor]
├──► SUCCEEDED with rows → split by sourceInput, then analyse
├──► SUCCEEDED, 0 rows → READ THE LOG + the DEBUG_* key-value records
└──► 10 pins per source → free plan cap, not a data pull

💰 Cost Control & Pricing Transparency

Billing model: usage-based. This Actor bills for platform usage — the compute time and resources a run consumes — not per row. Current rates are on the Actor's Apify Store page; the Console shows the live total mid-run.

The shape to keep in mind: cost tracks time spent scrolling, not pin count directly. Pinterest feeds are infinite-scroll, so a run is a browser holding a page open and scrolling until your limit is met or the feed dries up.

ChoiceEffect on cost
maxItemsThe main lever — it decides how long the scrolling continues.
Number of sourcesEach search, board or profile is its own browser page and its own scroll loop.
maxItemsPerSourceCaps the deep-scroll on any one feed; useful for predictability as well as fairness.
Niche queriesCheap in a good way — the feed dries up early and the source finishes.
Being blockedThe browser loads, scrolls, and finds nothing. A datacenter proxy is the most expensive setting on this page.

Worked examples — relative run shape

ScenarioSourcesPinsNotes
Probe — 1 query, maxItems: 251≤ 25Baseline. Confirms proxy and query in a few scrolls.
Trend snapshot — 1 query, 300 pins1≤ 300One deep scroll loop; the common research shape.
Board audit — 1 board1board sizeStops when the board is exhausted.
Single pin lookup11The cheapest possible run.
Five sources, maxItems: 500, no per-source cap5≤ 500⚠️ One feed may take all 500.
Five sources, maxItemsPerSource: 1005≤ 500Even split, five shorter scroll loops.
Unbounded — maxItems: 0 on a broad query1until the feed dries upNever without maxTotalChargeUsd.

Keeping runs predictable:

  1. First run: one query, maxItems: 25. Proves the proxy and the query cheaply.
  2. Always set maxItemsPerSource with more than one source — for cost predictability as much as fairness.
  3. Prefer several focused queries over one broad one — narrow feeds finish; broad ones scroll forever.
  4. Always set maxTotalChargeUsd when maxItems is 0 or in the high hundreds.
  5. Schedule small and often rather than one huge sweep if you're tracking a trend over time.
  6. Free Apify plans get 10 pins per source — a connectivity check, not a data pull.

🛠️ Troubleshooting

Most problems are the proxy, the global-vs-per-source limits, or an expectation about fields Pinterest doesn't expose — not parser bugs.

#Symptom you seeMost likely causeFix
1SUCCEEDED but the dataset is emptyNo sources supplied — the schema only requires the proxyRead the log for Nothing to scrape - exiting. and pass searchQueries or startUrls.
2Empty dataset and DEBUG_*_info says looksLikeLogin: truePinterest served a sign-in gate, almost always a datacenter IPSwitch to residential and retry.
3One source returned nothingPrivate/secret content, a dead URL, or a genuinely empty queryOpen the URL signed-out in a browser; inspect the saved DEBUG_<source> HTML.
4Some sources contributed nothing to a multi-source runmaxItems is global; one feed consumed itSet maxItemsPerSource.
5Fewer pins than maxItemsThe feed stopped serving new pins, or the scroll ceiling was reachedExpected for niche queries and small boards — broaden or add sources.
6title is null on most rowsVery common on PinterestUse description; treat null titles as normal.
7No save counts, comments or reactionsEngagement metrics aren't collectedOut of scope for this Actor.
8{images} renders empty in a Notion/Slack messageThe nested object is dataset-onlyUse {imageUrl} in templates.
9videoUrl is nullThe pin is a still imageCheck isVideo first.
10sourceType is unknownThe URL didn't match a known Pinterest shapeUse a canonical pin, board or profile URL.
11You expected image filesOnly URLs are returnedFetch them yourself — and read Compliance first.
12A pin URL returned only one rowBy designUse board or profile URLs for breadth.
13The run is slow for the pin countBrowser-driven infinite-scroll crawlingExpected. Lower maxItems or split across scheduled runs.
14Only 10 pins per sourceFree plan capUpgrade; the log says Free plan detected - capping results to 10 pins per source.
15Hundreds of connector calls firedperPin sends one call per pinSwitch to chunked or summary.
16Every Notion page looks identical{part}/{partCount} missing from the title in chunked modeAdd them to the title template.
17Slack / Notion received nothingDelivery needs both mcpConnector and mcpToolSet both. Every dataset row is still saved.
18Log: APIFY_MCP_PROXY_URL is not setRan locally; connectors only resolve on the platformapify push and run on the platform.
19HTTP 401 / 403 from the Apify APIMissing, expired or malformed APIFY_TOKENRegenerate in Console → Settings → API & Integrations.
20HTTP 429 / 408 from the Apify APIApify rate limits / the sync endpoint's time ceilingBack off (2s → 4s → 8s), or switch to async POST /runs + polling.

Diagnostic checklist before opening an issue

  1. Confirm a source is setsearchQueries or startUrls. The proxy alone is valid input.
  2. Confirm the proxy is residential and the plan supports it.
  3. Open the DEBUG_* records in the run's key-value store — looksLikeLogin usually settles it in one look.
  4. Baseline run: one query, maxItems: 25, deliveryMode: "none".
  5. Open the same search or URL signed-out in a browser — private and empty look identical to a scraper.
  6. Check sourceType on the rows you did get, to confirm each URL was classified as intended.

If the issue survives all six, open an Issues ticket (or email support) with the run ID, the input you used, and what you expected.


❓ FAQ

Do I need a Pinterest account or API key?

No. The Actor reads publicly visible pins. You need an Apify account and API token; you need no Pinterest credentials, developer app or OAuth token.

Is this the official Pinterest API?

No. This is an independent Actor and is not affiliated with, endorsed by, or sponsored by Pinterest, Inc. The official API is built around your own account's pins, boards and analytics; this Actor covers public discovery it doesn't reach.

Do I need a paid Apify plan?

In practice, yes. Pinterest blocks datacenter IPs, so the default residential proxy — which requires a paid plan — is what makes runs work. proxyConfiguration is also the Actor's only required input.

Can I plug it into Claude, Cursor, or a LangChain agent?

Yes — it is a native MCP tool: claude mcp add --transport http apify "https://mcp.apify.com?tools=techforce.global/pinterest-scraper"

What can I pass as a start URL?

Pin URLs (/pin/<id>/), public board URLs (/<user>/<board>/) and public profile URLs (/<user>/). The Actor detects which is which and records the result in sourceType. A pin URL yields exactly one row.

Can I mix searches, boards, profiles and pins in one run?

Yes — that's the point of sourceType and sourceInput, which appear on every row so a mixed run stays separable afterwards.

Why did some of my sources return nothing?

Most often because maxItems is a global cap and maxItemsPerSource defaults to unlimited, so one busy feed consumed the whole budget. Set maxItemsPerSource for an even spread. Otherwise, check the DEBUG_* records — the source may be private, empty or gated.

Why did I get fewer pins than maxItems?

The feed ran out. Scrolling stops when your limit is reached, when the scroll ceiling is hit, or after several consecutive scrolls produce nothing new. Niche queries and small boards legitimately finish early.

Why is title null on so many rows?

Because a great many Pinterest pins genuinely have no title — the description carries the text. Treat null titles as normal and fall back to description.

Can I get save counts, comments or engagement metrics?

No. This Actor returns the pin's content and provenance, not its engagement. Comment text and commenter identities aren't collected either.

Does it download the images or videos?

No. You get imageUrl, videoUrl and the full images rendition object. Fetching the files is your pipeline's decision — and a copyright one, since the images usually belong to a third party.

What is the images object for?

It holds every rendition Pinterest publishes, keyed by size, so you can pick a thumbnail or the original without guessing at URL patterns. It's dataset-only — connector templates should use {imageUrl}.

What is dominantColor good for?

Palette and trend work. Group a search's pins by dominantColor and you get the colour story of an aesthetic in one aggregation, instead of eyeballing a moodboard.

Can it reach secret boards or private profiles?

No. The Actor never signs in, so anything invisible to a signed-out visitor is out of reach by design.

Does the output contain personal data?

Yes — pinnerUsername and pinnerFullName identify real people, frequently by real name. They're the one genuinely sensitive part of the output. If your question is about images or trends, drop both columns at ingest. See Compliance & Data Privacy.

Can I republish the images I collect?

Almost certainly not without permission. Pinterest is a repinning platform, so the pinner is usually not the author, and the URLs point at third-party copyrighted work. Internal research and analysis sit on far safer ground than republication.

Which delivery mode should I use, and does it work locally?

summary for a single digest (the default), chunked for long pin lists into services with request caps like Notion, perPin only when you want one record each — a 500-pin run is 500 calls — and none for dataset-only runs. Delivery only works on the Apify platform; locally you'll see APIFY_MCP_PROXY_URL is not set and the dataset saves as normal.

What does it cost, and what do I get on the free plan?

Usage-based: you pay for the platform usage a run consumes, not per row. Because feeds are infinite-scroll and browser-driven, cost tracks scrolling time — maxItems is the lever. Free Apify plans return 10 pins per source. Pass maxTotalChargeUsd for a hard per-run ceiling.


🔍 Companion machine-readable files

FileWhat it defines
.actor/input_schema.jsonEvery input, its type, default and bounds — and that proxyConfiguration is required
.actor/dataset_schema.jsonAll 16 output fields with nullability, and the three Console views
.actor/output_schema.jsonWhere the run's output is exposed
.actor/actor.jsonActor identity and storage wiring

If this page and the schema files disagree, the schema files win. They are what the platform validates against at run time; this page is documentation and can lag a release.


ActorBest forWhy pair it with this one
Etsy ScraperListings from Etsy's handmade and vintage marketplaceThe closest commercial match to a Pinterest aesthetic — turn a trend into things people actually sell
Amazon Product ScraperAmazon listings across 7 marketplaces, with prices and ratingsPrice and demand reality behind the mood board
Quince ScraperCatalogue and pricing from QuinceA direct-to-consumer storefront to compare a trend against real product assortment

Pipeline patterns: trend → product — a Pinterest search for an aesthetic, then Etsy or Amazon for the same terms, to see whether the look has a market · palette tracking — the same query on a schedule, grouped by dominantColor, to watch a colour story shift over months · competitor moodboards — several board URLs with maxItemsPerSource, compared side by side on colour and subject · creative brief feed — a curated search delivered into Notion via chunked, images and all.

Browse all Actors by Techforce Global at scraper.techforce.global.


🔐 Compliance & Data Privacy

Trademark & affiliation. This is an independent Actor. It is not affiliated with, endorsed by, or sponsored by Pinterest, Inc. Pinterest™ is a trademark of Pinterest, Inc.

1. Pinner names are personal data

pinnerUsername and pinnerFullName identify real people, and on Pinterest a great many accounts use a real name rather than a handle.

  • Under GDPR / UK GDPR and CCPA/CPRA, collecting and storing those columns is processing personal data, and the obligations sit with you, not with the Actor.
  • The cheapest compliance measure is a projection. If your question is about images, colours or trends — which it usually is — drop pinnerUsername and pinnerFullName at ingest. What remains is commercial and creative content, not a record about individuals.
  • Don't build profiles. Aggregating one person's pins across boards to infer their interests, household, health or life events is exactly the processing that carries risk, and Pinterest boards are unusually revealing on all four.
  • If you do keep pinner identity, have a lawful basis, keep retention short and restrict access.

2. The images are almost certainly someone else's

Pinterest's whole mechanic is repinning, so the account that pinned an image is usually not the person who made it.

  • imageUrl, videoUrl and every entry in images point at third-party copyrighted work hosted by Pinterest on someone else's behalf. A URL in your dataset is not a licence.
  • Internal research, trend analysis, palette extraction and moodboarding sit on far safer ground than republishing, redistributing or training on the imagery.
  • Hotlinking Pinterest's CDN in your own product is both a copyright question and an operational one — those URLs can rotate or disappear without notice.
  • If you plan to publish anything visual you found this way, trace it back to the original creator and get permission. The pin's description and destination link are starting points, not proof of authorship.

And generally

  • Public pins only. No sign-in, no secret boards, no private profiles, no account or analytics data, no credentials of any kind.
  • Feeds are personalised and volatile. Pinterest reorders and re-ranks constantly, so a run is one observation, not "what Pinterest shows for X". Two runs minutes apart can legitimately differ; say when you captured a trend.
  • The Actor does not consult robots.txt. That's a deliberate configuration for a browser-driven scraper on a JavaScript-gated site, and it's a fact you should weigh rather than discover later.
  • Pinterest's Terms of Service prohibit automated access and data extraction. This Actor does not remove that risk — it is a risk you accept by running it. Keep volumes proportionate to the question you're answering.
  • Attribution over mirroring. Every row carries pinUrl and boardUrl. Link back to the pin rather than presenting Pinterest's visual graph as your own collection.

🆘 Support & Custom Pipeline Engineering

Need automated multi-city scheduled feeds, webhook enrichment, or enterprise data warehouse syncs?



🏷️ Structured data for search & AI discovery

SoftwareApplication describes the Actor; FAQPage wraps the FAQ above so those answers are eligible for rich results, matching it question-for-question.

{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Pinterest Scraper",
"alternateName": "Pinterest Scraper | All-In-One",
"applicationCategory": "BusinessApplication",
"applicationSubCategory": "Web Scraping / Visual Discovery & Trend Research",
"operatingSystem": "Cloud (Apify platform)",
"description": "Scrapes public Pinterest pins from keyword searches, board URLs, profile URLs and individual pin URLs — all four input types mixed freely in a single run — without a Pinterest account, developer app or OAuth token. Each row carries the pin id, title, description, pin URL, largest still-image URL, board name and URL, pinner username and display name, dominant image colour, a video flag and stream URL, every available image rendition, the creation date, and the source type and exact input that produced it. Runs through a residential proxy with a real browser engine, and results can be delivered into Notion, Slack, Linear, Airtable or any MCP connector.",
"url": "https://apify.com/techforce.global/pinterest-scraper",
"author": { "@type": "Organization", "name": "Techforce Global", "url": "https://www.techforceglobal.com" },
"provider": { "@type": "Organization", "name": "Apify", "url": "https://apify.com" },
"offers": {
"@type": "Offer",
"priceCurrency": "USD",
"category": "Pay per platform usage",
"description": "Usage-based: billed for the compute time and resources a run consumes, not per row. Browser-driven and scroll-based, so cost tracks time spent scrolling feeds. Current rates are shown on the Actor's Apify Store page.",
"url": "https://apify.com/techforce.global/pinterest-scraper"
},
"featureList": [
"No Pinterest account, developer app or OAuth token required",
"Four input types in one run: keyword searches, boards, profiles and single pins",
"Automatic URL type detection with sourceType on every row",
"sourceInput records the exact query or URL that produced each pin",
"Largest still-image URL plus every image rendition in a nested images object",
"Video flag and stream URL for video pins",
"Dominant image colour as a hex string for palette and trend analysis",
"Board name and URL, pinner handle and display name",
"Global maxItems cap plus a per-source cap for even distribution",
"Residential proxy with a real browser engine for Pinterest's JavaScript gate",
"Rendered HTML saved to the key-value store when a source yields nothing, with a login-wall flag",
"Rows saved as they are scraped, so aborted runs keep their partial data",
"Optional MCP delivery in summary, chunked or per-pin shapes",
"Three Console dataset views covering pins, media/colour and attribution"
],
"isAccessibleForFree": false,
"softwareRequirements": "Apify account and API token; a paid plan for residential proxies",
"keywords": "Pinterest scraper, scrape Pinterest pins, Pinterest board scraper, Pinterest image URL extractor, Pinterest API alternative, visual trend research, moodboard data, dominant colour palette, creative intelligence, MCP connector"
}
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "Do I need a Pinterest account or API key?",
"acceptedAnswer": { "@type": "Answer", "text": "No. The Actor reads publicly visible pins. You need an Apify account and API token; you need no Pinterest credentials, developer app or OAuth token." }
},
{
"@type": "Question",
"name": "Is this the official Pinterest API?",
"acceptedAnswer": { "@type": "Answer", "text": "No. This is an independent Actor and is not affiliated with, endorsed by, or sponsored by Pinterest, Inc. The official API is built around your own account's pins, boards and analytics; this Actor covers public discovery it doesn't reach." }
},
{
"@type": "Question",
"name": "Do I need a paid Apify plan?",
"acceptedAnswer": { "@type": "Answer", "text": "In practice, yes. Pinterest blocks datacenter IPs, so the default residential proxy — which requires a paid plan — is what makes runs work. proxyConfiguration is also the Actor's only required input." }
},
{
"@type": "Question",
"name": "Can I plug it into Claude, Cursor, or a LangChain agent?",
"acceptedAnswer": { "@type": "Answer", "text": "Yes — it is a native MCP tool: claude mcp add --transport http apify \"https://mcp.apify.com?tools=techforce.global/pinterest-scraper\"" }
},
{
"@type": "Question",
"name": "What can I pass as a start URL?",
"acceptedAnswer": { "@type": "Answer", "text": "Pin URLs (/pin/<id>/), public board URLs (/<user>/<board>/) and public profile URLs (/<user>/). The Actor detects which is which and records the result in sourceType. A pin URL yields exactly one row." }
},
{
"@type": "Question",
"name": "Can I mix searches, boards, profiles and pins in one run?",
"acceptedAnswer": { "@type": "Answer", "text": "Yes — that's the point of sourceType and sourceInput, which appear on every row so a mixed run stays separable afterwards." }
},
{
"@type": "Question",
"name": "Why did some of my sources return nothing?",
"acceptedAnswer": { "@type": "Answer", "text": "Most often because maxItems is a global cap and maxItemsPerSource defaults to unlimited, so one busy feed consumed the whole budget. Set maxItemsPerSource for an even spread. Otherwise, check the DEBUG_* records — the source may be private, empty or gated." }
},
{
"@type": "Question",
"name": "Why did I get fewer pins than maxItems?",
"acceptedAnswer": { "@type": "Answer", "text": "The feed ran out. Scrolling stops when your limit is reached, when the scroll ceiling is hit, or after several consecutive scrolls produce nothing new. Niche queries and small boards legitimately finish early." }
},
{
"@type": "Question",
"name": "Why is title null on so many rows?",
"acceptedAnswer": { "@type": "Answer", "text": "Because a great many Pinterest pins genuinely have no title — the description carries the text. Treat null titles as normal and fall back to description." }
},
{
"@type": "Question",
"name": "Can I get save counts, comments or engagement metrics?",
"acceptedAnswer": { "@type": "Answer", "text": "No. This Actor returns the pin's content and provenance, not its engagement. Comment text and commenter identities aren't collected either." }
},
{
"@type": "Question",
"name": "Does it download the images or videos?",
"acceptedAnswer": { "@type": "Answer", "text": "No. You get imageUrl, videoUrl and the full images rendition object. Fetching the files is your pipeline's decision — and a copyright one, since the images usually belong to a third party." }
},
{
"@type": "Question",
"name": "What is the images object for?",
"acceptedAnswer": { "@type": "Answer", "text": "It holds every rendition Pinterest publishes, keyed by size, so you can pick a thumbnail or the original without guessing at URL patterns. It's dataset-only — connector templates should use {imageUrl}." }
},
{
"@type": "Question",
"name": "What is dominantColor good for?",
"acceptedAnswer": { "@type": "Answer", "text": "Palette and trend work. Group a search's pins by dominantColor and you get the colour story of an aesthetic in one aggregation, instead of eyeballing a moodboard." }
},
{
"@type": "Question",
"name": "Can it reach secret boards or private profiles?",
"acceptedAnswer": { "@type": "Answer", "text": "No. The Actor never signs in, so anything invisible to a signed-out visitor is out of reach by design." }
},
{
"@type": "Question",
"name": "Does the output contain personal data?",
"acceptedAnswer": { "@type": "Answer", "text": "Yes — pinnerUsername and pinnerFullName identify real people, frequently by real name. They're the one genuinely sensitive part of the output. If your question is about images or trends, drop both columns at ingest." }
},
{
"@type": "Question",
"name": "Can I republish the images I collect?",
"acceptedAnswer": { "@type": "Answer", "text": "Almost certainly not without permission. Pinterest is a repinning platform, so the pinner is usually not the author, and the URLs point at third-party copyrighted work. Internal research and analysis sit on far safer ground than republication." }
},
{
"@type": "Question",
"name": "Which delivery mode should I use, and does it work locally?",
"acceptedAnswer": { "@type": "Answer", "text": "summary for a single digest (the default), chunked for long pin lists into services with request caps like Notion, perPin only when you want one record each — a 500-pin run is 500 calls — and none for dataset-only runs. Delivery only works on the Apify platform; locally you'll see APIFY_MCP_PROXY_URL is not set and the dataset saves as normal." }
},
{
"@type": "Question",
"name": "What does it cost, and what do I get on the free plan?",
"acceptedAnswer": { "@type": "Answer", "text": "Usage-based: you pay for the platform usage a run consumes, not per row. Because feeds are infinite-scroll and browser-driven, cost tracks scrolling time — maxItems is the lever. Free Apify plans return 10 pins per source. Pass maxTotalChargeUsd for a hard per-run ceiling." }
}
]
}