Pop Mart Scraper — prices, stock & drop dates avatar

Pop Mart Scraper — prices, stock & drop dates

Pricing

from $1.05 / 1,000 products

Go to Apify Store
Pop Mart Scraper — prices, stock & drop dates

Pop Mart Scraper — prices, stock & drop dates

Pop Mart Labubu US catalog prices in USD, stock level (0/1/2, not a unit count) & release date. A separate events dataset records sold out, restock and price changes, with the time range between two checks. Events start on the second run. PPE per product row and per stock-change.

Pricing

from $1.05 / 1,000 products

Rating

0.0

(0)

Developer

Noah Adler

Noah Adler

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

17 days ago

Last modified

Categories

Share

Pop Mart product data from the US store: Labubu, Molly, SkullPanda, Crybaby, Dimoo, Hirono and the rest of the catalogue. One row per SKU with price in USD, live stock level, sold-out flag and the official release date.

Blind box and Whole Set are priced separately on Pop Mart, so they come out as separate rows — the way a reseller actually compares them.

Not a purchase bot. Drops sell out in seconds and this Actor does not touch checkout. It gives you the data: what dropped, when, at what price, and whether it is in stock.

Keywords: pop mart scraper · labubu price · popmart api · pop mart stock · blind box scraper


What it does

StepAction
1Input: searchTerms (series or keyword) + maxItems. Default mode is snapshot. autoWatch is off
2Reads the Pop Mart US storefront search (server-rendered payload, no browser)
3Paginates until the catalogue for that term is exhausted or maxItems is hit
4Flattens each product into its SKUs and pushes one row per SKU to the default dataset
5Compares each SKU with the previous observation and appends any change to the events dataset

Input

FieldRequiredDescription
searchTermsYesSeries or keywords as typed on popmart.com: labubu, molly, skullpanda, crybaby, dimoo, hirono…
maxItemsNo1–500 rows across all terms (default 100)
includeSoldOutNotrue (default) keeps sold-out SKUs — needed to track restocks
includeZeroPriceSkusNofalse (default) drops add-on placeholder SKUs with no real price
modeNosnapshot (default) or watch
autoWatchNofalse (default). Snapshot only. If a SKU's releaseAt (UTC) is inside the next watch window, this same run keeps polling only those SKUs until the window ends. No second run and no schedule
stateStoreNameNoKey-value store for the last observation. Default popmart-state. Different names do not overwrite each other. The same name still races if two runs use it at once
watchProductIdsNoWatch only. Product IDs to keep. searchTerms is still required. Up to 40
pollIntervalSecNoWatch and auto-watch. 15–300, default 60. This is the gap the run aims for between looks
watchWindowMinutesNoWatch and auto-watch. 30–60, default 45. The run exits when the window ends
proxyConfigurationNoRESIDENTIAL US recommended

Example (Try it)

{
"searchTerms": ["labubu", "skullpanda"],
"maxItems": 60,
"includeSoldOut": true,
"includeZeroPriceSkus": false,
"mode": "snapshot",
"autoWatch": false,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"],
"apifyProxyCountry": "US"
}
}

Output (one SKU per row)

FieldExample
productTitleTHE MONSTERS Hair Salon Series Figures
skuTitle / skuCodeSingle box · Whole Set
price / discountPrice / currency17.99 · 17.99 · USD
onlineStock / isSoldOut1 · false
isAvailableproduct-level sale status
releaseAt2026-06-26T23:30:00Z — official online release, UTC
url / imageUrlhttps://www.popmart.com/us/products/{id}
errorhonest soft-fail row if the storefront blocks

Zero-price placeholder SKUs are not pushed as success rows unless you ask for them.

onlineStock is a level, not a count of boxes: 0 (sold out), 1 or 2 (buyable). The default dataset is always this catalog shape. Stock changes are not mixed into these rows.


Snapshot and watch

Snapshot (default, including Try it) reads the catalogue once. It updates the remembered level for each SKU and appends any change since the previous run. It also logs SKUs whose releaseAt (UTC) falls in the next 24 hours. It does not start another run. autoWatch defaults to false, so Try it stays a single look.

autoWatch (only when mode is snapshot and the flag is true): after that full snapshot, if any SKU has releaseAt within the next watchWindowMinutes (default 45, UTC), this same run keeps polling only those SKUs every pollIntervalSec until the window ends. It does not spawn a second run and it does not create a schedule. If no releaseAt is inside that window, the snapshot ends as usual. A schedule you create every 30–60 minutes, plus autoWatch, is how drops get covered. releaseAt comparisons are UTC.

Watch stays inside this run. Pass the series in searchTerms. Optionally pass watchProductIds to keep only those products (the product page does not include the stock level, so the run reads search results and drops the rest). It looks again every pollIntervalSec until watchWindowMinutes is over, then exits. State is written after every poll, not only when the run ends, so a platform timeout does not leave the next run diffing a stale snapshot.

Start the watch run yourself shortly before releaseAt (UTC). The Actor does not sleep until the release, and it does not create a schedule. Set the Apify run timeout longer than the window (a 45 minute watch needs a timeout above 45 minutes). If the timeout is shorter, the run stops and the log says the window did not complete.

The default dataset receives the latest catalog once, at the end of the watch, so it is not filled with one copy per poll. Every transition still goes to events.

{
"searchTerms": ["labubu"],
"watchProductIds": ["8990"],
"mode": "watch",
"pollIntervalSec": 60,
"watchWindowMinutes": 45,
"maxItems": 20,
"includeSoldOut": true
}

Events dataset (events)

One row per transition, in a dataset named events (not the default dataset). Rows accumulate across runs on the account that runs the Actor. The last observation for each SKU is kept in the key-value store named by stateStoreName (default popmart-state: level, price, time, title, URL). No personal data. Two parallel runs that share that name can overwrite each other's last observation.

Events show up starting on the second run. The first time a SKU is seen, the only event is new_sku. Sold-out, restock and other level changes start on the next observation.

eventWhen
new_skuFirst observation. No previous level
stock_dropLevel 2 → 1
sold_outLevel 1 → 0 or 2 → 0
restockLevel leaves 0 (0 → 1 or 0 → 2)
stock_riseLevel 1 → 2. This is not a restock
price_changePrice changed. If the level changed too, this is a second row

A change is noticed by comparing two looks. Times are UTC. The time on the row is only as precise as the gap between those two looks. That gap is changedBetween: [previous observation, this observation]. It is not the exact second the level moved. In watch mode the run aims to look every pollIntervalSec seconds, so the gap is about that long, and pollIntervalSec is filled in. In a one-shot snapshot, pollIntervalSec is null and the precision is changedBetween itself (however long it was since the previous run).

new_sku has no earlier look, so changedBetween is null.

For sold_out only, timeToSoldOut is two durations in seconds, computed from UTC timestamps: from releaseAt to the previous look, and from releaseAt to the look that first saw level 0. It is a range, not a US-local clock time. If releaseAt is missing, timeToSoldOut is null. There is never a single sold-out time.

FieldMeaning
sku / series / skuTitle / productId / urlWhich SKU. series is the product title
fromLevel / toLevelLevels 0, 1 or 2. Null on new_sku and on price_change
fromPrice / toPrice / currencySet on price_change
prevSeenAt / seenAt / scrapedAtISO times in UTC. scrapedAt is this observation, same as seenAt
changedBetweenThe two observation times (UTC). Null on new_sku
timeToSoldOutTwo integers, seconds since releaseAt (UTC). Only on sold_out; otherwise null
pollIntervalSecWatch interval for this run, or null on a snapshot

Pricing

Pay-per-event: the catalog row is the product charge (one per SKU in the default dataset). Each row in the events dataset is a separate stock-change charge, higher than the catalog row and still a cheap volume price. A named dataset is not covered by the catalog event. See Actor pricing on Apify.


Notes

  • Coverage is the US store (popmart.com/us), so prices are USD.
  • A handful of legacy products carry no release timestamp; releaseAt is left empty rather than guessed. Those SKUs get timeToSoldOut: null if they sell out.
  • onlineStock is a stock level, not a unit count: the storefront only exposes 0 (sold out), 1 or 2 (buyable). Read it with isSoldOut.
  • You can run snapshot on your own schedule if you want a daily history. This Actor does not create that schedule. Turn on autoWatch on that schedule if you also want the run to stay and poll when a releaseAt (UTC) is inside the window.
  • releaseAt, seenAt and timeToSoldOut are UTC. timeToSoldOut is a range of durations in seconds, not a US local time.
  • If a run returns a single row with error=true mentioning Cloudflare, turn on RESIDENTIAL US and retry.