# Lazada Singapore Products Scraper (`scrapyx/lazada-products-scraper`) Actor

Product search results from Lazada Singapore: name, price and original price in SGD, discount, rating and review count, seller, brand, ships-from location, stock and product URL. Search any keyword, sort by price, filter by price range.

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

## Pricing

from $0.56 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Singapore Products Scraper

Product search results from **Lazada Singapore**: product name, **price and
original price in SGD**, discount, **rating and review count**, seller, brand,
where it ships from, stock status, image and product URL.

Search any keyword, sort by price, filter by a price range. Reads the same
catalog data the lazada.sg search page loads. No login, no browser.

### What it is for

- **Price monitoring** and competitor tracking on Singapore's major marketplace.
- **Seller and brand research** — who sells what, at what price, from where.
- **Assortment and discount analysis** by keyword.

### Input

| field | what it does |
| --- | --- |
| `queries` | One search each, e.g. `air fryer`, `iphone 17`. |
| `sortBy` | `best_match`, `price_low_high`, `price_high_low` (each checked to actually sort). |
| `priceMin`, `priceMax` | Price range in S$ (0 = open). |
| `maxItems` | Products per query (default 100; 40 per page). |
| `maxPages` | Default 25; see "Captcha" below. |

### Five things worth knowing before you trust the data

#### 1. A query Lazada can't match returns unrelated products

Searching a nonsense word gets "7,001 items found" — all iPhone accessories —
not zero. This Actor checks how many first-page product names actually contain
a word of your query; below 20% it returns **no rows** for that query and says
why (`queryMatched: false`), instead of a dataset of unrelated products under
your search term. The share is reported on every search (`queryMatchShare`).

#### 2. Two different totals

"iphone": the page says **33,861 items found**, but Lazada will only ever show
**4,080** of them (102 pages × 40). The summary reports both
(`itemsFoundClaim`, `reachableTotal`).

#### 3. The last page is flagged, not empty

Past its last page Lazada keeps returning 40 products, with a `noMorePages`
flag. A scraper that waits for an empty page never stops. This one stops on
the flag and never asks past the reported page count.

#### 4. Page one can be a brand-store takeover

For "iphone", page 1 holds just 8 products from the Apple Flagship Store;
page 2 has 40. A short first page is not the end.

#### 5. Numbers arrive as text

Prices, discounts and ratings are strings, with `""` for "no rating yet".
They are kept as published and parsed into `priceSgd`, `originalPriceSgd`,
`discountPercent`, `rating` and `reviewCount` (`null` when absent — never 0).

Price sorting ranks everything that matches a query word: "air fryer",
highest price first, starts with a built-in oven that has an air-fry mode.

### Captcha

Lazada is protected by Alibaba's anti-bot, which answers with a captcha page
(not an error) when it objects. Measured: normal searches from Apify's own
servers passed; nonsense queries, very deep paging and Singapore
**residential** proxies drew the captcha on every request. So the proxy is
off by default, pages are unhurried, and a captcha is retried once or twice
and then reported as an error row — never returned as empty data. If you see
it, use fewer pages or a more specific query.

### Output

```json
{
  "recordType": "PRODUCT",
  "name": "SAMSUNG NV7B6675CAA/SP 76L BESPOKE BUILT-IN OVEN | Air Fry | ...",
  "priceSgd": 2699,
  "rating": 5,
  "reviewCount": 1,
  "sellerName": "Mega Discount Store",
  "location": "Singapore",
  "productUrl": "https://www.lazada.sg/products/pdp-i238457322.html"
}
```

Every row also carries Lazada's complete item object (SKU ids, category ids,
thumbnails, promotion icons, sold count where shown).

# Actor input Schema

## `queries` (type: `array`):

One search per entry, as you would type it on lazada.sg. A query Lazada cannot match returns unrelated products there — this Actor detects that and returns no rows for it instead.

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

Lazada's own orderings.

## `priceMin` (type: `integer`):

0 = no minimum.

## `priceMax` (type: `integer`):

0 = no maximum.

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

Up to 40 per page. 0 = as many as maxPages allows.

## `maxPages` (type: `integer`):

Very deep paging is what makes Lazada show its captcha; Lazada itself stops at 102 pages.

## `maxConcurrency` (type: `integer`):

Queries in parallel.

## `minRequestInterval` (type: `number`):

Unhurried by default: pace is part of what Lazada watches.

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

Off by default, by measurement: Apify's own servers passed normal searches, while Singapore residential addresses were shown Lazada's captcha on every request.

## Actor input object example

```json
{
  "queries": [
    "air fryer",
    "iphone 17"
  ],
  "sortBy": "best_match",
  "priceMin": 0,
  "priceMax": 0,
  "maxItems": 100,
  "maxPages": 25,
  "maxConcurrency": 2,
  "minRequestInterval": 2,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `items` (type: `string`):

One row per scraped record. See the dataset's default view for field definitions.

# 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 = {
    "queries": [
        "air fryer",
        "iphone 17"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapyx/lazada-products-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 = { "queries": [
        "air fryer",
        "iphone 17",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("scrapyx/lazada-products-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 '{
  "queries": [
    "air fryer",
    "iphone 17"
  ]
}' |
apify call scrapyx/lazada-products-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapyx/lazada-products-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/WqHJadabjHeGapbpF/builds/mvwuztyKwFROwR0SB/openapi.json
