Aviso legal: Este artículo cubre únicamente el acceso a datos públicos de Pinterest. Antes de extraer cualquier dato, revisa los Términos de Servicio de Pinterest. En EE. UU., la Computer Fraud and Abuse Act (CFAA) penaliza el acceso no autorizado a sistemas informáticos. En la UE, el RGPD (GDPR) regula el tratamiento de datos personales. Si el dato requiere login o contiene información personal, usa la API oficial de Pinterest v5 en lugar de scraping.
Si has intentado scrapear Pinterest en 2026, probablemente te topaste con bloqueos de IP, páginas vacías renderizadas en JavaScript y respuestas truncadas. Pinterest es una plataforma visual con más de 500 millones de usuarios activos mensuales, y su arquitectura combina renderizado dinámico con endpoints internos JSON que no están documentados públicamente. Esta guía explica cómo construir un Pinterest scraper robusto orientado a datos públicos —pins, boards y resultados de búsqueda— usando proxies residenciales rotativos, y cuándo conviene recurrir a la API oficial.
Cómo scrapear Pinterest Pins y Boards en 2026: el panorama técnico
Pinterest funciona como una SPA (Single Page Application) construida sobre React. Cuando un usuario navega, el navegador no recibe HTML estático con los pins; en su lugar, la app JS realiza llamadas XHR a endpoints internos conocidos como Resource API. Estos endpoints devuelven JSON estructurado con toda la información del pin o board. El reto para cualquier Pinterest API scraping es que estos endpoints requieren headers específicos, tokens CSRF y están protegidos por sistemas de puntuación anti-bot que limitan el número de requests por IP en ventanas de tiempo cortas.
Antes de profundizar, es crucial distinguir entre las superficies accesibles y las que no lo son:
| Superficie | Acceso | ¿Scraping viable? |
|---|---|---|
| Pin público (URL /pin/ID/) | Sin login | Sí, datos del pin visibles |
| Board público (URL /board/...) | Sin login | Sí, feed de pins del board |
| Resultados de búsqueda | Sin login | Sí, pero localizado por IP |
| Home feed personalizado | Requiere login | No — usa API oficial |
| Estadísticas de cuenta propia | Requiere login | No — usa API v5 |
API oficial de Pinterest v5 vs scraping
Pinterest ofrece una API REST oficial v5 con endpoints para obtener pins, boards y analíticas de cuentas propias. Sin embargo, esta API está diseñada principalmente para gestores de cuentas y anunciantes. Limitaciones clave:
- Requiere autenticación OAuth 2.0 con una cuenta de Pinterest Developer.
- El endpoint
/v5/boards/{board_id}/pinsdevuelve solo los pins de tus propios boards, no de cualquier board público. - No existe un endpoint de búsqueda pública de pins de terceros.
- Rate limits documentados de aproximadamente 1,000 requests por minuto por token, con cuotas diarias adicionales.
Para casos de uso como análisis de tendencias visuales, investigación de mercados o construcción de datasets de imágenes públicas —donde necesitas acceder a boards y pins de cualquier usuario público— el scraping de superficies públicas sigue siendo la opción práctica. La API v5 no cubre este caso.
La Resource API interna de Pinterest
Pinterest expone sus datos a través de endpoints bajo el path /resource/. Cada recurso tiene un nombre (PinResource, BoardFeedResource, SearchResource) y se invoca con una petición GET que incluye dos parámetros clave en la URL:
source_url=: la URL amigable que el usuario vería en el navegador, codificada en formato URL. Por ejemplo, para un board:source_url=%2Fusuario%2Fboard-slug%2F.data=: un objeto JSON codificado como URL con los parámetros de la consulta, incluyendo el cursor de paginación (bookmarks).
Endpoints principales
PinResource: Devuelve los datos de un pin individual.
GET /resource/PinResource/get/?source_url=%2Fpin%2F1234567890%2F&data=%7B%22options%22%3A%7B%22id%22%3A%221234567890%22%2C%22field_set_key%22%3A%22unauth_react_main_pin%22%7D%7D
BoardFeedResource: Devuelve los pins de un board público con paginación por cursor.
GET /resource/BoardFeedResource/get/?source_url=%2Fusuario%2Fboard-slug%2F&data=%7B%22options%22%3A%7B%22board_id%22%3A%22BOARD_ID%22%2C%22page_size%22%3A25%2C%22bookmarks%22%3A%5B%5D%7D%7D
SearchResource: Devuelve resultados de búsqueda de pins. Los resultados están localizados según la IP del solicitante.
GET /resource/BaseSearchResource/get/?source_url=%2Fsearch%2Fpins%2F%3Fq%3Dminimalist%2520interior&data=%7B%22options%22%3A%7B%22query%22%3A%22minimalist%20interior%22%2C%22bookmarks%22%3A%5B%5D%7D%7D
Headers requeridos
Las peticiones a la Resource API deben incluir headers específicos o serán rechazadas:
| Header | Propósito |
|---|---|
X-Pinterest-PWS-Handler | Identifica el handler del frontend (ej. www/[username]/[slug].js) |
X-APP-VERSION | Versión de la app JS actual; cambia con cada deploy |
csrftoken | Token CSRF extraído de la cookie inicial |
Accept | application/json, text/javascript, */*; q=0.01 |
User-Agent | Debe coincidir con un navegador real moderno |
El csrftoken se obtiene de la cookie csrftoken que Pinterest establece en la primera petición a cualquier página pública. Es esencial mantener la misma sesión (mismo conjunto de cookies) entre la petición inicial y las llamadas a la Resource API.
Realidad anti-bot: por qué necesitas proxies residenciales
Pinterest aplica un sistema de puntuación anti-bot que combina varios signals: tasa de requests por IP, patrón de navegación, headers, TLS fingerprint y comportamiento de cursor. Cuando una IP supera un umbral de requests —típicamente en el orden de 50–100 requests por minuto para IPs de datacenter— Pinterest responde con HTTP 429, páginas vacías o un desafío de seguridad intersticial.
Los proxies de datacenter (AWS, DigitalOcean, OVH) son detectados rápidamente porque Pinterest utiliza bases de datos de rangos IP comerciales. Los rangos ASN de proveedores cloud conocidos son marcados como sospechosos por defecto.
Los proxies residenciales ofrecen IPs asignadas a proveedores de ISP reales (Comcast, AT&T, Movistar, Vodafone), lo que los hace indistinguibles de usuarios legítimos a nivel de ASN. Esto es crítico para Pinterest por dos razones:
- Rate limits por IP: Con rotación de IPs residenciales, distribuyes tus requests entre cientos o miles de IPs, manteniendo cada IP por debajo del umbral de detección.
- Localización de resultados: Los resultados de búsqueda y las recomendaciones de Pinterest están localizados por IP. Una búsqueda de "muebles de diseño" desde una IP en Madrid devuelve resultados diferentes a una IP en Ciudad de México. Si necesitas datos de un mercado específico, debes usar proxies con geo-targeting.
Consulta las ubicaciones de proxies disponibles en ProxyHat para verificar cobertura por país.
Configuración de ProxyHat para scraping de Pinterest
ProxyHat proporciona proxies residenciales rotativos accesibles vía un gateway HTTP/SOCKS5 unificado. La autenticación se realiza en el formato estándar usuario:contraseña@host:puerto, y los parámetros de geo-targeting y sesión se pasan dentro del nombre de usuario.
Parámetros clave
- Geo-targeting por país:
user-country-US:pass@gate.proxyhat.com:8080 - Geo-targeting por ciudad:
user-country-DE-city-berlin:pass@gate.proxyhat.com:8080 - Sesión sticky:
user-session-abc123:pass@gate.proxyhat.com:8080— mantiene la misma IP de salida entre requests. - Combinado:
user-country-US-session-abc123:pass@gate.proxyhat.com:8080
Para más detalles sobre configuración, consulta la documentación oficial de ProxyHat.
Ejemplo 1: Scrapear BoardFeedResource con Python
Este ejemplo pagina los pins de un board público usando la Resource API de Pinterest a través del gateway HTTP de ProxyHat en el puerto 8080. Usa una sesión sticky para mantener el csrftoken entre peticiones.
import requests
import json
import urllib.parse
import time
# Credenciales ProxyHat — residencial, EE. UU., sesión sticky
PROXY = "http://user-country-US-session-pint01:PASSWORD@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/131.0.0.0 Safari/537.36",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Language": "en-US,en;q=0.9",
"X-Pinterest-PWS-Handler": "www/[username]/[slug].js",
"X-APP-VERSION": "c8f5c1a",
"Referer": "https://www.pinterest.com/",
}
BOARD_URL = "/usuario/board-slug/"
BOARD_ID = "1234567890123456789"
def fetch_board_pins(board_id, max_pages=10):
session = requests.Session()
session.proxies = PROXIES
session.headers.update(HEADERS)
# 1. Visitar la página del board para obtener cookies y csrftoken
board_page = session.get(f"https://www.pinterest.com{BOARD_URL}")
csrf = session.cookies.get("csrftoken", "")
session.headers["X-CSRFToken"] = csrf
bookmarks = []
all_pins = []
for page in range(max_pages):
data_param = json.dumps({
"options": {
"board_id": board_id,
"page_size": 25,
"bookmarks": bookmarks,
"current_url": BOARD_URL,
}
})
encoded_data = urllib.parse.quote(data_param)
encoded_source = urllib.parse.quote(BOARD_URL)
api_url = (
f"https://www.pinterest.com/resource/BoardFeedResource/get/"
f"?source_url={encoded_source}&data={encoded_data}"
)
resp = session.get(api_url)
if resp.status_code == 429:
print(f"Rate limited en página {page}. Esperando 60s...")
time.sleep(60)
continue
if resp.status_code != 200:
print(f"Error HTTP {resp.status_code} en página {page}")
break
payload = resp.json()
resource_resp = payload.get("resource_response", {})
pins = resource_resp.get("data", [])
bookmarks = resource_resp.get("bookmark", [])
for pin in pins:
all_pins.append({
"id": pin.get("id"),
"title": pin.get("title") or pin.get("grid_title", ""),
"image_url": pin.get("images", {}).get("orig", {}).get("url", ""),
"link": pin.get("link", ""),
})
if not bookmarks or bookmarks == [""]:
print("No hay más páginas.")
break
# Pacing: 2-3 segundos entre páginas
time.sleep(2.5)
return all_pins
pins = fetch_board_pins(BOARD_ID, max_pages=5)
print(f"Total pins extraídos: {len(pins)}")
for p in pins[:3]:
print(json.dumps(p, indent=2, ensure_ascii=False))
Salida esperada (pin truncado):
{
"id": "9876543210987654321",
"title": "Ideas de decoración minimalista",
"image_url": "https://i.pinimg.com/736x/ab/cd/ef/abcdef123456.jpg",
"link": "https://example.com/blog/minimalist-decor"
}
Ejemplo 2: Scrapear resultados de búsqueda con Node.js
Este ejemplo usa el gateway HTTP de ProxyHat en el puerto 8080 para buscar pins públicos y extraer los campos relevantes.
const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');
const PROXY_URL = 'http://user-country-US-session-pint02:PASSWORD@gate.proxyhat.com:8080';
const agent = new HttpsProxyAgent(PROXY_URL);
const HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'en-US,en;q=0.9',
'X-Pinterest-PWS-Handler': 'www/search/[scope].js',
'X-APP-VERSION': 'c8f5c1a',
'Referer': 'https://www.pinterest.com/',
};
async function searchPins(query, maxPages = 5) {
const client = axios.create({
httpsAgent: agent,
headers: HEADERS,
timeout: 30000,
});
// Obtener cookies iniciales
const initial = await client.get('https://www.pinterest.com/search/pins/?q=' + encodeURIComponent(query));
const setCookie = initial.headers['set-cookie'] || [];
const csrfMatch = setCookie.find(c => c.startsWith('csrftoken='));
const csrf = csrfMatch ? csrfMatch.split('=')[1].split(';')[0] : '';
const sourceUrl = `/search/pins/?q=${encodeURIComponent(query)}`;
let bookmarks = [];
const allPins = [];
for (let page = 0; page < maxPages; page++) {
const dataParam = encodeURIComponent(JSON.stringify({
options: { query, bookmarks, scope: 'pins' }
}));
const encodedSource = encodeURIComponent(sourceUrl);
const apiUrl = `https://www.pinterest.com/resource/BaseSearchResource/get/?source_url=${encodedSource}&data=${dataParam}`;
const resp = await client.get(apiUrl, {
headers: { ...HEADERS, 'X-CSRFToken': csrf }
});
const resourceResp = resp.data.resource_response || {};
const pins = resourceResp.data || [];
bookmarks = resourceResp.bookmark || [];
for (const pin of pins) {
allPins.push({
id: pin.id,
title: pin.title || pin.grid_title || '',
image_url: pin.images?.orig?.url || '',
link: pin.link || '',
});
}
if (!bookmarks.length || bookmarks[0] === '') break;
await new Promise(r => setTimeout(r, 2500));
}
return allPins;
}
(async () => {
const pins = await searchPins('minimalist interior design', 3);
console.log(`Pins encontrados: ${pins.length}`);
console.log(JSON.stringify(pins.slice(0, 3), null, 2));
})();
Paginación por cursor, sesiones sticky y pacing
Bookmark/cursor pagination
Pinterest usa un sistema de paginación por cursor opaco. La respuesta de cada Resource API incluye un campo bookmark (a veces llamado bookmarks) que es un array de strings. Para obtener la siguiente página, debes pasar ese array en el campo options.bookmarks de la siguiente petición. Cuando el array está vacío o contiene un string vacío, no hay más resultados.
Los bookmarks son opacos: no son offsets numéricos ni IDs secuenciales. Son tokens generados por el servidor que codifican el estado de la paginación. Nunca intentes modificarlos o construirlos manualmente.
Sesión sticky para continuidad de csrftoken
El csrftoken está vinculado a la sesión de cookies. Si tu proxy rota la IP entre la petición inicial (que obtiene el token) y las llamadas a la Resource API, Pinterest puede invalidar la sesión. Por eso es crucial usar el flag -session- en ProxyHat para mantener la misma IP durante todo el flujo:
# Sesión sticky con geo US
http://user-country-US-session-mi-sesion-01:PASSWORD@gate.proxyhat.com:8080
Cuando termines de scrapear un board o búsqueda completa, puedes cambiar el identificador de sesión para rotar a una nueva IP y empezar el siguiente objetivo con una sesión limpia.
Pacing y rate limiting
Incluso con proxies residenciales, el pacing es esencial. Recomendaciones prácticas:
- 2–3 segundos entre cada página de resultados (request a la Resource API).
- 5–10 segundos de pausa si recibes un HTTP 429.
- Máximo 50 requests por minuto por sesión/IP para mantener un perfil de navegación humano.
- Rotar el identificador de sesión (
-session-) cada 100–200 requests para cambiar de IP y reducir la acumulación de señales anti-bot.
User-Agent y fingerprint hygiene
El User-Agent debe ser un navegador real moderno y consistente con el resto de headers. Reglas:
- Usa un UA de Chrome o Firefox actualizado (no uses UA de bots o librerías).
- Mantén el mismo UA durante toda la sesión.
- Incluye
Accept-Languagecoherente con el geo del proxy (ej.es-ES,es;q=0.9para IPs en España). - No rotes UAs entre requests de la misma sesión — eso es una señal de bot obvia.
- Considera usar
curl_cffien Python para imitar el TLS fingerprint de Chrome a nivel de handshake, ya que Pinterest puede inspeccionar el JA3/JA4.
Errores comunes y edge cases
| Problema | Causa probable | Solución |
|---|---|---|
Respuesta JSON vacía o resource_response.data = [] | IP bloqueada o session expirada | Rotar sesión (-session-) y re-obtener csrftoken |
| HTTP 403 Forbidden | Headers incompletos o X-APP-VERSION desactualizado | Visitar la página pública y copiar el X-APP-VERSION actual del HTML |
| HTTP 429 Too Many Requests | Rate limit por IP excedido | Aumentar pacing, rotar IP, reducir concurrencia |
| Bookmarks siempre vacíos | Board sin más pins o query sin resultados | Verificar que el board_id es correcto y público |
| Página de seguridad intersticial | <Puntuación anti-bot alta | Cambiar a IP residencial de otro país, reducir velocidad |
Scraping ético y cuándo usar la API oficial
El scraping de Pinterest debe limitarse a datos públicos, no personales: metadatos de pins (título, descripción, imagen, enlace), boards públicos y resultados de búsqueda agregados. No extraigas:
- Datos de usuarios que requieren login para ver (perfiles privados, boards secretos).
- Información personal identificable más allá de lo visible públicamente.
- Datos de analíticas o métricas de cuentas de terceros.
Respeta el archivo robots.txt de Pinterest. Aunque los endpoints de la Resource API no siempre están listados en robots.txt, las URLs de boards y pins sí lo están. Si robots.txt prohíbe un path, no lo scrapees.
Cuándo preferir la API oficial v5
- Producción estable: Si necesitas datos de tus propias cuentas o boards gestionados, la API v5 es más fiable y no viola ToS.
- Datos de analíticas: La API v5 ofrece endpoints de analíticas de pins y campañas que no están disponibles vía scraping público.
- Escritura de datos: Crear pins, boards o gestionar cuentas requiere la API oficial — el scraping es solo lectura.
- Cumplimiento corporativo: Si tu organización requiere auditoría y cumplimiento de ToS, la API oficial es la única opción respaldada por Pinterest.
Para más información sobre casos de uso de scraping con proxies, consulta nuestra guía de web scraping y la página de precios de ProxyHat. Si necesitas tracking de resultados de motores de búsqueda, también tenemos un caso de uso sobre SERP tracking.
Puntos clave
1. Datos públicos solamente: Scrapea pins, boards y búsquedas públicas. Cualquier dato detrás de login requiere la API oficial v5.
2. La Resource API es el camino: Los endpoints
/resource/devuelven JSON estructurado, pero requieren headers específicos y csrftoken válido.3. Proxies residenciales con geo: Pinterest localiza resultados por IP. Usa
-country-USo el mercado que necesites. Los proxies de datacenter son bloqueados rápidamente.4. Sesión sticky para csrftoken: Mantén la misma IP durante todo el flujo con
-session-para evitar invalidación de sesión.5. Pacing y fingerprint: 2–3 segundos entre páginas, UA consistente, rotación de sesión cada 100–200 requests.






