Come Scrapear Pin e Board di Pinterest nel 2026: Guida per Sviluppatori

Guida tecnica per scrapear pin, board e risultati di ricerca pubblici di Pinterest nel 2026: endpoint Resource API, paginazione con bookmark, proxy residenziali rotanti ed etica del scraping.

How to Scrape Pinterest Pins and Boards in 2026: A Developer's Guide

Avvertenza legale ed etica. Questa guida riguarda esclusivamente l'accesso a dati pubblici e non personali di Pinterest (pin, board e risultati di ricerca visibili senza login). Prima di qualsiasi attività di scraping, leggi i Terms of Service di Pinterest, rispetta robots.txt e considera il Computer Fraud and Abuse Act (CFAA) negli Stati Uniti e il GDPR nell'Unione Europea. Non raccogliere dati personali identificabili, non aggirare paywall o login-walls e, per workload di produzione, preferisci l'API ufficiale.

Se devi costruire dataset di contenuti visivi, trend di moda, idee di arredamento o segnali di marketing, scrapear Pinterest nel 2026 è ancora una delle fonti più ricche di intento utente strutturato. Ma Pinterest negli ultimi anni ha indurito i suoi controlli anti-bot: rate limit per IP, bot scoring, localizzazione aggressiva di search e feed. In questa guida spieghiamo come scrapear pin e board di Pinterest nel 2026 usando l'API Resource interna, proxy residenziali rotanti con geo e paginazione bookmark, con snippet Python e Node.js pronti da eseguire sul gateway ProxyHat.

Come scrapear Pinterest pin e board nel 2026: panoramica

Pinterest espone tre superfici pubbliche principali che interessano uno sviluppatore che costruisce un Pinterest scraper:

  • Pin pubblici — ogni pin ha una pagina canonica https://www.pinterest.com/pin/{id}/ accessibile senza login, con titolo, descrizione, immagine e link di destinazione.
  • Board pubblichehttps://www.pinterest.com/{user}/{board_slug}/ mostra un feed di pin visibile a chiunque (le board private richiedono login e non vanno toccate).
  • Risultati di ricercahttps://www.pinterest.com/search/pins/?q={query} restituisce una griglia di pin rilevanti, fortemente localizzata per paese.

Le home feed personalizzate (/home/) sono invece login-walled e contengono raccomandazioni personalizzate basate sull'utente: non sono superfici pubbliche e scrapearle richiede autenticazione, il che le pone fuori dal perimetro etico di questa guida. La Pinterest API v5 ufficiale offre accesso ai propri account (Analytics, Boards, Pins) ma non permette di cercare pin pubblici arbitrari o di leggere board di terzi, e ha rate limit di circa 10 richieste al minuto per endpoint in write mode — troppo limitati per dataset di trend.

Perché il problema esiste: l'API Resource interna di Pinterest

Il frontend React di Pinterest non chiama REST endpoint pubblici documentati: chiama invece un'API interna chiamata Resource API, con URL della forma:

https://www.pinterest.com/resource/{ResourceName}/get/?source_url={encoded_path}&data={encoded_json}

Le risorse più utili per un Pinterest scraper sono:

  • BoardFeedResource — paginazione dei pin di una board.
  • SearchResource — risultati di ricerca per query.
  • PinResource — dettagli di un singolo pin.
  • UserResource / BoardsResource — profilo e board di un utente.

Il parametro data è un oggetto JSON url-encoded che contiene opzioni come board_id, page_size (tipicamente 25), current_bookmark e search_query. La risposta è JSON con un campo resource_response.data (lista di pin) e bookmark per la pagina successiva.

Gli header richiesti includono:

  • X-Pinterest-PWS-Handler — identificatore del controller lato server (es. BoardPageRootDefaultRouteHandler).
  • X-APP-VERSION — versione build del frontend, cambia ogni release (es. 9c3f4a1).
  • csrftoken — cookie CSRF, va mantenuto tra richieste con una sessione sticky.
  • User-Agent realistico e coerente con il fingerprint del browser.

Senza questi header Pinterest risponde con 401 o con una pagina HTML di login invece del JSON atteso.

Anti-bot, rate limit e perché servono proxy residenziali

Pinterest applica controlli su più livelli:

  1. Rate limit per IP — richieste troppo ravvicinate dallo stesso IP ricevono 429 o 403 dopo poche decine di hit.
  2. Bot scoring — combinazione di fingerprint browser, header mancanti, pattern di navigazione lineare (solo endpoint Resource, senza asset).
  3. Localizzazione — search e feed cambiano in base alla geolocalizzazione dell'IP. Una ricerca per "kitchen ideas" da un IP italiano restituisce risultati diversi rispetto a un IP statunitense.

Ecco perché i proxy residenziali rotanti con geo-targeting sono la scelta corretta per il Pinterest API scraping:

  • IP reali ISP riducono il bot score rispetto a IP datacenter (che Pinterest classifica spesso come sospetti).
  • La rotazione per-request distribuisce il carico e tiene sotto il rate limit per IP.
  • Il flag -country-US ti dà risultati coerenti con il mercato statunitense, utile per dataset di trend omogenei.
  • Le sessioni sticky (-session-abc123) mantengono lo stesso IP per un blocco di richieste, indispensabili per conservare csrftoken e bookmark durante la paginazione di una singola board.

Consulta la pagina delle locazioni ProxyHat per la lista completa di paesi supportati.

Setup ProxyHat: gateway HTTP e SOCKS5

ProxyHat espone un gateway unificato. Per lo scraping Pinterest usiamo la porta HTTP 8080:

http://USERNAME:PASSWORD@gate.proxyhat.com:8080

Per SOCKS5 (utile in ambienti Node con agent custom) si usa la porta 1080:

socks5://USERNAME:PASSWORD@gate.proxyhat.com:1080

I flag di geo e sessione vanno nel username:

  • user-country-US — IP statunitensi.
  • user-country-DE-city-berlin — IP di Berlino.
  • user-session-abc123 — sessione sticky per continuità csrftoken.

Consulta la pagina prezzi per i piani residenziali e la documentazione ProxyHat per i dettagli tecnici. Per altri casi d'uso di scraping vedi anche web scraping e SERP tracking.

Snippet 1: Python — BoardFeedResource con paginazione bookmark

Ecco un esempio completo che pagina una board pubblica tramite BoardFeedResource usando ProxyHat come proxy HTTP residenziale con sessione sticky e geo US.

import requests
import json
import time
import urllib.parse

PROXY = "http://user-country-US-session-b1:pass@gate.proxyhat.com:8080"
PROXIES = {"http": PROXY, "https": PROXY}

HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                  "(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
    "Accept": "application/json, text/javascript, */*; q=0.01",
    "Accept-Language": "en-US,en;q=0.9",
    "X-Requested-With": "XMLHttpRequest",
    "X-Pinterest-PWS-Handler": "BoardPageRootDefaultRouteHandler",
    "X-APP-VERSION": "9c3f4a1",
}

BOARD_SLUG = "username/board-slug"
BOARD_ID = "123456789012345678"  # estrai dall'HTML della board

def fetch_page(bookmark=None):
    options = {
        "board_id": BOARD_ID,
        "page_size": 25,
        "current_bookmark": bookmark,
        "is_prefetch": False,
    }
    data_param = urllib.parse.quote(json.dumps({"options": options, "context": {}}))
    source_url = urllib.parse.quote(f"/{BOARD_SLUG}/")
    url = f"https://www.pinterest.com/resource/BoardFeedResource/get/?source_url={source_url}&data={data_param}"
    r = requests.get(url, headers=HEADERS, proxies=PROXIES, timeout=30)
    r.raise_for_status()
    payload = r.json()
    pins = payload.get("resource_response", {}).get("data", [])
    next_bookmark = payload.get("bookmark")
    return pins, next_bookmark

def parse_pin(pin):
    images = pin.get("images", {})
    orig = images.get("orig", {})
    return {
        "id": pin.get("id"),
        "title": pin.get("title") or pin.get("grid_title"),
        "image_url": orig.get("url"),
        "link": pin.get("link"),
    }

def scrape_board(max_pages=10):
    bookmark = None
    collected = []
    for page in range(max_pages):
        pins, bookmark = fetch_page(bookmark)
        if not pins:
            break
        collected.extend(parse_pin(p) for p in pins)
        print(f"page {page+1}: {len(pins)} pins, bookmark={bookmark}")
        if bookmark in (None, "-end-"):
            break
        time.sleep(2.0)  # pacing
    return collected

if __name__ == "__main__":
    data = scrape_board(max_pages=5)
    print(json.dumps(data[:3], indent=2))

Un singolo pin parsato ha questa forma (troncato):

{
  "id": "1234567890",
  "title": "Minimalist kitchen inspo",
  "image_url": "https://i.pinimg.com/originals/ab/cd/ef/abcdef123456.jpg",
  "link": "https://example.com/blog/kitchen"
}

Note chiave: la sessione sticky -session-b1 mantiene lo stesso IP (e quindi lo stesso csrftoken) per tutta la paginazione della board. Il pacing di 2 secondi riduce il rischio di rate limit. Il bookmark è il cursore opaco di Pinterest: va passato tal quale nella richiesta successiva.

Snippets 2: Node.js — SearchResource via gateway HTTP

Per ambienti Node usiamo undici con un ProxyAgent verso il gateway ProxyHat sulla porta 8080.

import { request } from 'undici';
import { ProxyAgent } from 'undici';
import querystring from 'node:querystring';

const proxyUrl = 'http://user-country-US-session-s1:pass@gate.proxyhat.com:8080';
const agent = new ProxyAgent(proxyUrl);

const headers = {
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' +
                '(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
  'Accept': 'application/json, text/javascript, */*; q=0.01',
  'X-Requested-With': 'XMLHttpRequest',
  'X-Pinterest-PWS-Handler': 'SearchPageResourceHandler',
  'X-APP-VERSION': '9c3f4a1',
};

async function searchPins(query, bookmark = null) {
  const options = {
    query,
    page_size: 25,
    current_bookmark: bookmark,
    scope: 'pins',
  };
  const data = encodeURIComponent(JSON.stringify({ options, context: {} }));
  const sourceUrl = encodeURIComponent(`/search/pins/?q=${encodeURIComponent(query)}`);
  const url = `https://www.pinterest.com/resource/SearchResource/get/?source_url=${sourceUrl}&data=${data}`;
  const { statusCode, body } = await request(url, { method: 'GET', headers, dispatcher: agent });
  if (statusCode !== 200) throw new Error(`HTTP ${statusCode}`);
  const payload = await body.json();
  const pins = payload.resource_response?.data ?? [];
  const next = payload.bookmark ?? null;
  return { pins, next };
}

(async () => {
  let bookmark = null;
  for (let i = 0; i < 3; i++) {
    const { pins, next } = await searchPins('scandinavian kitchen', bookmark);
    console.log(`page ${i+1}: ${pins.length} pins`);
    bookmark = next;
    if (!bookmark || bookmark === '-end-') break;
    await new Promise(r => setTimeout(r, 2500));
  }
})();

Snippets 3: curl — singolo pin via PinResource

Per debugging rapido, un one-liner curl via ProxyHat:

curl -x http://user-country-US-session-x1:pass@gate.proxyhat.com:8080 \
  -H 'User-Agent: Mozilla/5.0 ...' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -H 'X-Pinterest-PWS-Handler: PinPageRootDefaultRouteHandler' \
  -H 'X-APP-VERSION: 9c3f4a1' \
  'https://www.pinterest.com/resource/PinResource/get/?source_url=%2Fpin%2F1234567890%2F&data=%7B%22options%22%3A%7B%22id%22%3A%221234567890%22%7D%7D'

Errori comuni e edge case

  • Sessione sticky non mantenuta. Se ruoti IP a ogni richiesta durante la paginazione di una board, il csrftoken cambia e Pinterest restituisce 401. Usa -session-{id} per tutta una board, poi ruota per la board successiva.
  • X-APP-VERSION scaduto. La versione del frontend cambia frequentemente; se ricevi 403 su tutte le richieste, apri la board in un browser, ispeziona gli header e aggiorna il valore.
  • bookmark perso. Il cursore è opaco: non modificarlo, non base64-decodificarlo, passalo tal quale. Se lo perdi, ricomincia da null e accetta duplicati.
  • Geo inconsistente. Se mescoli IP US e IT nello stesso dataset di search, i risultati non sono confrontabili. Fissa -country-US per tutto il crawl di un trend.
  • Volume eccessivo. Più di ~3 richieste/sec per IP sostenute per minuti porta quasi sempre a 429. Pacing 1-3 secondi + rotazione è più affidabile di burst.
  • Fingerprint browser. Header incompleti (manca Accept-Language, sec-ch-ua) aumentano il bot score. Mantieni un set di header coerente e realistico.

Confronto: API ufficiale v5 vs Resource API scraping

AspettoPinterest API v5 ufficialeResource API scraping
Accesso pin propriSì, documentatoSì (ma non consigliato)
Search pin pubblici arbitrariNo
Board di terziNoSì (solo pubbliche)
Rate limit~10 req/min writeSoft, per-IP
Stabilità contrattualeAltaBassa (endpoint interni)
Compliance ToSCompletaDa valutare caso per caso
Costo infrastrutturaBassoProxy + parsing

Key Takeaways

  • Scrapa solo superfici pubbliche: pin, board pubbliche, risultati di ricerca. Mai home feed login-walled.
  • L'API Resource interna (/resource/{Name}/get/) è il canale reale del frontend: usa header X-Pinterest-PWS-Handler, X-APP-VERSION e csrftoken.
  • Proxy residenziali rotanti con geo (-country-US) sono necessari per risultati localizzati e per restare sotto i rate limit per IP.
  • Sessioni sticky (-session-{id}) per tutta la paginazione di una board: mantengono csrftoken e bookmark.
  • Pacing 1-3 secondi, header coerenti, User-Agent realistico: riducono bot score.
  • Per workload di produzione su dati dei propri account, usa l'API v5 ufficiale. Lo scraping Resource va riservato a dataset di trend su contenuti pubblici.

Scraping etico e quando usare l'API ufficiale

Il Pinterest API scraping con proxy è giustificabile quando:

  • costruisci dataset di ricerca accademica o di trend su contenuti pubblici e non personali;
  • l'API v5 non copre il tuo caso d'uso (search arbitraria, board di terzi);
  • rispetti robots.txt, i ToS di Pinterest e i limiti di volume ragionevoli.

Non è giustificabile quando:

  • raccolga dati personali (profili utente, interazioni, follower) coperti da GDPR;
  • aggiri login o paywall;
  • operi su scale che impatta la disponibilità del servizio (un volume da DDoS non è scraping).

Per pipeline di produzione su account che possiedi (schedulazione pin, analytics, gestione board), l'API v5 ufficiale è più stabile, legalmente sicura e non richiede infrastruttura proxy. Lo scraping con proxy resta lo strumento giusto per dataset di contenuti pubblici su larga scala — ma con responsabilità, pacing e rispetto dei ToS.

Pronto a iniziare? Crea un piano residenziali su ProxyHat, fissa -country-US e prova i snippet sopra su una board pubblica di test prima di scalare.

Pronto per iniziare?

Accedi a oltre 50M di IP residenziali in oltre 148 paesi con filtraggio AI.

Vedi i prezziProxy residenziali
← Torna al Blog