Pinterest Pins Videos Search Scraper extracts pins and video results from Pinterest search queries. Collect pin titles, descriptions, images, video URLs, engagement metrics, and source links. Ideal for trend research, content discovery, and market analysis.
Root cause (confirmed live against https://www.pinterest.com/search/videos/?q=running+shoes&rs=content_type_filter
and the equivalent pins/All search on 2026-08-29):
.actor/input_schema.json's merchantDomainFilter field shipped with
"prefill": ["amazon.com", "etsy.com"]. Apify's Console "Start" run (the most
common way this actor gets tried/tested) submits prefilled field values as the
actual run input unless a user edits them, so essentially every run was
launched with merchantDomainFilter = ["amazon.com", "etsy.com"].
Live verification showed Pinterest only discloses a pin's outbound link
and domain to a logged-in viewer — every pin returned by an anonymous
(signed-out) scrape has domain: "", on both the BaseSearchResource XHR
payload and the page's own embedded __PWS_DATA__ JSON, across both the
videos and pins search surfaces (0/24 and 0/25 non-empty domains sampled
for "running shoes"). passes_domain_filter() returns False whenever
domain is empty and a filter list is non-empty, so every single pin got
filtered out before Actor.push_data() — even though the scrape itself was
successfully collecting 20-25+ real pins per term. This is the actual root
cause of the reported "returns 0 results on every run."
.actor/input_schema.json: merchantDomainFilter prefill changed from
["amazon.com", "etsy.com"] to [] so a default/Console run no longer
self-filters to zero. Description updated on merchantDomainFilter and
onlyLinkedPins to document that both features require a logged-in session
to have any effect, since anonymous scraping never receives a domain/link
value from Pinterest.
src/main.py: scrape_pinterest_search() and _capture_board_or_profile()
waited on the stale selector [data-test-id="pin"] (plus pinrep/
pinWrapper/article in the board/profile path), which no longer appears
for a signed-out session and always timed out after 10s on every run
(wasted time, misleading "Pin selector not found" warning log). Live DOM
inspection of both search results pages and profile/board pages confirmed
Pinterest now renders anonymous visitors a "gated" pin grid tagged
[data-test-id="gated-search-pins-feed"] / [data-test-id="gated-pin-rep"]
/ [data-test-id="PinTypeIdentifier"] instead. Both selector waits now
include these current test-ids alongside the legacy ones, so the wait
actually resolves instead of always timing out.
Verified
Confirmed via a scratch venv (playwright + chromium, installed fresh) that
scrape_pinterest_search() end-to-end now returns 24 real pins (image +
HLS video URLs, e.g. https://v1.pinimg.com/videos/iht/hls/.../*.m3u8) for
the term "running shoes" with no selector-timeout warning, and that with the
fixed merchantDomainFilter prefill all 24 pins are pushed to the dataset
(0 were pushed with the old prefilled filter, using identical scraped data).
Confirmed the scraping engine itself (navigation, response interception,
bookmark-cursor pagination, extract_pin_data parsing) is not broken —
Pinterest's search/profile pages are reachable and pins are extracted
correctly; the missing domain/link/title/pinner values on every row
are a Pinterest-side anonymous-view data restriction, not a parsing bug, and
are out of scope to work around (would require adding an authenticated
session, which is new architecture beyond this fix).
Not changed (verified working / out of scope)
Dockerfile: uses apify/actor-python:latest + explicit
playwright install chromium && playwright install-deps chromium at build
time. This is a valid, supported pattern (the base image is Debian-based
with apt available for install-deps) and does install real Chromium
binaries — it is not a plain Python image missing browser support, so it was
left as-is per task scope.