Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/treg/catalog/apify.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -255,4 +255,32 @@ endpoints:
example_response: examples/apify.account.usage.json
docs_url: https://docs.apify.com/api/v2/users-me-get

- id: apify.lazada.search.products
capability: lazada.search.products
platform: lazada
scope: any_account
method: POST
path: /actors/herus13~lazada-scraper/run-sync-get-dataset-items
name: "Search Lazada products by keyword across Southeast Asia"
summary: "Search Lazada and return products with price, original price, currency, rating, review and sold counts, seller and location from one of six SEA country sites (SG, MY, VN, TH, PH, ID)"
input:
queryParams:
maxItems: {type: integer, required: false, note: "SERVER-SIDE result cap — the only hard spend ceiling for a pay-per-result actor; set it on every call. Equals the number of product-result events billed", example: 40}
maxTotalChargeUsd: {type: number, required: false, note: "alternative hard cap, in dollars", example: 1.0}
timeout: {type: integer, required: false, note: "seconds before the synchronous run is cut off; Apify closes the connection at 300s regardless — a large pull should use the async web.scrape.job.* pair above", example: 180}
body:
search_terms: {type: "array[string]", required: true, note: "keywords to search, one per entry; each is paged until the run reaches max_results. An empty list stops the run with an input error before anything is charged", example: ["iphone 15 case"]}
region: {type: string, required: false, note: "one of sg|my|vn|th|ph|id — decides which country site, the listing language and the currency of every price. Default sg. One run covers one country, so comparing markets means one run per region", example: "sg"}
max_results: {type: integer, required: false, note: "total products across all search terms; default 40, min 1, max 4000. A single keyword usually runs out before 4000 — widen coverage with more terms, not a higher cap", example: 40}
proxyUrls: {type: "array[string]", required: false, note: "leave empty to use the residential proxy included in the run price; or pass one gateway URL per entry (http://user:pass@host:port) to route through your own provider instead"}
bodyType: json
note: "the response is the dataset items array directly — no run envelope, no polling. Each row carries title, price, price_original, currency, rating, review_count, sold_count, seller_name, location, brand and product_url. Cap every call with maxItems: it is the enforced ceiling and equals the count of product-result events billed"
test_request:
queryParams: {maxItems: 1, maxTotalChargeUsd: 0.05, timeout: 180}
body: {search_terms: ["iphone 15 case"], region: "sg", max_results: 1}
cost: {type: per_result, value: 0.005, currency: USD, per: 1, unit: result, source: rate_card_api, source_url: 'https://api.apify.com/v2/acts/herus13~lazada-scraper', checked: '2026-09-23', confidence: documented, note: 'pay-per-event: one product-result event = one product, $0.005 — read live 2026-09-23 from the actor pricingInfos (eventPriceUsd 0.005, the sole event; apifyMarginPercentage 0.20). The caller pays this on their own Apify token. NOT self-observable from the owner meter: a maxItems=1 run 2026-09-23 (run FoMZQgBrce1dYgbik, HTTP 201, 1 product) reported usageTotalUsd 0.00588 of platform COMPUTE with chargedEventCounts null, because Apify does not bill an owner the per-result rental on their own actor. Charged per product produced even if the run is cut short — cap with maxItems'}
example_response: examples/apify.lazada.search.products.json
docs_url: https://apify.com/herus13/lazada-scraper

proposed_capabilities:
lazada.search.products: "Search Lazada products by keyword across Southeast Asia (SG, MY, VN, TH, PH, ID)"
1 change: 1 addition & 0 deletions src/treg/catalog/capabilities.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ platforms:
jd: {label: "JD.com", category: "E-commerce", featured: 3, summary: "Products, prices, comments and search from JD.com."}
tiktok-shop: {label: "TikTok Shop", category: "E-commerce", featured: 4, summary: "Product listings and search from TikTok Shop."}
douyin-shop: {label: "Douyin e-commerce (product and shop data)", category: "E-commerce", summary: "Products, SKUs, shop listings and item comments from Douyin e-commerce."}
lazada: {label: "Lazada", category: "E-commerce", summary: "Product listings and search from Lazada across Southeast Asia (SG, MY, VN, TH, PH, ID)."}
"1688": {label: "1688 (Alibaba wholesale)", category: "E-commerce", summary: "Wholesale item data and search from 1688."} # quoted: unquoted 1688 is a YAML integer
xianyu: {label: "Xianyu / Goofish (Alibaba second-hand)", category: "E-commerce", summary: "Second-hand listings and search from Xianyu (Goofish)."}
dewu: {label: "Dewu / Poizon", category: "E-commerce", summary: "Product data from Dewu (Poizon)."}
Expand Down
20 changes: 20 additions & 0 deletions src/treg/catalog/examples/apify.lazada.search.products.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[
{
"scraped_at": "2026-09-23T17:02:05+00:00",
"product_id": "3625882801",
"title": "Spigen Mag Armor (MagFit) Compatible with MagSafe Designed for iPhone 16 15 14 Pro Max / iPhone 13 Pro Max /iPhone 12 / 13 Pro Case Protective Cover | Authentic Original",
"price": 8.54,
"price_original": 19.84,
"currency": "SGD",
"rating": 4.866666666666666,
"review_count": 164,
"sold_count": 680,
"seller_name": "Allie Libra",
"location": "China",
"brand": "No Brand",
"thumbnail_url": "https://sg-test-11.slatic.net/p/922bc17723a36aec7d8c765286066238.jpg",
"product_url": "https://www.lazada.sg/products/pdp-i3625882801.html",
"region": "sg",
"error": null
}
]
Loading