# Lazada Scraper — Products, Prices & Reviews (SEA) (`tortuga/lazada-scraper`) Actor

Scrape Lazada products from search, category and product URLs in Singapore, Malaysia, Thailand, Philippines, Indonesia and Vietnam: price, discount, rating, sold, seller, reviews.

- **URL**: https://apify.com/tortuga/lazada-scraper.md
- **Developed by:** [Trevor Ortega](https://apify.com/tortuga) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.80 / 1,000 product scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Lazada Scraper — Products, Prices & Reviews (SEA)

Scrape **Lazada** product data from all six Southeast Asian sites (Singapore, Malaysia, Thailand, the Philippines,
Indonesia and Vietnam). It works from keyword searches, category, brand and store pages, and single product URLs. Each
product comes with its price, original price, discount, rating, review count, sold count, seller, LazMall and
free-shipping flags, and the location it ships from. You can also add product details (description, category path,
gallery, video, every variant) and customer reviews with star ratings, text, dates, photos and seller replies. There is
no login and no browser.

### What data does Lazada Scraper extract?

| Field | Example | Notes |
|---|---|---|
| `itemId`, `skuId`, `sku` | `3739956594`, `21185247689`, `3739956594_MY` | Lazada item id, cheapest SKU id, seller SKU |
| `title`, `url` | `Electrova Low-GI Steamer Rice Cooker 2.5L …`, `https://www.lazada.com.my/products/pdp-i3739956594.html` | |
| `country`, `currency` | `MY`, `MYR` | SG/SGD, MY/MYR, TH/THB, PH/PHP, ID/IDR, VN/VND |
| `price`, `originalPrice`, `discountPercent` | `118`, `459`, `74` | Numbers in the site's currency; `originalPrice` only when a struck-through price is shown |
| `priceText` | `RM118.00` | As displayed |
| `rating`, `reviewCount` | `4.93`, `106` | Average stars and number of ratings |
| `soldCount`, `soldText` | `368`, `368 sold` | `3.7K sold` becomes `3700` |
| `sellerName`, `sellerId`, `shopId` | `Electrova Malaysia`, `300145209042`, `1359405` | |
| `brand`, `brandId` | `Electrova` | |
| `isLazMall`, `freeShipping` | `true`, `false` | LazMall (official store) and free-shipping badges |
| `location` | `Selangor` | Where the product ships from (`China`, `Overseas`, a state or city) |
| `inStock`, `isSponsored`, `badges` | `true`, `false`, `["lazMall", "campaign"]` | All badges shown on the card |
| `categoryIds`, `image`, `images` | | Image URLs at full size |
| `position`, `page`, `source`, `searchTerm`, `sourceUrl`, `scrapedAt` | `1`, `1`, `search`, `rice cooker` | Where the product was found |

**With "Include product details"** (always on for product URLs): `description` (text), `descriptionImages`,
`categoryPath` (`["Home Appliances", "Kitchen Appliances", "Cooking Equipment", "Cookers"]`), `categoryId`, the complete
`images` gallery, `videoUrl`, `variantOptions` (`[{"name": "Color", "values": ["Black", "White"]}]`), `variants` (one per
SKU: `skuId`, `options`, `image`, `url`), `inStock`, `maxPurchaseQuantity`, `brandUrl`.

**With "Reviews per product"**: `reviews` (each with `reviewId`, `rating`, `text`, `date`, `dateText`, `boughtDate`,
`reviewerName`, `isAnonymous`, `variant`, `images`, `videoUrl`, `likes`, `isPurchased`, `sellerReply`),
`ratingDistribution` (`{"5": 100, "4": 5, "3": 1, "2": 0, "1": 0}`) and `reviewsWithImages`.

### How to use Lazada Scraper

1. Enter one or more **Search terms** and pick the **Country** whose Lazada site to search. Or paste Lazada URLs into
   **Start URLs**: search, category, brand or store pages from any of the six sites, with the filters you set on the site
   (price range, rating, location, LazMall …), or single product pages.
2. Set **Max products**. Optionally turn on **Include product details**, set **Reviews per product**, or choose a sort
   order (best match, price low to high, price high to low).
3. Run it and download the results as JSON, CSV or Excel, or read them through the API.

### Input example

```json
{
  "searchTerms": ["rice cooker"],
  "country": "MY",
  "maxItems": 100,
  "sortBy": "popularity",
  "includeDetails": true,
  "maxReviewsPerProduct": 10,
  "startUrls": [
    { "url": "https://www.lazada.co.th/products/pdp-i3539123466.html" },
    { "url": "https://www.lazada.sg/shop-wireless-earbuds/" }
  ]
}
```

### Output example

A product from a search with details and reviews on (lists shortened):

```json
{
  "itemId": "3739956594",
  "skuId": "21185247689",
  "title": "Electrova Low-GI Steamer Rice Cooker 2.5L iCook Series l 304 Stainless Steel Pot l Non Stick Inner Pot l 8 Menu Selection",
  "url": "https://www.lazada.com.my/products/pdp-i3739956594.html",
  "country": "MY",
  "price": 118,
  "originalPrice": 459,
  "discountPercent": 74,
  "currency": "MYR",
  "priceText": "RM118.00",
  "rating": 4.93,
  "reviewCount": 106,
  "soldCount": 368,
  "soldText": "368 sold",
  "brand": "Electrova",
  "sellerName": "Electrova Malaysia",
  "sellerId": "300145209042",
  "shopId": "1359405",
  "isLazMall": true,
  "freeShipping": false,
  "location": "Selangor",
  "inStock": true,
  "isSponsored": false,
  "badges": ["voucherApplied", "campaign", "lazMall"],
  "image": "https://my-live-01.slatic.net/p/36b7f025b22c155e3b8c5ec59c00b581.png",
  "position": 1,
  "source": "search",
  "searchTerm": "rice cooker",
  "page": 1,
  "categoryPath": ["Home Appliances", "Kitchen Appliances", "Cooking Equipment", "Cookers"],
  "description": "Electrova Digital Rice Cooker EzRice\nGenerous Capacity: ...",
  "videoUrl": "https://cloud.video.lazada.com/play/u/1359405/p/1/e/6/t/1/d/sd/8000130846425.mp4",
  "variantOptions": [{ "name": "Specification", "values": ["Rice Cooker 2L", "Low-Gi Rice Cooker"] }],
  "variants": [{ "skuId": "21185247689", "options": { "Specification": "Rice Cooker 2L" }, "image": "https://my-test-11.slatic.net/p/56458290568e6b8baefe706c7368e435.jpg", "url": "https://www.lazada.com.my/products/electrova-...-i3739956594-s21185247689.html" }],
  "detailsScraped": true,
  "reviews": [{
    "reviewId": "470786050656594",
    "rating": 5,
    "text": "inside is very sturdy thick stainless steel bowl. i used it once to cook normal rice. ...",
    "date": "2026-09-26",
    "dateText": "2 weeks ago",
    "reviewerName": "Lim Xuewei",
    "isAnonymous": false,
    "variant": "Specification:Low-Gi Rice Cooker",
    "images": ["https://lzd-u.slatic.net/136850a1fae24a9e9fd09bbbd7036d0e_7_1790097832.434250.jpg"],
    "likes": 2,
    "isPurchased": true,
    "sellerReply": "Hi dear, we really appreciate you taking the time to share your rating with us. ..."
  }],
  "ratingDistribution": { "5": 100, "4": 5, "3": 1, "2": 0, "1": 0 },
  "scrapedAt": "2026-10-10T03:10:49Z"
}
```

### How to scrape Lazada prices in Thailand, Indonesia, Vietnam and the other countries

Every product is read from the site it belongs to, with prices in that site's currency (`currency` tells which). Search
terms run on the site chosen in **Country**. For several countries in one run, add search URLs from each site to **Start
URLs**, for example `https://www.lazada.co.th/catalog/?q=power+bank` and `https://www.lazada.vn/catalog/?q=power+bank`.
Category names and review dates come in English; titles, descriptions and variant names are as the seller wrote them.

### How to scrape Lazada reviews

Set **Reviews per product** (for example 20). Each product then gets a `reviews` list in Lazada's default order, up to
that number, plus the star distribution. Reviewer names are exported as Lazada shows them. Lazada masks anonymous
reviewers (`J***m`), and those come out as `reviewerName: null` with `isAnonymous: true`. Dates shown as "2 weeks ago" are
converted to a calendar date (`date`), and the original text stays in `dateText`. To get the reviews of specific
products, paste their product URLs into **Start URLs**.

### How to scrape a Lazada product URL

Paste the product page URL (`…/products/…-i3539123466.html`). The Actor opens the product page for the description,
category path, gallery, video and every variant. It then searches the product's title on the same site to get its
listing card: price, original price, discount, sold count, seller, location and badges. If the product does not show up
in that search (1 of 6 products in our platform tests), `cardFound` is `false`. The current price, rating and review count then come
from the product's review data, and the card-only fields (original price, sold count, seller name, location) stay empty.

### Monitor changes on a schedule

Turn on **Only new or changed items** and the Actor remembers what earlier runs of the same input returned. Each run then
outputs only products that are new in the watched results or whose price, struck-through original price or stock
changed. Unchanged products are dropped before any product page or review is requested, so they are not charged.
**Max products** becomes the window checked on every run, e.g. the first 40 results of a search. Save the input as a
task and add a Schedule to it in Apify Console (Schedules → Create new, for example daily). Every output product carries
`changeType` (`new` or `changed`). Changed ones also carry `previousValues`, e.g. `{"price": 129}` for a rice cooker that
now costs 118. Sold counts, ratings and review counts change all the time and do not count as changes. The steadiest
watch is a store's or brand's product list. Paste its "All Products" URL (for example
`https://www.lazada.sg/bose/?q=All-Products&from=wangpu&langFlag=en&pageTypeId=2`): our test run output 26 products
on day one and 0 on the next run. Search results are personalised by Lazada, so a search watch also reports products
that rotate into the window as `new`. Each product is reported only once, and the share drops after the first runs; we
saw 9 of 40 on the second run. Use **Monitoring key** to keep several schedules on the same input separate.

### Does it work without login or a browser?

Yes. It reads Lazada's own public JSON and product pages over plain HTTP: no account, no cookies from you, no browser.

### Proxy note and run cost

Lazada protects its product lists with an Alibaba slider captcha that blocks datacenter **and** residential proxy IPs.
We measured 0 of 48 search pages from residential IPs and 1 of 72 from datacenter IPs. So the Actor uses Apify's
**Unblocker** proxy by default. Each successful Unblocker request costs about $0.0015 of proxy usage (10 units) and
returns 40 products, so about **$0.04 per 1,000 products** plus a little compute. Product pages and reviews are fetched
through residential IPs of the product's own country, about 20 KB each, which is a fraction of a cent. If one is
blocked, the Actor retries it through the Unblocker. Proxy usage is billed by Apify to your account next to the per-event
prices below. If you choose a different proxy, it is used as given for everything. Lazada will then most likely block the
product lists, and the run log says so.

### Pricing

Pay per event, no start fee:

- **Product scraped**: $0.0028 per product from a search, category, brand or store page.
- **Product page opened**: +$0.001 per product when details are on (always on for product URLs).
- **Review scraped**: $0.001 per review.

Plus Apify platform usage (proxy and compute, about $0.05 per 1,000 products without details).

### Integrations and API

Use the results from Make, Zapier, n8n, Google Sheets or your own code through the Apify API, or get notified by
webhook when a run finishes.

### Is it legal to scrape Lazada?

The Actor collects only data that Lazada shows publicly to any visitor: product listings, prices, seller (shop) names
and public reviews with the reviewer name as Lazada displays it. It does not log in. It does not export masked or hidden
values, so anonymous reviewers stay anonymous, and it collects no buyer contact details. You are responsible for how you
use the data and for complying with Lazada's terms and the data-protection law that applies to you, especially if you
store reviewer names.

### Support

Found a bug or need a field added? Open an issue in the **Issues** tab; it is usually answered within a day.

# Actor input Schema

## `searchTerms` (type: `array`):

Keywords to search on the Lazada site chosen in Country, one per line (e.g. "wireless earbuds", "rice cooker"). Each term is searched separately and paginated automatically (40 products per page).

## `country` (type: `string`):

Which Lazada site the search terms run on. Start URLs always use the site in their own address.

## `startUrls` (type: `array`):

Lazada URLs from any of the six sites, instead of (or in addition to) search terms: search pages (https://www.lazada.sg/catalog/?q=power+bank), category pages (https://www.lazada.com.my/shop-mobiles/), brand or store product lists, with any filters you set on the site (price, rating, location), or single product pages (https://www.lazada.co.th/products/...-i123456789.html, returned with full details).

## `maxItems` (type: `integer`):

Stop after this many products in total (across all search terms and URLs). Keeps cost predictable.

## `maxPagesPerSearch` (type: `integer`):

How many result pages to open per search term or listing URL (40 products each). Lazada serves at most 102 pages (4,080 products) per listing.

## `sortBy` (type: `string`):

Result order for search terms and listing URLs: best match (Lazada's default) or price low to high / high to low. Lazada offers no other sort.

## `includeDetails` (type: `boolean`):

Also open every product's page to get the full description text and images, category path, the complete image gallery, video, every variant (options such as color / size with their SKU id, image and URL) and stock status. Charged extra per product (see pricing). Product URLs always include details.

## `maxReviewsPerProduct` (type: `integer`):

Number of customer reviews to add to every product (0 = none): rating, text, date, reviewer name as shown, purchased variant, photos, video and seller reply, plus the star distribution. Reviews come in Lazada's default order. Charged per review (see pricing).

## `onlyNewOrChanged` (type: `boolean`):

Remember what earlier runs of this search returned and output only new items or items whose price/status changed. Use with a Schedule; unchanged items are not charged. Compared: price, struck-through original price and stock; sold counts, ratings and review counts are ignored. With this on, Max products is the number of products checked each run (the watched window, e.g. the first 40 results), and details / reviews are fetched only for new or changed products.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same search stay separate; defaults to a key derived from the search input.

## `proxyConfiguration` (type: `object`):

Keep the default Apify Unblocker proxy: Lazada blocks its product-list data for datacenter and residential IPs. Each successful Unblocker request costs about $0.0015 in proxy usage (10 units) and returns 40 products, so about $0.04 per 1,000 products. With this default, product pages and reviews go through cheaper residential IPs of the product's own country (falling back to the Unblocker). A different proxy is used as given for everything.

## Actor input object example

```json
{
  "searchTerms": [
    "wireless earbuds"
  ],
  "country": "SG",
  "startUrls": [],
  "maxItems": 100,
  "maxPagesPerSearch": 10,
  "sortBy": "popularity",
  "includeDetails": false,
  "maxReviewsPerProduct": 0,
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchTerms": [
        "wireless earbuds"
    ],
    "startUrls": [],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "UNBLOCKER"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tortuga/lazada-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchTerms": ["wireless earbuds"],
    "startUrls": [],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["UNBLOCKER"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("tortuga/lazada-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchTerms": [
    "wireless earbuds"
  ],
  "startUrls": [],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ]
  }
}' |
apify call tortuga/lazada-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tortuga/lazada-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/zdO13R6yAhfrVZ0E3/builds/Js6M61XMVbJCbSY4n/openapi.json
