Skip to content

Pinterest API

The TrueScrape Pinterest API exposes 4 public endpoints covering Board and its pins, Pin details and Search pins. Every call is a GET against public, logged-out pages and returns the same unified schema as every other platform here. Calls cost 1 credit each. A cache hit is free, and a failed or empty response is never charged.

Endpoints

EndpointReturnsCreditsCacheableBatchable
/v1/pinterest/boardBoard and its pins1yesyes
/v1/pinterest/pinPin details1yesyes
/v1/pinterest/searchSearch pins1yesyes
/v1/pinterest/user/boardsBoards owned by a user1yesyes

Reference

GET/v1/pinterest/board1 creditcacheablebatchable

Board and its pins

Board metadata plus a page of its pins. Pass the cursor from the previous response to page through the board.

ParameterTypeRequiredDescription
urlstringyesBoard URL, e.g. https://www.pinterest.com/pinterest/spice-up-your-dinner-plans/
cursorstringnoBookmark from the previous response

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns an object with board, items.

Fields
FieldTypePresent
boardobjectalways
board.platform"pinterest"always
board.idstringalways
board.namestring | nullalways
board.urlstring | nullalways
board.descriptionstring | nullalways
board.thumbnailUrlstring | nullalways
board.pinCountnumber | nullalways
board.followerCountnumber | nullalways
board.sectionCountnumber | nullalways
board.ownerHandlestring | nullalways
board.ownerNamestring | nullalways
board.isPrivateboolean | nullalways
board.categorystring | nullalways
board.createdAtstring | nullalways
board.fetchedAtstringalways
itemsPost[]always
curl
curl "$API/v1/pinterest/board?url=8XkPqR2nLvE&cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  url: '8XkPqR2nLvE',
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/pinterest/board?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/pinterest/board",
    params={
        "url": "8XkPqR2nLvE",
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or upstream_rate_limited. Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_blocked / upstream_schema_drift. Not charged
504upstream_timeout. Not charged
Try it here
GET/v1/pinterest/board
Open the full playground
GET/v1/pinterest/pin1 creditcacheablebatchable

Pin details

Public details for a pin: title, description, reactions, comments, shares and full-resolution media. The destination link and save count are in raw.

ParameterTypeRequiredDescription
urlstringyesPin URL, e.g. https://www.pinterest.com/pin/1130122100248990600/

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns one Post.

Fields
FieldTypePresentDescription
platformone of 32 stringsalways
idstringalways
typevideo | short | image | carousel | text | live | story | reel | audio | album | episode | unknownalwaysWhat kind of post this is. `short` and `reel` are short-form video formats, `live` is a live stream or a recording of one, `carousel` holds several images or videos, `audio` is a music track, `album` is an album, `episode` is a podcast episode, and `unknown` covers anything else.
urlstring | nullalways
titlestring | nullalways
textstring | nullalwaysThe post's text: a caption, a description or the message body.
authorIdstring | nullalways
authorHandlestring | nullalways
authorNamestring | nullalways
thumbnailUrlstring | nullalways
mediaUrlsstring[]always
durationSecondsnumber | nullalways
viewCountnumber | nullalwaysViews. Null means the platform did not expose a count, which is not the same as zero.
likeCountnumber | nullalwaysLikes, or the platform's nearest equivalent. Null means not exposed, not zero.
commentCountnumber | nullalwaysComments. Null means not exposed, not zero.
shareCountnumber | nullalwaysShares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero.
hashtagsstring[]alwaysHashtags or the platform's own topic tags, without the leading #.
mentionsstring[]alwaysHandles mentioned in the post text, without the leading @.
taggedUsersstring[]may be absentUsernames tagged in the media itself, as distinct from `mentions`, which come from the caption text. Absent when the platform does not report tags; an empty array means it reports none.
isSponsoredboolean | nullalwaysWhether the platform labels the post as an ad, promoted content or a paid partnership.
publishedAtstring | nullalwaysWhen the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago".
fetchedAtstringalwaysWhen this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch.
curl
curl "$API/v1/pinterest/pin?url=8XkPqR2nLvE&cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  url: '8XkPqR2nLvE',
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/pinterest/pin?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/pinterest/pin",
    params={
        "url": "8XkPqR2nLvE",
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or upstream_rate_limited. Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_blocked / upstream_schema_drift. Not charged
504upstream_timeout. Not charged
Try it here
GET/v1/pinterest/pin
Open the full playground
GET/v1/pinterest/user/boards1 creditcacheablebatchable

Boards owned by a user

Public boards on a profile, most recently pinned-to first, with pin and follower counts.

ParameterTypeRequiredDescription
handlestringyesUsername, e.g. "pinterest"
cursorstringnoBookmark from the previous response

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns a list of object in data.items.

Fields
FieldTypePresent
platform"pinterest"always
idstringalways
namestring | nullalways
urlstring | nullalways
descriptionstring | nullalways
thumbnailUrlstring | nullalways
pinCountnumber | nullalways
followerCountnumber | nullalways
sectionCountnumber | nullalways
ownerHandlestring | nullalways
ownerNamestring | nullalways
isPrivateboolean | nullalways
categorystring | nullalways
createdAtstring | nullalways
fetchedAtstringalways
curl
curl "$API/v1/pinterest/user/boards?handle=%40mkbhd&cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  handle: '@mkbhd',
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/pinterest/user/boards?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/pinterest/user/boards",
    params={
        "handle": "@mkbhd",
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or upstream_rate_limited. Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_blocked / upstream_schema_drift. Not charged
504upstream_timeout. Not charged
Try it here
GET/v1/pinterest/user/boards
Open the full playground

Questions

How much does the Pinterest API cost?
Calls cost 1 credit each. Every endpoint is cacheable, and a cache hit costs nothing. A failed request and an empty result are both free, on every endpoint.
Does the Pinterest API need a login or cookies?
No. Every endpoint reads public, logged-out pages only — no account, no cookies, no session. An API key identifies your own TrueScrape account and nothing else.
Can I fetch many Pinterest targets in one request?
Yes. 4 of 4 are batchable: one POST to /v1/jobs/batch takes many targets and returns a job id to poll.
Can I watch Pinterest endpoints for changes?
Yes, 3 of 4. A subscription polls on your schedule and fires your webhook only when the content changed; the rest carry x-subscribable: false in the spec.