# Pinterest Scraper — Pins, Boards, Search, Video URLs | $1.99/1k (`glasswing/pinterest-scraper`) Actor

Scrape Pinterest pins and boards by keyword, the pins of any board, or single pins by URL. Titles, descriptions, outbound links and domains, image URLs, video URLs, alt text, engagement counts and dominant colour. No login and no pinner identity data. Export to CSV, JSON or Excel.

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

## Pricing

from $1.99 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

Turn any Pinterest search into a spreadsheet of pins you can actually work with: title, description, the outbound destination link, a direct image URL with its real pixel dimensions, the dominant colour, the board it lives on, when it was created and whether it is a video. Built for e-commerce and trend researchers, content and social planners, designers hunting reference, and anyone feeding a creative pipeline or an AI agent.

Scrape Pinterest pins by keyword - one keyword or a whole list in a single run - or switch scope to **boards** and get the boards that rank for a topic instead. Paste a **board URL** to get every pin saved on that board, or a **pin URL** to get one detailed row with save, repin, share and reaction counts and the direct video URL of a video pin. No login, no API key, no cookie and no browser: the Actor reads the same public responses pinterest.com loads for a visitor, so a 20-result preview finishes in about **7 seconds** and 1,000 pins cost only a handful of HTTP requests. Results export to CSV, JSON, Excel or XML.

This is an unofficial community Actor. It is not affiliated with, endorsed by or connected to Pinterest.

### What does this Pinterest scraper do?

You give it keywords or Pinterest URLs; it gives you back one clean row per pin or board.

- **Keyword search.** One keyword in `query`, several in `queries`, or Pinterest search URLs. **Scope `pins`** (the default) returns individual pins with their image, description, destination link and board. **Scope `boards`** returns the boards that match the keyword, with the board name, description, cover image and pin count.
- **Board URLs.** `https://www.pinterest.com/<owner>/<board>/` returns the pins saved on that board, page after page, up to your limit.
- **Pin URLs.** `https://www.pinterest.com/pin/<id>/` returns one detailed row: everything a search row has, plus save, repin, comment, share and reaction counts and, for a video pin, the MP4 URL.
- **Video, domain and alt text on every path.** `videoUrl` for video pins, `domain` (the host of the outbound link) and `altText` are filled wherever Pinterest publishes them.

Country domains work (`pinterest.co.uk`, `pinterest.de`, ...), and a bare keyword typed into the URL field is accepted as a shortcut. A board or pin that does not exist becomes one free `not_found` row. Profile URLs and `/search/users/` are refused on purpose, each with one free explanatory row, because this Actor does not collect people.

#### Result status (tri-state output)

Every row says what happened to it, so nothing ever fails silently:

| `status` | Meaning | Billed? |
|---|---|---|
| `ok` | Data was extracted. | Yes |
| `not_found` | Pinterest answered normally, but there is no such pin or board, or the search matched nothing. | No |
| `error` | The source could not be read or the input entry was unusable; `error` explains why. | No |

You are only charged for `ok` rows. A run that finds nothing costs you the Actor start event and nothing else.

### Use cases for Pinterest search data

- **E-commerce trend research.** A merchandiser pulls 500 pins for "quiet luxury kitchen", groups them by `dominantColor` and `createdAt`, and sees which palettes and product shapes are surfacing this quarter before committing to a buy.
- **Content and campaign planning.** A social media manager searches their category weekly, reads the `title` and `description` wording that keeps appearing, and writes pin copy and hashtags that match how people actually search.
- **Creative inspiration and moodboards.** A designer or art director collects `imageUrl` plus `imageWidth` and `imageHeight` for a theme and drops the set straight into a moodboard tool, a brief, or a vision-model pipeline — no manual right-click-save.
- **Traffic and affiliate research.** An affiliate or SEO analyst filters to rows where `link` is present to see exactly which shops, blogs and recipe sites Pinterest is sending category traffic to.
- **Competitor category monitoring.** A brand team searches a competitor's product terms and watches which boards their pins get collected on and how large (`pinCount`) those boards are.
- **AI agents and automation.** Rows are flat JSON with an explicit `status` column, so an agent building a mood report or a product feed can tell "no results" apart from "could not check" without parsing prose.

### What data you get from every pin or board

One row per result: a pin found by a search, a pin saved on a board, or a pin given by URL. `resultType` is `pin` normally, or `board` when you search with Scope set to boards. Missing means Pinterest did not publish it — fields are omitted, never filled with a guess.

#### The result

| Field | Type | Description |
|---|---|---|
| `resultType` | string | `pin` for a pin result, `board` for a board result. |
| `pinId` | string | Pinterest's numeric id for the result: the pin id, or the board id when Scope is boards. |
| `title` | string | Pin title. When the pinner left it blank, Pinterest's grid title or its image alt text is used instead. For a board row, the board name. |
| `description` | string | Description written by the pinner, or the board description. Frequently empty on Pinterest. |
| `pinUrl` | string | Canonical pinterest.com URL of the pin, or of the board for a board row. |
| `link` | string | Outbound destination URL the pin points at — the shop, recipe or article. Absent for pins uploaded straight to Pinterest. |
| `domain` | string | Host of `link` without a leading `www.`, e.g. `amazon.com`. Absent when there is no outbound link. |
| `isVideo` | boolean | True when the pin plays a video: a video pin, or an idea pin with a video block. |
| `videoUrl` | string | Best playable URL of a video pin: the largest MP4 when Pinterest publishes one (a pin URL does), otherwise the HLS playlist (`.m3u8`). Absent for image pins. The video file itself is never copied. |
| `createdAt` | string | ISO 8601 timestamp of when the pin was created. Pinterest does not publish this for boards, nor for the pins in a board listing. |

#### Image

| Field | Type | Description |
|---|---|---|
| `imageUrl` | string | URL of the largest still image Pinterest publishes for this result. The image file itself is never copied or re-hosted. |
| `imageWidth` | integer | Width in pixels of the image at `imageUrl`. |
| `imageHeight` | integer | Height in pixels of the image at `imageUrl`. |
| `altText` | string | Alt text of the image: the one written for the pin when there is one, otherwise the one Pinterest generated. |
| `dominantColor` | string | Hex colour Pinterest computed for the image, e.g. `#816748`. Handy for palette and trend analysis. |

#### Board

| Field | Type | Description |
|---|---|---|
| `boardName` | string | Name of the board the pin is saved on. |
| `boardUrl` | string | Absolute URL of that board. |
| `pinCount` | integer | Number of pins on the board. Board rows only. |

#### Engagement (complete for pin URLs, partial elsewhere — see Limitations)

| Field | Type | Description |
|---|---|---|
| `saveCount` | integer | Times the pin was saved. Returned for a pin URL and for board pins; usually absent from search results. |
| `repinCount` | integer | Repin count. Returned for a pin URL and for board pins; usually absent from search results. |
| `commentCount` | integer | Comment count. Returned for a pin URL; usually absent from search results. |
| `shareCount` | integer | Times the pin was shared. Pin URLs only. |
| `reactionCount` | integer | Reactions of every kind added up. Returned for a pin URL and for most search results. |

#### Bookkeeping

| Field | Type | Description |
|---|---|---|
| `searchQuery` | string | The keyword this row was found with, so several searches stay separable in one dataset. Absent on rows that came from a board URL or a pin URL. |
| `url` | string | The URL this row describes; identical to `pinUrl`. |
| `status` | string | `ok`, `not_found` or `error` — see the table above. |
| `error` | string | Why the row is not `ok`. Absent on `ok` rows. |
| `scrapedAt` | string | ISO 8601 timestamp of when this row was extracted. |

### How to scrape Pinterest pins and boards

1. Open the Actor and type your keywords into **Keywords**, one per line (or a single one into **Search keyword**). To read a board or a single pin instead, paste its URL into **Pinterest URLs**; search URLs go there too, and a bare keyword typed into that field works as well.
2. Pick a **Scope** for the keyword searches: `Pins` for individual pins (the default), `Boards` to find boards about the topic.
3. Set **Maximum results**. Start with the default 20 to see the shape of the data. With several keywords the total is shared evenly between them; set **Maximum results per search** to choose the share yourself.
4. Click **Start**. Results appear in the dataset within seconds; export as JSON, CSV, Excel, XML or HTML, or read them from the API.

To run it from code or from an agent, call the Apify API with the same input object; the dataset is available at `https://api.apify.com/v2/datasets/<datasetId>/items`.

### Input

| Field | Type | Default | When to change it |
|---|---|---|---|
| `startUrls` | array of strings | `["https://www.pinterest.com/search/pins/?q=coffee"]` | Replace with your own URLs, one per line: search pages, boards (`https://www.pinterest.com/<owner>/<board>/`) or single pins (`https://www.pinterest.com/pin/<id>/`), in any mix. Country domains (pinterest.co.uk, pinterest.de, ...) are accepted, and a bare keyword such as `coffee` works as a shortcut. |
| `query` | string | *(empty)* | Use it instead of a URL when you just want to type one keyword the way you would in the Pinterest search box. It can be combined with `startUrls`: it simply adds one more search. |
| `queries` | array of strings | *(empty)* | Several keywords in one run, one per line. Each is searched at the selected Scope, and `searchQuery` on every row says which keyword found it. When `queries` or `query` is given and `startUrls` still holds only the built-in coffee example, the example is skipped. |
| `scope` | select: `pins`, `boards` | `pins` | Switch to `boards` when you want the boards that rank for a topic rather than individual pins. Applies to `query`, to `queries` and to any search URL that does not name a scope itself. Board and pin URLs are not affected. |
| `maxItems` | integer | `20` | Raise it for a real dataset — this is also your spending cap, since each `ok` row is one billable result. It counts rows of every status, across all keywords and URLs. |
| `maxItemsPerQuery` | integer | *(empty)* | The most rows any one keyword, search URL or board may add. Leave it empty and a single search or board may use everything up to `maxItems`; with `queries`, leaving it empty shares `maxItems` evenly between the searches so the first keyword cannot use up the run. |
| `proxyConfiguration` | object | `{ "useApifyProxy": false }` | Leave off; the Actor is HTTP-only and needs no proxy from a normal IP. Enable Apify Proxy (datacenter) only if Pinterest starts answering 403 or 429. |

Example input — several keywords in one run, 50 pins each:

```json
{
    "queries": ["cold brew", "matcha latte", "espresso bar"],
    "scope": "pins",
    "maxItems": 150,
    "maxItemsPerQuery": 50
}
```

Example input — every pin saved on a board:

```json
{
    "startUrls": ["https://www.pinterest.com/ikeahacker/best-ikea-hacks/"],
    "maxItems": 200
}
```

Example input — single pins in detail, with counts and the video URL:

```json
{
    "startUrls": [
        "https://www.pinterest.com/pin/181199585001797964/",
        "https://www.pinterest.com/pin/63191201017606220/"
    ]
}
```

The original forms keep working unchanged: a search URL in `startUrls`, a single keyword in `query`, or both.

```json
{
    "startUrls": ["https://www.pinterest.com/search/pins/?q=coffee"],
    "query": "cold brew setup",
    "scope": "pins",
    "maxItems": 100,
    "proxyConfiguration": { "useApifyProxy": false }
}
```

Profile URLs, board section URLs and `/search/users/` pages are **not** supported. They are skipped, each with one free `error` row explaining why, rather than silently disappearing. Profiles and `/search/users/` are refused on purpose: this Actor does not collect people.

### Output

A real row from the default run (start URL `https://www.pinterest.com/search/pins/?q=coffee`, `maxItems: 20`, which finished in 6.3 seconds with 20 `ok` rows from a single HTTP request):

```json
{
    "url": "https://www.pinterest.com/pin/26036504092933313/",
    "status": "ok",
    "scrapedAt": "2026-09-20T19:10:30.981Z",
    "resultType": "pin",
    "pinId": "26036504092933313",
    "searchQuery": "coffee",
    "title": "there is a cup of coffee on the saucer",
    "pinUrl": "https://www.pinterest.com/pin/26036504092933313/",
    "imageUrl": "https://i.pinimg.com/originals/f3/56/59/f3565938a74dffad34103837416f664f.jpg",
    "imageWidth": 1440,
    "imageHeight": 1440,
    "altText": "there is a cup of coffee on the saucer",
    "dominantColor": "#7c6e5d",
    "boardName": "Ideias para meu diário",
    "boardUrl": "https://www.pinterest.com/giovannaemilia2/ideias-para-meu-di%C3%A1rio/",
    "createdAt": "2026-01-17T20:05:53.000Z",
    "reactionCount": 2641,
    "isVideo": false
}
```

A pin URL (`https://www.pinterest.com/pin/181199585001797964/`), a video pin, from a real run:

```json
{
    "url": "https://www.pinterest.com/pin/181199585001797964/",
    "status": "ok",
    "scrapedAt": "2026-09-20T19:07:41.040Z",
    "resultType": "pin",
    "pinId": "181199585001797964",
    "title": "Pouring Perfection: Tulip Latte Art in Action",
    "description": "Perfecting the tulip pour, one latte at a time 🌷☕️ #LatteGoals",
    "link": "https://subminimal.com/products/nanofoamer",
    "domain": "subminimal.com",
    "pinUrl": "https://www.pinterest.com/pin/181199585001797964/",
    "imageUrl": "https://i.pinimg.com/originals/9e/15/f9/9e15f947032f2dfa5f0d119332a47e8a.jpg",
    "imageWidth": 1080,
    "imageHeight": 1920,
    "dominantColor": "#b27755",
    "boardName": "Coffee is Life",
    "boardUrl": "https://www.pinterest.com/Kathyd2016/coffee-is-life/",
    "createdAt": "2024-06-20T10:33:25.000Z",
    "saveCount": 1423,
    "repinCount": 582,
    "commentCount": 0,
    "shareCount": 54,
    "reactionCount": 194,
    "isVideo": true,
    "videoUrl": "https://v1.pinimg.com/videos/iht/720p/0b/08/e9/0b08e9d5e378b9f8f7f3081de3bfd394.mp4"
}
```

One pin of a board URL (`https://www.pinterest.com/ikeahacker/best-ikea-hacks/`), from the same run:

```json
{
    "url": "https://www.pinterest.com/pin/112167846967490473/",
    "status": "ok",
    "scrapedAt": "2026-09-20T19:07:41.594Z",
    "resultType": "pin",
    "pinId": "112167846967490473",
    "title": "Turn IKEA doll beds into an adorable cat bunk bed",
    "description": "Move over dolls, we want the IKEA DUKTIG as a cat bunk bed You may have seen some photos of these adorable cat bunk beds and wondered where they came from. They’re actually sold as “doll beds” at IKEA! IKEA does sell pet furniture (in some countries) and it’s probably easier to buy than make,",
    "link": "https://ikeahackers.net/2019/10/cat-bunk-bed-pets-ikea.html",
    "domain": "ikeahackers.net",
    "pinUrl": "https://www.pinterest.com/pin/112167846967490473/",
    "imageUrl": "https://i.pinimg.com/originals/82/60/9e/82609efa4694110d07ee9ec0cf77856e.jpg",
    "imageWidth": 1000,
    "imageHeight": 1500,
    "altText": "there are two pictures of a cat on the floor and in front of a bunk bed",
    "dominantColor": "#ab9e8d",
    "boardName": "Best Ikea Hacks",
    "boardUrl": "https://www.pinterest.com/ikeahacker/best-ikea-hacks/",
    "saveCount": 1,
    "repinCount": 0,
    "isVideo": false
}
```

The same Actor with `"scope": "boards"` and `"query": "minimalist home office"`:

```json
{
    "url": "https://www.pinterest.com/greenwithless/minimalist-home-office/",
    "status": "ok",
    "scrapedAt": "2026-09-08T12:48:20.186Z",
    "resultType": "board",
    "pinId": "848084242269709151",
    "searchQuery": "minimalist home office",
    "title": "Minimalist Home Office",
    "description": "Do you like minimalist home office design? On this board, you'll find the best minimalist home office ideas, minimalist home office decor, minimalist home office setup ideas, minimalist desk setup ideas, decluttering ideas for a minimalist home office, and more!",
    "pinUrl": "https://www.pinterest.com/greenwithless/minimalist-home-office/",
    "imageUrl": "https://i.pinimg.com/474x/77/23/b5/7723b511a95d32109589011837e0dfbe.jpg",
    "boardName": "Minimalist Home Office",
    "boardUrl": "https://www.pinterest.com/greenwithless/minimalist-home-office/",
    "pinCount": 29,
    "isVideo": false
}
```

And a profile URL, refused and written as a free row instead of vanishing:

```json
{
    "url": "https://www.pinterest.com/",
    "status": "error",
    "error": "Input entry \"Profile URLs are not supported (this Actor does not collect people): https://www.pinterest.com/ikeahacker/\" is not a URL this Actor can fetch; it was skipped.",
    "scrapedAt": "2026-09-20T19:07:39.672Z"
}
```

### How much does it cost to scrape Pinterest?

Pay per event. You pay for what you actually receive.

| Event | Price | When it is charged |
|---|---|---|
| Actor start | $0.005 | Once per run (per GB of memory; the 1 GB default is one event). |
| Result | $0.00199 | Per saved row with status `ok` — one pin (from a search, a board or a pin URL), or one board when Scope is boards. |

That works out at **$1.99 per 1,000 results**. Rows with status `not_found` or `error` are written to your dataset **free of charge**, and the Actor never bills for a row it could not deliver. Platform compute is included: the two events above are the whole price list. The free Apify plan's $5 of monthly credit covers about 2,500 results in a single run.

### How it compares

This Actor is deliberately focused and cheap: keyword search across pins and boards, the pins of a board, and single pins in detail — all over HTTP in seconds, with no login, no cookie and no browser to pay for. If what you want is a wide sample of what Pinterest surfaces for a topic, with real image URLs, destination links and colour data you can analyse, it is a good fit and it will not cost much.

It is not the tool for creator analytics or influencer discovery: it returns no pinner identity data at all, it does not read profiles, and full engagement counts come only with pin URLs — a search response rarely carries them. It cannot read private boards, it does not download image files, and because Pinterest personalises and localises search, two runs of the same keyword will not return an identical list. If you need per-creator metrics, follower counts or reproducible ranking, look elsewhere.

### Integrations, API and AI agents

Results export to **CSV, JSON, Excel and XML** from the Apify console, or flow straight into **Google Sheets, Airtable, Slack or a CRM** through Apify integrations and webhooks — including Make, Zapier and n8n. Schedule the Actor to re-run a set of keywords weekly and only append what is new.

It can be called from the **Apify API**, from any Apify client library, from the **Apify MCP server**, or by any AI agent that can call an HTTP endpoint. Output is flat JSON with a stable `status` column, so an agent can distinguish "found nothing" from "could not check" without heuristics.

### Tips

- **Use `searchQuery` when you batch.** Put twenty keywords into `queries` and every row still tells you which keyword produced it.
- **Two steps for full counts and MP4s.** Search first, then feed the `pinUrl` values you care about back in as `startUrls`: each comes back with save, repin, share and reaction counts and, for a video pin, the MP4 instead of the HLS playlist. One pin URL is one request and one result.
- **`dominantColor` is the cheap trend signal.** Bucket it by hue and plot against `createdAt` to see a palette shift over months without downloading a single image.
- **`link` is the commercial signal.** Filter to rows where `link` is present to get only pins that actually send traffic somewhere.
- **Raise `maxItems` before you raise concurrency.** One request already returns up to 100 results, so a bigger `maxItems` is nearly free in requests.
- **Set `maxItems` deliberately.** It counts every row, including free `not_found` and `error` rows, so a run always stays bounded.

### Limitations

- **Unofficial endpoints.** This Actor reads the undocumented JSON calls that pinterest.com's own search, board and pin pages make. They are not a published API, they carry no stability guarantee, and Pinterest can change or restrict them at any time. If that happens the Actor fails loudly with `error` rows rather than returning an empty success.
- **No pinner identity, by design.** Usernames, real names, profile URLs, avatars and follower counts are present in the upstream response and are never written to the dataset. If you need creator-level data, this Actor is not the right tool. Note that a `boardUrl` naturally contains the board owner's public handle as its first path segment, because that is how Pinterest builds board URLs.
- **Engagement counts depend on the path.** A pin URL returns saves, repins, comments, shares and reactions. A board listing returns saves and repins. A search response usually carries only `reactionCount`. Treat counts on search rows as a bonus, not as a guarantee; for dependable counts, pass the pin URLs.
- **Video URLs depend on the path too.** A pin URL returns an MP4. Search results and board listings carry only the HLS playlist (`.m3u8`), which players and ffmpeg read but a plain download does not. Video files are referenced, never downloaded.
- **Board listings have no creation date.** Pinterest leaves `createdAt` out of a board's pin list; pass a pin URL when you need it.
- **Board sections and short links are not read.** A section URL (`/<owner>/<board>/<section>/`) and `pin.it` short links are skipped with an explanatory row; use the board URL or the full pin URL. Secret boards are not reachable.
- **Results vary by region and over time.** Pinterest personalises and localises search. The same keyword run from a different country, or an hour later, returns a different and differently ordered set. Row counts and ordering are therefore not reproducible.
- **`description` and `link` are often empty.** Most pins carry neither. In a typical 100-pin sample roughly a third have a description and under a fifth have an outbound link. `title` falls back to Pinterest's alt text and is present on almost every row.
- **A pins search almost never returns nothing.** For an unmatched keyword Pinterest quietly serves loosely related pins instead of an empty result, so a `not_found` row is rare in `pins` scope. A boards search does return a genuinely empty result set, and that becomes one `not_found` row.
- **Images are referenced, never downloaded.** You get `imageUrl`; fetching or storing the image itself is your decision and your responsibility.
- **Datacenter IPs are untested at scale.** The endpoint was verified working without a proxy, but Pinterest may treat cloud IP ranges differently from a home connection. If you see HTTP 403 or 429 the run will fail visibly — switch on Apify Proxy (datacenter) in the input and retry.

### FAQ

**Is it legal to scrape Pinterest?** This Actor reads only publicly visible search results, without logging in and without defeating any access control. Whether a particular collection and use is lawful depends on your jurisdiction, your purpose and Pinterest's terms of service, which you are responsible for reading. Get your own legal advice before running this at scale or for a commercial product.

**Do I need a Pinterest account, an API key or a proxy?** None of the three. The Actor reads a public search response over plain HTTP from Apify's datacenter IPs. Apify Proxy is available in the input but is off by default and is only worth enabling if you start seeing 403 or 429 responses.

**Can I scrape Pinterest boards as well as pins?** Yes, in two ways. To *find* boards about a topic, set **Scope** to `Boards` and each row becomes a board: `title` is the board name, `pinCount` is how many pins it holds, and `pinUrl` links to it. To get the *pins of a board*, paste the board URL into `startUrls`.

**Can I get the video of a video pin?** Yes. `videoUrl` holds the best URL Pinterest publishes: an MP4 when you pass the pin URL, the HLS playlist on search and board rows. The Actor never downloads the file.

**Can I search several keywords at once?** Yes. Put them into `queries`, one per line. `maxItems` is shared evenly between them unless you set `maxItemsPerQuery`.

**How many pins can I get in one run?** As many as `maxItems` allows. One request to Pinterest returns 25-100 results, so even a 1,000-row run is only 10-40 requests and finishes in well under a minute.

**Why did I get fewer rows than `maxItems`?** Either the search genuinely ran out of results, or `maxItems` counts rows of every status — a couple of free `error` rows for unusable input entries reduce the number of `ok` rows in the same run. The final log line reports the exact breakdown.

**What if a field is missing?** Missing means Pinterest did not publish it for that result. Fields are omitted rather than filled with empty strings or zeros, so a missing `link` means "this pin points nowhere", not "the scraper failed". Only `error` rows indicate a failure.

**Can I search for people, or scrape a profile?** No. Board search is supported through the Scope input and a single board can be read by its URL; people search and profile pages are deliberately not, and `/search/users/` and profile URLs are rejected with an explanatory row. This Actor is for content, not for profiling individuals.

**Does it download the images?** No. It gives you `imageUrl`, `imageWidth` and `imageHeight`. No image file is copied, cached or re-hosted by the Actor.

**Can I use it from an AI agent or an MCP client?** Yes. Call it through the Apify API or the Apify MCP server like any other Actor; the flat JSON rows and the `status` column are designed for exactly that.

### Legal and data-protection notice

This Actor collects only publicly accessible content from Pinterest search results, public boards and public pins. It does not log in, does not access private boards, and does not attempt to defeat any technical access restriction.

Pinterest content is user-generated, which means personal data can appear inside it. This Actor is built to avoid that: pinner usernames, full names, profile URLs, profile images and follower counts are present in the upstream response and are **deliberately excluded** from every dataset row. Board names and board URLs are retained as content metadata, and a board URL includes the owner's public handle because that is part of the URL Pinterest publishes. Images and videos are referenced by URL only; no media file is copied or stored by the Actor.

If your dataset nevertheless ends up containing personal data — for example a person's name written into a pin title, a description or a board name by the person who posted it — you are the data controller for that processing under the GDPR, the CCPA and comparable laws. You are responsible for having a lawful basis, for honouring data-subject requests, and for deleting data you no longer need. Do not use this Actor to build profiles of individuals.

Pinterest is a trademark of its respective owner. This Actor is an independent, unofficial tool and is not affiliated with, authorised by or endorsed by Pinterest.

# Changelog

This Actor's version history is a separate document: https://apify.com/glasswing/pinterest-scraper/changelog.md

# Actor input Schema

## `startUrls` (type: `array`):

Pinterest pages to scrape, one per line. Three kinds are accepted. A search page, for example https://www.pinterest.com/search/pins/?q=coffee , returns the results of that search. A board, https://www.pinterest.com/<owner>/<board>/ , returns the pins saved on that board. A single pin, https://www.pinterest.com/pin/<id>/ , returns one detailed row with engagement counts and, for a video pin, the video URL. Country domains (pinterest.co.uk, pinterest.de, ...) work too, and a bare keyword such as `coffee` is accepted as a shortcut. Profile URLs and `/search/users/` are refused on purpose, each with one free explanatory row, because this Actor does not collect people.

## `query` (type: `string`):

One keyword to search for, exactly as you would type it into the Pinterest search box (for example `minimalist home office`). Searched at the Scope selected below. Can be combined with the URLs above: it simply adds one more search. To search several keywords in one run, use Keywords instead.

## `queries` (type: `array`):

Several keywords in one run, one per line (for example `cold brew`, `matcha latte`, `espresso bar`). Each keyword is searched at the Scope selected below, and every row says which keyword found it in `searchQuery`. Maximum results is shared evenly between the searches unless you set Maximum results per search. When Keywords are given and the URL field still holds only the built-in coffee example, the example is skipped.

## `scope` (type: `string`):

What a keyword search should return: individual pins, or the boards that match the keyword. Applies to the Search keyword, to Keywords, and to any search URL that does not name a scope itself. Board and pin URLs are not affected.

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

Stop after this many rows have been saved to the dataset, across all keywords and URLs. Each saved row with status `ok` is one billable result. One request to Pinterest returns 25-100 results, so small runs finish in seconds.

## `maxItemsPerQuery` (type: `integer`):

Optional. The most rows any one keyword, search URL or board may add to the dataset. Leave empty to let a single search or board use everything up to Maximum results; with Keywords, leaving it empty shares Maximum results evenly between the searches.

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

Optional and off by default. The Actor is HTTP-only and needs no proxy from a normal IP. If Pinterest starts answering 403 or 429, enable Apify Proxy (the datacenter group is the default); residential proxies are not required and not recommended for this Actor.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.pinterest.com/search/pins/?q=coffee"
  ],
  "scope": "pins",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        "https://www.pinterest.com/search/pins/?q=coffee"
    ],
    "scope": "pins",
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("glasswing/pinterest-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "startUrls": ["https://www.pinterest.com/search/pins/?q=coffee"],
    "scope": "pins",
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("glasswing/pinterest-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    "https://www.pinterest.com/search/pins/?q=coffee"
  ],
  "scope": "pins",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call glasswing/pinterest-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,glasswing/pinterest-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/abIfDLaAfODTJjsit/builds/0puQ8xg05KuiB8LRF/openapi.json
