Skip to content

bstoilov/py3-pinterest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

93 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Pinterest

py3-pinterest

The most complete unofficial Pinterest API client for Python

PyPI Β  Python Β  License Β  Stars


πŸ“Œ Pin Β· πŸ“€ Upload Images & Videos Β· πŸ“‹ Manage Boards Β· πŸ‘₯ Follow Β· πŸ” Search Β· πŸ’¬ Comment & Message

No API key needed. Works by mimicking browser requests to Pinterest's internal endpoints.


πŸš€ What's New in v2.0.0

The comeback release. Nearly every core feature has been fixed, modernized, or rewritten.

Highlight
🎬 Video pin uploads β€” full Story Pin / Idea Pin support via S3 upload flow
πŸ–ΌοΈ Image uploads rewritten β€” old broken /upload-image/ replaced with working S3 flow
πŸ“„ Pagination fixed β€” reset_bookmark bug fixed across all 12 paginated methods
πŸ” Login hardened β€” cookie banner handling, language-independent selectors, proper cleanup
πŸ—‘οΈ Board deletion β€” new delete_board() method
πŸ“‚ Board sections β€” now supports page_size (up to 100, was hardcoded to 25)
πŸ›‘οΈ No more data loss β€” Registry no longer rmtree's your directories on init
πŸ“¦ Dependency pins β€” selenium>=4.0.0, webdriver-manager>=4.0.0
πŸ“‹ Full list of resolved issues (click to expand)
Issue Description Status
#220 Video upload not supported βœ… Fixed
#219 Login β€” element not interactable (cookie banner) βœ… Fixed
#218 Error in search (pin & board) βœ… Fixed
#217 403 Forbidden β€” _ngjs URL prefix βœ… Fixed
#213 Search page size & pagination βœ… Fixed
#209 pin() unexpected keyword image_path βœ… Fixed
#208 load_pin KeyError v3GetPinQuery βœ… Fixed
#207 404 on PinResource/create βœ… Fixed
#205 load_pin β€” __PWS_DATA__ / props error βœ… Fixed
#204 401 Unauthorized on /upload-image/ βœ… Fixed
#203 get_user_pins stops short on large accounts βœ… Fixed
#202 Timeout <object> error (selenium 3 + urllib3 2) βœ… Fixed
#200 Downstream extruct issue βœ… N/A (dependency removed)
#195 Login error β€” ChromeDriver URL change βœ… Fixed
#193 Login fails for non-English locales βœ… Fixed
#191 ChromeDriver download 404 βœ… Fixed
#188 404 on PinResource/create βœ… Fixed
#187 get_board_sections limited to 25 βœ… Fixed
#184 Bad request β€” can't create pins βœ… Fixed
#181 403 Forbidden on PinResource/create βœ… Fixed
#178 Can't upload a new pin βœ… Fixed
#176 Issue creating pins βœ… Fixed
#175 Can't post a new pin βœ… Fixed
#174 Pinning fails with HTML output βœ… Fixed
#156 Credentials not storing βœ… Fixed
#148 Facing problem with pinning image βœ… Fixed
#147 How to create video pins? βœ… Fixed
#139 data/ directory automatic removal βœ… Fixed
#138 KeyError resources in load_pin βœ… Fixed
#137 Pin from local file not working βœ… Fixed
#136 Pin and delete function not working βœ… Fixed
#130 Story pin creation βœ… Fixed
#108 Login broken (API updates) βœ… Fixed

πŸ“¦ Installation

pip install py3-pinterest

Requirements: Python 3.8+ Β Β·Β  Google Chrome (for login only)


⚑ Quick Start

from py3pin.Pinterest import Pinterest

pinterest = Pinterest(
    email='you@email.com',
    password='your_password',
    username='your_username',
    cred_root='cred_root'       # cookies stored here, created automatically
)

# Login once β€” cookies are saved and reused automatically (~15 days)
pinterest.login()

# Pin an image
pinterest.pin(
    board_id='123456789',
    image_url='https://example.com/image.jpg',
    title='My Pin',
    description='Pinned with py3-pinterest'
)

🎬 Upload Pins

Image from local file

pinterest.upload_pin(
    board_id='123456789',
    image_file='photo.jpg',
    title='My Pin',
    description='Uploaded with py3-pinterest',
    link='https://example.com'
)

Video pin ✨

pinterest.upload_video_pin(
    board_id='123456789',
    video_file='video.mov',
    title='My Video Pin',
    description='Video uploaded with py3-pinterest',
    link='https://example.com'
)

πŸ’‘ Requires ffmpeg and ffprobe on PATH. Or provide duration_ms, width, height, and cover_image_file manually to skip the dependency.

Pin from URL

pinterest.pin(
    board_id='123456789',
    image_url='https://example.com/image.jpg',
    title='Pin Title',
    description='Pin description'
)

Repin

pinterest.repin(board_id='board_id', pin_id='pin_id')

πŸ“Œ Pin Management

pinterest.load_pin(pin_id='pin_id')         # Get full pin data
pinterest.delete_pin(pin_id='pin_id')        # Delete a pin
pinterest.get_pinnable_images(url='...')      # Get pinnable images from any website

πŸ“‹ Boards

# List boards
boards = pinterest.boards(username='someone')          # One page
boards = pinterest.boards_all(username='someone')       # All boards

# Create & delete
pinterest.create_board(name='My Board', description='A new board')
pinterest.delete_board(board_id='board_id')

# Board feed β€” all pins in a board
pins = pinterest.board_feed(board_id='board_id', reset_bookmark=True)

# Recommendations ("More ideas")
recs = pinterest.board_recommendations(board_id='board_id', reset_bookmark=True)

Board Sections

pinterest.create_board_section(board_id='board_id', section_name='My Section')
pinterest.delete_board_section(section_id='section_id')
pinterest.get_board_sections(board_id='board_id')       # Supports page_size up to 100
pinterest.get_section_pins(section_id='section_id')

# Pin directly to a section
pinterest.pin(board_id='board_id', section_id='section_id', image_url='...')
pinterest.upload_pin(board_id='board_id', section_id='section_id', image_file='...')

πŸ‘€ Users

pinterest.get_user_overview(username='someone')
pinterest.get_user_pins(username='someone', reset_bookmark=True)

πŸ‘₯ Follow / Unfollow

# Users
pinterest.follow_user(user_id='user_id')
pinterest.unfollow_user(user_id='user_id')

# Boards
pinterest.follow_board(board_id='board_id')
pinterest.unfollow_board(board_id='board_id')

# Get following & followers (batched)
following = pinterest.get_following(username='someone', reset_bookmark=True)
followers = pinterest.get_user_followers(username='someone', reset_bookmark=True)

# Get all at once
all_following = pinterest.get_following_all(username='someone')
all_followers = pinterest.get_user_followers_all(username='someone')

πŸ” Search

# Scopes: pins, buyable_pins, my_pins, videos, boards
results = pinterest.search(scope='pins', query='home decor', reset_bookmark=True)

Visual Search

pin_data = pinterest.load_pin(pin_id='pin_id')
results = pinterest.visual_search(pin_data, x=10, y=50, w=100, h=100)

Type-ahead

pinterest.type_ahead(term='apple')

πŸ’¬ Comments

pinterest.comment(pin_id='pin_id', text='Nice pin!')
pinterest.delete_comment(pin_id='pin_id', comment_id='comment_id')
pinterest.get_comments(pin_id='pin_id', reset_bookmark=True)

βœ‰οΈ Messages

conversations = pinterest.get_conversations()
messages = pinterest.load_conversation(conversation_id='conv_id')

# Send text, pin, or both
pinterest.send_message(conversation_id='conv_id', message='Hey!')
pinterest.send_message(conversation_id='conv_id', pin_id='pin_id')
pinterest.send_message(conversation_id='conv_id', pin_id='pin_id', message='Check this out')

🏠 Home Feed

pins = pinterest.home_feed(reset_bookmark=True)

πŸ“– Pagination

Most list methods are batched β€” they return one page per call. Loop until empty:

all_pins = []
batch = pinterest.board_feed(board_id='board_id', reset_bookmark=True)
while batch:
    all_pins += batch
    batch = pinterest.board_feed(board_id='board_id')

print(f'Total: {len(all_pins)} pins')

Always pass reset_bookmark=True on the first call to start fresh.


🌐 Proxy Support

proxies = {"http": "http://user:pass@proxy_ip:port"}
pinterest = Pinterest(
    email='...', password='...', username='...',
    cred_root='cred_root', proxies=proxies
)

pinterest.login(proxy='ip:port')

πŸ” Login & Session

pinterest.login()                           # Headless Chrome
pinterest.login(headless=False)             # Visible browser (for debugging)
pinterest.login(proxy='ip:port')            # Through a proxy
pinterest.login(lang='en')                  # Set browser language
pinterest.logout()

Cookies persist to disk and are reused across runs. Re-login when you start seeing 401/403 errors (~every 15 days).


🧩 Working with Responses

All methods return the raw Pinterest response:

resp = pinterest.upload_pin(board_id='...', image_file='photo.jpg', title='Test')
data = resp.json()

pin_id = data["resource_response"]["data"]["id"]
board_id = data["resource_response"]["data"]["board"]["id"]

πŸ“‚ Examples

Full working examples in the Examples/ directory:

File Description
examples.py πŸ—‚οΈ Comprehensive overview of all features
upload_examples.py πŸ“€ Image and video upload
board_sections_example.py πŸ“‚ Board sections and section pins
download_board_images.py ⬇️ Download all images from boards
follow_examples.py πŸ‘₯ Search, follow users and boards
mass_board_invites.py πŸ“¨ Bulk board invites from search
messages_example.py βœ‰οΈ Conversations and messaging
get_board_followers.py πŸ‘€ Get board followers

🀝 Contributing

Found a bug or want to add a feature? Open an issue or submit a PR.

Thanks to all contributors: @alglez, @anonymustard, @Ashad001, @bahrmichaelj, @CapofWeird, @edersonff, @elmissouri16, @erenalpt, @evezus, @fratamico, @Gmanicus, @imgVOID, @kruvatz, @magicaltoast, @marcosfelt, @mfhassan22, @Nviard, @RKuttruff, @VeemPees, @victorviro, @vladradishevsky, @vriadlee, @vtni, @yaonur

πŸ“š Community Guides


MIT License · Made with ❀️ by @bstoilov