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 pubbliche —
https://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 ricerca —
https://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-Agentrealistico 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:
- Rate limit per IP — richieste troppo ravvicinate dallo stesso IP ricevono
429o403dopo poche decine di hit. - Bot scoring — combinazione di fingerprint browser, header mancanti, pattern di navigazione lineare (solo endpoint Resource, senza asset).
- 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-USti 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 conservarecsrftokenebookmarkdurante 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
csrftokencambia e Pinterest restituisce401. 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
403su 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
nulle accetta duplicati. - Geo inconsistente. Se mescoli IP US e IT nello stesso dataset di search, i risultati non sono confrontabili. Fissa
-country-USper 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
| Aspetto | Pinterest API v5 ufficiale | Resource API scraping |
|---|---|---|
| Accesso pin propri | Sì, documentato | Sì (ma non consigliato) |
| Search pin pubblici arbitrari | No | Sì |
| Board di terzi | No | Sì (solo pubbliche) |
| Rate limit | ~10 req/min write | Soft, per-IP |
| Stabilità contrattuale | Alta | Bassa (endpoint interni) |
| Compliance ToS | Completa | Da valutare caso per caso |
| Costo infrastruttura | Basso | Proxy + 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 headerX-Pinterest-PWS-Handler,X-APP-VERSIONecsrftoken.- 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.






