Search Alibaba.com product listings by keyword and get structured rows for every matching supplier offer — product id, title, price/price range, MOQ, supplier name, image, and product URL. Built for dropshippers, sourcing agents, and e-commerce tooling. A wholesale supplier API alternative.
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.