---
title: "Pinterest Downloader API — Pin Images & Videos | FastSaverAPI"
url: https://fastsaverapi.com/pinterest-downloader-api/
description: "Pinterest downloader API: turn a pin.it or /pin/ link into the stored image or MP4, its pixel dimensions and caption. Idea pins arrive as an items array."
updated: 2026-08-10
api_base: https://api.fastsaver.io/v1
site_index: https://fastsaverapi.com/llms.txt
openapi: https://fastsaverapi.com/openapi.json
---

# Pinterest downloader API for images, videos and idea pins

Resolve any public Pinterest pin — image, video or multi-page idea pin — with one GET
request to the Pinterest downloader API. You get the stored file rather than the grid thumbnail,
plus dimensions, duration and the description, for 1.5 credits.
Instagram, TikTok, X, Facebook and RuTube answer on the same endpoint.

- **Endpoint**: GET /fetch

- **Credits**: 1.5 per pin

- **Auth**: X-Api-Key header

- **Media**: image pins, video pins, idea pins

## what a pin resolves to

Pinterest runs through the same universal endpoint as the other non-YouTube platforms. Hand it
a pin URL; it works out what the pin contains and answers with JSON.

- Image pins — the stored file plus its pixel dimensions and the pin description.
- Video pins — an MP4 with duration , and a poster frame in thumbnail_url .
- Idea pins and carousels — multi-page pins arrive as type: "album" with an items array, one entry per page.
- GIF-style pins — Pinterest stores most of these as video, so expect type: "video" .

Three link shapes work: the canonical /pin/<id>/ permalink, a
pin.it short link from the mobile share sheet, and localised hosts such as
ru.pinterest.com . Query strings are ignored, so the tracking noise the app appends
is harmless.

## one request, one pin

A GET with the pin in the url parameter and your key in a header. Nothing else.

GET
https://api.fastsaver.io/v1/fetch
1.5 credits



```
curl -G "https://api.fastsaver.io/v1/fetch" \
  --data-urlencode "url=https://pin.it/4kQvXcL9r" \
  -H "X-Api-Key: fs_sk_•••••••••••"
```



```
{
  "ok": true,
  "id": "1125968838649261847",
  "source": "pinterest.com",
  "type": "video",
  "download_url": "https://v1.pinimg.com/videos/mc/720p/...",
  "thumbnail_url": "https://i.pinimg.com/originals/...",
  "width": 720,
  "height": 1280,
  "duration": 21,
  "caption": "Walnut desk build — three-hour timelapse."
}
```


--data-urlencode instead of gluing the link into the query string is a habit worth
keeping: pin links carry their own parameters, and an unencoded & silently
truncates the URL your server receives.

An image pin is the same envelope with duration null:



```
{
  "ok": true,
  "id": "60446345121012345",
  "source": "pinterest.com",
  "type": "image",
  "download_url": "https://i.pinimg.com/originals/2f/8c/1d/....jpg",
  "thumbnail_url": "https://i.pinimg.com/236x/2f/8c/1d/....jpg",
  "width": 1536,
  "height": 2048,
  "duration": null,
  "caption": "Muted terracotta kitchen, brass fittings."
}
```

A multi-page idea pin, and a carousel pin, use a different envelope. There is no top-level
download_url , width or height — the pages live in an
items array instead, and each entry carries its own type ,
download_url , thumbnail_url , width and
height :



```
{
  "ok": true,
  "id": "3096293941226352",
  "source": "pinterest.com",
  "type": "album",
  "items": [
    {
      "type": "image",
      "download_url": "https://i.pinimg.com/originals/a1/4e/90/....jpg",
      "thumbnail_url": "https://i.pinimg.com/originals/a1/4e/90/....jpg",
      "width": null,
      "height": null
    },
    {
      "type": "video",
      "download_url": "https://v1.pinimg.com/videos/mc/720p/...",
      "thumbnail_url": "https://i.pinimg.com/originals/b7/22/05/....jpg",
      "width": 720,
      "height": 1280
    }
  ],
  "thumbnail_url": "https://i.pinimg.com/originals/a1/4e/90/....jpg",
  "duration": null,
  "caption": "Five-step gouache landscape."
}
```

Two details worth coding around. Image items report width and height as
null — Pinterest does not publish per-page dimensions for them, so probe the file if you need
them. And a one-page idea pin collapses to a plain image or video
response rather than an album, so a branch that only handles "album" will miss it.

## the original file versus what the feed shows you

Compare the two URLs in that image response. The thumbnail sits under a 236x path
segment; the download sits under originals . Pinterest stores several derivatives of
every upload and the browse grid serves the small ones — which is why right-clicking a pin in a
feed hands you a 236-pixel-wide JPEG that looks fine as a thumbnail and terrible anywhere else.

download_url points at the stored file, and width and
height tell you what you are about to fetch. Read them: "original" means original
upload , and a pin re-pinned from a compressed screenshot stays compressed. If you promise
print-quality assets, gate on those dimensions.

## saving a list of pins

Two shapes. The throwaway one — resolve, then pipe the bytes to disk:



```
curl -sG "https://api.fastsaver.io/v1/fetch" \
  --data-urlencode "url=https://www.pinterest.com/pin/1125968838649261847/" \
  -H "X-Api-Key: fs_sk_•••••••••••" \
| jq -r '.download_url' \
| xargs -r curl -sL -o pin.mp4
```

And the one you would deploy: a loop over a file of links, naming each output after the pin id
so re-runs are idempotent and your storage keys stay stable. Note the album branch — reading
download_url on an idea pin raises KeyError , because that key is only
on single-media responses.



```
import pathlib, time, requests

KEY = "fs_sk_•••••••••••"
OUT = pathlib.Path("moodboard")
OUT.mkdir(exist_ok=True)

def write(name, media):
    dest = OUT / (name + (".mp4" if media["type"] == "video" else ".jpg"))
    dest.write_bytes(requests.get(media["download_url"], timeout=120).content)
    return dest

def save_pin(link):
    r = requests.get(
        "https://api.fastsaver.io/v1/fetch",
        params={"url": link},
        headers={"X-Api-Key": KEY},
        timeout=60,
    )
    data = r.json()
    if not data.get("ok"):
        print("skipped", link, data.get("detail"))
        return []
    if data["type"] == "album":                 # idea pin or carousel: one file per page
        return [write(data["id"] + "-" + str(i), item)
                for i, item in enumerate(data["items"])]
    return [write(data["id"], data)]            # image or video pin

for link in pathlib.Path("pins.txt").read_text().split():
    print(save_pin(link))
    time.sleep(1)          # stay inside your plan's per-minute limit
```

The sleep is not decoration. Ten requests per minute on the free tier disappears
fast during a backfill, and a 429 costs a retry you could have avoided.

## what people build with it

Pinterest traffic here skews towards ingest rather than one-off downloads: something else
produced the link, and a job has to turn it into a file.

### Moodboard tools

product
A user pastes a pin; you store the file and its dimensions and lay out a real grid instead of hotlinking someone else's CDN.

### Design archives

internal
References that outlive the pin. Pins get deleted; your own copy, with the caption attached, does not.

### Content pipelines

automation
A worker pulls a link off a queue, gets JSON, pushes the file to object storage. No headless browser in the loop.

## what Pinterest keeps out of reach

- Public pins only. Secret boards, and anything that asks you to log in, will not resolve.
- One pin per call. No board, profile or search endpoint — you supply the links.
- CDN URLs expire. Treat download_url as single-use: fetch the bytes in the same job, never store the link.
- No dimensions inside an album. Idea-pin and carousel image items report width and height as null; only single-media responses carry real numbers.
- Pacing is per plan. Free allows 10 requests a minute, Mega 900. A 429 says slow down, not that the pin is bad.
- Pins disappear , and Pinterest changes its markup. We fix resolution behind the endpoint; a deleted pin nobody can fix.

One more, and it is not a technicality: almost nothing on Pinterest was made by the account that
pinned it. Downloading a file grants you no licence to republish it. Attribution, permission and
copyright are yours to sort out.

## questions about the Pinterest API

**Q: Does it work with pin.it short links?**

A: Yes. Pass the pin.it link exactly as the share sheet gave it to you — the redirect is followed server-side. No need to resolve it first, and no need to strip the tracking parameters the app appends.

**Q: Can I download Pinterest video pins and idea pins?**

A: Yes. A video pin returns an MP4 in download_url with duration set. A multi-page idea pin comes back as type: "album" carrying an items array — one entry per page, each with its own type , download_url , thumbnail_url , width and height . An album has no top-level download_url , so branch on type before you read one.

**Q: What image resolution does the Pinterest API return?**

A: The stored file, not the grid thumbnail you see while browsing. Read width and height rather than assuming: the ceiling is whatever the pinner uploaded, and plenty of pins were re-pinned from an already-compressed copy.

**Q: How many credits does one Pinterest request cost?**

A: 1.5 credits, image or video, the same as TikTok, X and Facebook. The free tier's 1,000 credits cover roughly 660 pins — enough to test an ingest pipeline before you pick a plan.

**Q: Can I pass a board URL or a profile instead of a single pin?**

A: No. The endpoint resolves one pin per call. For a board, collect its pin URLs yourself and loop, with a delay that keeps you under your plan's per-minute limit. Secret boards need a login and are out of scope.

## Keep reading

- All supported platforms — nine references
- X (Twitter) video API — same endpoint, same price
- Instagram downloader API — posts, reels, stories
- General FAQ — keys, credits, legality

## Resolve a pin in the playground

Paste any public pin link, hit send, and read the JSON before you commit to an integration.

Open the playground
Get a free API key
