Skip to main content

pinterest-downloader

Unofficial Python library to download and interact with Pinterest content — pins, videos, GIFs, profiles, and boards — without an API key.

PyPI Python License: MIT


Features

Feature Methods
🔎 Search pins & videos (paginated + bookmark) search, search_all
📁 Search boards by keyword search_boards
📌 Fetch single pin (image / video / GIF) with full metadata get_pin
🗂️ Board feeds (all pins on a board) get_board_pins
👤 User pins get_user_pins
👤 User profiles (followers, bio, counts, …) get_profile
📁 Board metadata + list of user boards get_board, get_boards
⬇️ Download pin media or entire board to disk download_pin, download_board
🛡️ Graceful errors — every method returns {"ok": …} (no exceptions raised by the library)
🚀 No API key required — works with public Pinterest data

Supported URL formats for pins:

  • Full URL: https://www.pinterest.com/pin/123456789012345678/
  • With or without trailing slash / query parameters
  • Short links: https://pin.it/xxxxx
  • Numeric pin ID only: "123456789012345678"

Supported media types: image, video (MP4 + HLS), GIF.


Requirements

  • Python ≥ 3.8
  • Dependencies (installed automatically):
    • requests >= 2.25.0
    • beautifulsoup4 >= 4.10.0

Installation

pip install pinterest-downloader

Or from source:

git clone https://github.com/x7007x/PinterestDownloader.git
cd PinterestDownloader
pip install -e .

Quick Start

from pinterest_downloader import Pinterest

p = Pinterest()

# --- Get a pin (image / video / GIF) ---
result = p.get_pin("https://www.pinterest.com/pin/1098174690415756357/")
# also works with: "https://pin.it/xxxxx"  or  "1098174690415756357"

if result["ok"]:
    pin = result["pin"]
    print(pin["id"], pin["media_type"])          # e.g. "image", "video", "gif"
    print(pin["images"]["orig"]["url"])          # original image URL
    if pin.get("video"):
        print(pin["video"]["formats"])           # list of MP4 / HLS variants

# --- Download media to disk ---
dl = p.download_pin("1098174690415756357", path="./downloads")
if dl["ok"]:
    print("Saved:", dl["path"], dl["media_type"])

# --- Search ---
search = p.search("cute cats", page_size=10)
if search["ok"]:
    for pin in search["pins"]:
        print(pin["id"], pin["media_type"], pin.get("title"))

# --- Profile & boards ---
profile = p.get_profile("pinterest")
board   = p.get_board("https://www.pinterest.com/pinterest/dream-dorm-room-inspo/")

All methods return a dictionary with an "ok" key:

  • "ok": True → success payload
  • "ok": False"error": {"message": "…"}

The library never raises exceptions for expected failures (invalid URL, missing pin, HTTP errors, etc.).


API Reference

Constructor

Pinterest(headers=None, timeout=30, proxies=None)
Parameter Type Default Description
headers dict None Extra HTTP headers merged into the session
timeout int/float 30 Request timeout in seconds
proxies dict None Proxies passed to requests (e.g. {"https": "http://…"})

A modern Chrome User-Agent is used by default.


get_pin(url_or_id)

Fetch full metadata for a single pin.

Accepts: full pin URL, pin.it short link, or numeric pin ID.

Success response (simplified):

{
    "ok": True,
    "pin": {
        "id": "1098174690415756357",
        "title": "...",
        "description": "...",
        "url": "https://www.pinterest.com/pin/1098174690415756357/",
        "external_link": "https://...",
        "media_type": "image" | "video" | "gif",
        "images": {
            "orig":  {"url": "https://i.pinimg.com/originals/...", "width": 1080, "height": 1920},
            "736x":  {"url": "...", "width": 736, "height": 1308},
            "474x":  {"url": "...", "width": 474, "height": 842},
            # ... other sizes (236x, 170x, 60x60, …)
        },
        "video": {                          # only when media_type == "video"
            "formats": [
                {"url": "https://v1.pinimg.com/..._720w.mp4", "quality": "V_720P", ...},
                {"url": "https://...m3u8", "quality": "V_HLSV4", ...},
            ],
            "mp4_available": True,
            "poster": "https://i.pinimg.com/..."
        },
        "created_at": "Mon, 17 Aug 2026 17:47:49 +0000",
        "author": {
            "id": "...",
            "username": "...",
            "full_name": "...",
            "image_url": "..."
        },
        "board": {
            "id": "...",
            "name": "...",
            "url": "https://www.pinterest.com/user/board/"
        },
        "engagement": {...},
        "source": {...},                    # when available
        "attribution": {...},               # when available
        "embed": {...}                      # when available
    },
    "media": {
        "type": "image",
        "url": "https://i.pinimg.com/originals/...",
        "video_formats": [...],             # when video
        "poster": "..."
    },
    "author": {...},
    "board": {...},
    "engagement": {...}
}

Error example:

{"ok": False, "error": {"message": "Cannot extract pin ID from URL"}}
# or
{"ok": False, "error": {"message": "HTTP 404"}}

download_pin(url_or_id, path=".")

Download the highest-quality media of a pin to disk.

  • Images / GIFs → original resolution
  • Videos → highest-quality MP4 when available, otherwise poster image
  • File is named <pin_id>.<ext>

Success response:

{
    "ok": True,
    "path": "./1098174690415756357.jpg",
    "filename": "1098174690415756357.jpg",
    "url": "https://i.pinimg.com/originals/...",
    "media_type": "image"
}

download_board(url_or_id, path=".", limit=None)

Download media for every pin on a board (walks all pages).
Pass limit to stop after N successful downloads.

Success response:

{
    "ok": True,
    "board": {"id": "...", "name": "..."},
    "downloaded": 25,
    "failed": 0,
    "total_pins": 25,
    "files": ["./123.jpg", "./456.mp4", ...]
}

search(query, page_size=25, bookmark=None, scope="pins")

Paginated keyword search.

result = p.search("cute cats", page_size=10)
# result["pins"]  → list of pin objects (same shape as get_pin["pin"])
# result["bookmark"] → pass to the next call for page 2

search_all(query, max_pages=5)

Convenience wrapper that walks up to max_pages pages and returns all pins.

result = p.search_all("mountain landscape", max_pages=2)
# result["pins"] → combined list

search_boards(query, page_size=25, bookmark=None)

Search public boards by keyword.

result = p.search_boards("interior design", page_size=10)
# result["boards"] → list of board summaries

get_profile(identifier)

Accepts: username, profile URL, or user ID.

{
    "ok": True,
    "profile": {
        "id": "...",
        "username": "pinterest",
        "full_name": "...",
        "bio": "...",
        "follower_count": 6259592,
        "following_count": ...,
        "pin_count": ...,
        "board_count": ...,
        "image_url": "...",
        ...
    },
    "boards": [ ... ]   # summary list of the user’s boards
}

get_boards(identifier)

Full detailed list of boards belonging to a user.

{
    "ok": True,
    "username": "pinterest",
    "boards": [
        {
            "id": "...",
            "name": "...",
            "description": "...",
            "privacy": "public",
            "pin_count": 463,
            "cover_url": "...",
            "board_url": "https://www.pinterest.com/username/board-name/",
            "owner": {"id": "...", "username": "..."}
        },
        ...
    ]
}

get_board(url)

Retrieve a specific board (URL required) plus the owner’s full board list.

{
    "ok": True,
    "board": {
        "id": "...",
        "name": "Dream dorm room inspo",
        "pin_count": 84,
        "follower_count": ...,
        "cover_url": "...",
        "board_url": "...",
        ...
    },
    "user": {"username": "...", "id": "...", "full_name": "..."},
    "boards": [ ... ]   # all boards of the same user
}

get_board_pins(url_or_id, page_size=25, bookmark=None)

Paginated list of pins belonging to a board.

result = p.get_board_pins("https://www.pinterest.com/pinterest/dream-dorm-room-inspo/", page_size=25)
# result["pins"], result["bookmark"]

get_user_pins(username, page_size=25, bookmark=None)

Paginated list of pins created by a user.

result = p.get_user_pins("pinterest", page_size=10)

Error Handling

Every public method returns a dict. Always check "ok":

result = p.get_pin("https://example.com/not-a-pin")
if not result["ok"]:
    print(result["error"]["message"])
    # → "Cannot extract pin ID from URL"

Common error messages:

Situation Typical message
Non-pin / malformed URL Cannot extract pin ID from URL
Pin / resource not found HTTP 404
Network / timeout underlying requests message
No downloadable media No downloadable media for this pin

The library itself does not raise exceptions for these cases.


Examples

Download every image from a search

from pinterest_downloader import Pinterest
import os

p = Pinterest(timeout=40)
os.makedirs("cats", exist_ok=True)

result = p.search("cute cats", page_size=15)
if result["ok"]:
    for pin in result["pins"]:
        if pin.get("media_type") == "image":
            p.download_pin(pin["id"], path="cats")

Download a whole board (first 20 pins)

p.download_board(
    "https://www.pinterest.com/pinterest/dream-dorm-room-inspo/",
    path="./board_downloads",
    limit=20
)

Resolve short links and videos

r = p.get_pin("https://pin.it/s5n05C0UK")
if r["ok"] and r["pin"]["media_type"] == "video":
    for fmt in r["pin"]["video"]["formats"]:
        print(fmt.get("quality"), fmt.get("url"))

Notes & Limitations

  • Works with public Pinterest content only.
  • Relies on Pinterest’s public resource endpoints; future site changes may require updates.
  • Media URLs (especially videos) may have limited lifetime — download promptly if you need the files offline.
  • Rate limiting / anti-bot behaviour is not aggressively handled; use reasonable delays for large scrapes.
  • Concurrent use of a single Pinterest instance is generally fine for moderate workloads, but creating separate instances is safer for heavy parallelism.

Development

git clone https://github.com/x7007x/PinterestDownloader.git
cd PinterestDownloader
pip install -e .
python3 test_live.py   # live smoke tests (requires network)

License

MIT © Ahmed Negm


Links

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pinterest_downloader-4.2.0.tar.gz (18.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pinterest_downloader-4.2.0-py3-none-any.whl (14.6 kB view details)

Uploaded Python 3

File details

Details for the file pinterest_downloader-4.2.0.tar.gz.

File metadata

  • Download URL: pinterest_downloader-4.2.0.tar.gz
  • Upload date:
  • Size: 18.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pinterest_downloader-4.2.0.tar.gz
Algorithm Hash digest
SHA256 bd74108f2d7ef90f75d58bf3f4759415cd3d6264ff29f0a4ea5325cedf35fc15
MD5 c81b812293588cef8f2d1ac5ac776bd7
BLAKE2b-256 e8f23218cc33d1b1f0f6ef618c00f4569ed9d0f3b7c136f99a0753495c2cbdb7

See more details on using hashes here.

File details

Details for the file pinterest_downloader-4.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pinterest_downloader-4.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 39f40ef87bd20748c247813f509d48476339940e1f4a41d74f4e958f91a378e5
MD5 95db4315fe4938d8244cbb0dbbd94dd2
BLAKE2b-256 ce0d64d2a84daff6dcac390c48917bf0c236aa80111d78e5ab8b51093aec6ed7

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

4.2.0 This release

2 files

4.1.0

2 files

4.0.0

2 files

3.0.0

2 files

2.0.6

2 files

2.0.5

2 files

2.0.4

2 files

2.0.2

2 files

2.0.1

2 files

2.0.0

2 files

1.0.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page