# Changelog of Alibaba Products Scraper (`devilscrapes/alibaba-products-scraper`) Actor

- **URL**: https://apify.com/devilscrapes/alibaba-products-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/devilscrapes/alibaba-products-scraper.md

## Alibaba Products Scraper — Changelog

### 0.4 — 2026-09-17

- **Fix (term coverage):** a served 200-OK anti-bot challenge on a term's
  first page used to end the whole term immediately. Fault isolation
  worked as designed, but a run requesting 3 search terms could SUCCEED
  while delivering rows for only 1 of them — a coordinator review of the
  0.3 deep-verification run caught this ("success is not delivery" one
  level up from an empty row). `scraper.py` now retries a detected
  challenge on a fresh browser-impersonation profile + proxy session,
  bounded by a `RunBudget` derived from `Actor.configuration.timeout_at`
  (the run's real platform kill deadline) — never a guessed fixed attempt
  count, mirroring `cars-com-listings-scraper`/`leboncoin-france-cars`'s
  `run_budget.py` fix from the same day. The success status message now
  names term coverage (`delivered/requested`), not just total rows.
- Confirmed already true, added an explicit regression test for it: a term
  that ultimately returns nothing is never charged `result-item` (charging
  is per-row, inside the loop over `scraper.run`'s yielded rows).

### 0.3 — 2026-09-17

- **Fix (reliability):** default proxy now requests RESIDENTIAL pinned to
  US instead of the bare datacenter/auto pool. The 0.2 qa\_sweep run FAILED
  outright — both search terms hit a served 200-OK anti-bot challenge on
  the default pool (correctly failed loud, not a code regression). Fresh
  RESIDENTIAL sessions cleared the same target every time tried the same
  day. An explicit `apifyProxyGroups`/`apifyProxyCountry` in the raw input
  still overrides this default.

### 0.2 — 2026-09-17

- **Fix (pre-publish):** the search-page inline JSON-blob marker
  (`window.__page__data=`) had stopped matching anything live — Alibaba
  now serves a build-tagged, per-key variable
  (`window.__page__data_sse10._offer_list = {...}`). Every real run
  silently fell through to the low-fidelity regex fallback: product\_id
  filled 100% but title ~17%, price/moq/supplier\_name/image\_url 0%.
  `PAGE_DATA_MARKER_RE` now matches the assignment by pattern (tolerant of
  the build-tag suffix and the exact sub-key spelling) instead of a
  literal string.
- **Fix:** `title` carries inline `<img>`/`<strong>` HTML for keyword
  highlighting on live pages; now stripped before the row is built.
- **Fix (post-QA):** a 226-row deep cloud verification run of this same
  0.1 build turned up one page (15/226 rows) where every row filled
  title/product\_id but nothing else — a sibling `pc_less_recommend`
  (recommendation module) list outsized the real `offerResultData.offers`
  list and won the largest-list BFS. `search_result_items` now tries the
  confirmed-real path first, BFS only as fallback. See notes.md for the
  re-verification run's field fill rates on the corrected build.
- **Tests:** added live-captured fixtures (`search_page.REAL.html`,
  `search_page_page2.REAL.html`, Apify residential proxy, 2026-09-17) and
  a field-fill-rate regression suite (`TestFieldFillRateOnRealFixture`)
  that fails on any core field below 90% fill or an all-`None` row — the
  guard the SYNTHETIC-only fixture suite could not provide.
- This is the first publishable build; the 0.0 scaffold (commit
  `58010d7f`) was local-green but shipped a near-empty dataset and was
  never pushed.

### 0.1.0 — 2026-05-15

- Initial scaffolded release.
