# Vietnam Shopping Products Scraper (`getdataforu/products-shopping`) Actor

Scrape products by keyword from Tiki, Lazada, Chợ Tốt and Google Shopping. Returns URL, title, price, sale price, discount, image, brand, seller, rating and sold count. Supports language/price filters, sorting and URL dedup across sources.

- **URL**: https://apify.com/getdataforu/products-shopping.md
- **Developed by:** [EMT Crawler](https://apify.com/getdataforu) (community)
- **Categories:** E-commerce, SEO tools, Other
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.00001 / actor start

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Actor: products-shopping

Apify actor **cào sản phẩm shopping theo từ khóa** từ nhiều nguồn. Dùng để dựng giao diện
kiểu Google Shopping: mỗi sản phẩm có `url`, `title`, `price`, `salePrice`, `image`, `merchant`, `rating`...

Built với [Crawlee](https://crawlee.dev/) + [CheerioCrawler](https://crawlee.dev/api/cheerio-crawler/class/CheerioCrawler)
(HTTP, không render JS).

> 📘 Hướng dẫn & giải thích chi tiết (đầu vào/đầu ra, kiến trúc, publish, mở rộng, xử lý sự cố):
> [`docs/HUONG_DAN.md`](docs/HUONG_DAN.md)

### Nguồn cào hiện có

| key      | Cách lấy                         | Độ tin cậy | Ghi chú                                        |
| -------- | -------------------------------- | ---------- | ---------------------------------------------- |
| `tiki`   | API JSON `tiki.vn/api/v2/products` | ⭐ Cao     | Giá/giá gốc/ảnh/rating/đã bán sạch, không cần proxy |
| `lazada` | API JSON `lazada.vn/catalog/?ajax=true` | ⭐ Cao | mods.listItems; nên bật proxy nếu bị chặn      |
| `chotot` | API JSON `gateway.chotot.com/v1/public/ad-listing` | ⭐ Cao | Sàn rao vặt lớn (hàng mới + cũ); tin giá 0 tự bị lọc |
| `bing`   | Bing Shopping HTML               | ⚠ Thử nghiệm | Qua HTTP thường bị redirect/JS-shell → 0 kết quả; cần Playwright |

> **Lọc giá rác:** sản phẩm giá VND < 1.000 ₫ (listing bait, vd "₫121") bị loại tự động
> (`isValidProduct` trong `normalize.js`).
>
> **Vì sao Google/Bing/Shopee không có?** Các trang này render bằng JavaScript hoặc chống bot
> mạnh nên **không** cào được bằng CheerioCrawler (HTTP thuần). Đã thử & xác nhận: Shopee chặn
> (`error 90309999`), Bing redirect, Sendo/Sàn khác trả challenge. Muốn cào Google Shopping cần
> chuyển sang **PlaywrightCrawler** — xem mục "Các hướng đi".

### Output (mỗi item trong dataset)

```jsonc
{
  "query": "váy",
  "source": "tiki",
  "position": 1,
  "title": "Chân Váy Thời Trang Kiểu Đuôi Cá...",
  "url": "https://tiki.vn/...-p278476178.html",
  "price": 250000,          // giá gốc (list price)
  "salePrice": 139000,      // giá khuyến mãi (null nếu không giảm)
  "discountRate": 44,       // % giảm (nguồn cấp hoặc suy ra từ price/salePrice)
  "currency": "VND",
  "image": "https://salt.tikicdn.com/.../x.png",
  "images": ["https://salt.tikicdn.com/.../x.png"],
  "brand": "MAYHOMES",      // thương hiệu
  "category": "Chân váy dài",// ngành hàng (Tiki có, Lazada để null)
  "merchant": "MAYHOMES Official Store",
  "rating": 5,
  "reviews": 2,
  "sold": 88,               // số đã bán
  "scrapedAt": "2026-06-30T..."
}
````

> Quy ước `price` / `salePrice` khớp `price_vnd` / `sale_price_vnd` trong app daisan-search
> (`src/lib/advertisedProductsClient.ts`) — ghép vào UI không cần đổi tên field.

### Chạy local

```bash
npm install
npm test              # unit test parse giá + parser HTML (offline, không cần mạng)

apify run             # đọc input từ storage/key_value_stores/default/INPUT.json
## hoặc:
node src/main.js
```

Kết quả ở `storage/datasets/default/*.json`.

### Deploy

```bash
npm -g install apify-cli
apify login
apify push
```

### Input

| Field              | Kiểu     | Mặc định            | Ý nghĩa                               |
| ------------------ | -------- | ------------------- | ------------------------------------- |
| `queries`          | string\[] | `["váy"]`           | Từ khóa (bắt buộc)                    |
| `sources`          | string\[] | `["tiki","lazada"]` | Nguồn cào                             |
| `maxItems`         | int      | `0`                 | **Tổng** sản phẩm cả run (0 = tắt). Đặt `100` để lấy đúng 100 |
| `maxItemsPerQuery` | int      | `40`                | Giới hạn / (từ khóa × nguồn); >40 tự phân trang. Bỏ qua nếu đặt `maxItems` |
| `sortBy`           | enum     | `relevance`         | `relevance`/`newest`/`best_selling`/`price_asc`/`price_desc` |
| `minPrice`         | int      | `0`                 | Giá bán tối thiểu (VND), 0 = bỏ qua   |
| `maxPrice`         | int      | `0`                 | Giá bán tối đa (VND), 0 = bỏ qua      |
| `productLanguage`  | enum     | `vi`                | Ngôn ngữ sản phẩm: `any`/`vi`/`en`    |
| `country`          | string   | `vn`                | mã quốc gia (cc)                      |
| `language`         | string   | `vi`                | mã ngôn ngữ                           |
| `proxyConfiguration` | object | `{useApifyProxy:false}` | proxy Apify                      |

Xem `input.json` ở thư mục gốc làm ví dụ.

### Tính năng

- **Lọc theo ngôn ngữ** (`productLanguage`: `any`/`vi`/`en`, mặc định `vi`): `vi` giữ tên có dấu tiếng Việt (loại hàng xuyên biên giới tên Anh/Trung); `en` giữ tên tiếng Anh; `any` không lọc. Chữ CJK/Thái luôn bị loại ở `vi`/`en`.
- **Phân bổ đều theo nguồn:** khi đặt `maxItems`, kết quả được chia đều giữa các nguồn bằng round-robin (xen kẽ tiki/lazada/chợ tốt); nguồn nào thiếu hàng thì **tự bù từ nguồn khác** cho đủ tổng.
- **Sắp xếp & lọc giá:** `sortBy` (liên quan/mới nhất/bán chạy/giá tăng/giá giảm) — áp ở nguồn (Tiki/Lazada) + sort client-side cuối cùng đảm bảo đúng thứ tự. `minPrice`/`maxPrice` lọc theo khoảng giá.
- **Đa nguồn + đa từ khóa:** chạy đồng thời (từ khóa × nguồn), gộp về một dataset.
- **Phân trang:** `maxItemsPerQuery` > 40 tự kéo nhiều trang (Tiki/Lazada 40 item/trang, tối đa 200 = 5 trang).
- **Làm giàu dữ liệu:** `price`, `salePrice`, `discountRate`, `brand`, `category`, `merchant`, `rating`, `reviews`, `sold`.
- **Khử trùng URL** trên toàn run (chống trùng giữa các trang & nguồn).
- **Lọc giá rác** (listing bait giá VND < 1.000 ₫).
- **Tự thử lại** khi sàn chặn tạm thời (`maxRequestRetries: 3`).

### Kiến trúc (dễ mở rộng)

```
src/
├── main.js        # đọc input, fan-out (từ khóa × nguồn), chạy CheerioCrawler
├── sources.js     # định nghĩa nguồn: cách build URL/request  ← thêm nguồn mới ở đây
├── routes.js      # router theo label: handler TIKI / LAZADA (JSON), BING (HTML)
├── mappers.js     # map item thô từng sàn (Tiki, Lazada) -> item chuẩn (test offline)
├── parseHtml.js   # parser HTML heuristic dùng chung (không bám class name)
└── normalize.js   # parse giá VN/USD, rating, reviews; quy ước price/salePrice; lọc giá rác
```

**Thêm 1 nguồn JSON mới** (vd Shopee): (1) thêm entry vào `SOURCES` trong `sources.js`
(build URL + label); (2) viết `mapXxxItem` trong `mappers.js`; (3) thêm
`router.addHandler('<LABEL>', ...)` trong `routes.js` gọi mapper + `isValidProduct`.
Nguồn HTML thì dùng lại `parseHtmlProducts` (như handler BING).

***

### Các hướng đi để cào sản phẩm shopping

#### Hướng 1 — API JSON của sàn TMĐT (actor này: `tiki`, `lazada`, `chotot`)

- Gọi thẳng endpoint search JSON của sàn.
- **Ưu:** dữ liệu sạch, đúng VND, có sẵn giá gốc/giá KM/rating/người bán; không cần render JS;
  Tiki/Chợ Tốt không cần proxy, Lazada thỉnh thoảng cần.
- **Nhược:** mỗi sàn một endpoint + một mapper riêng. **Đã thử & KHÔNG dùng được qua HTTP:**
  Shopee (`error 90309999`), Sendo (rỗng), Thế Giới Di Động/Điện Máy Xanh (trang challenge) →
  cần Playwright + cookie/bypass.

#### Hướng 2 — Parse HTML SERP shopping (actor này, nguồn `bing` — thử nghiệm)

- CheerioCrawler tải HTML rồi `parseHtml.js` bóc card bằng heuristic (img → leo lên `<a>` → tìm giá).
- **Thực tế:** Bing `/shop` qua HTTP thuần bị redirect sang JS-shell → 0 kết quả. Parser vẫn hữu ích
  khi cấp HTML đã render (vd từ Playwright) hoặc cho các trang shop server-render khác.

#### Hướng 3 — Google Shopping qua PlaywrightCrawler (cần chuyển template)

- Giao diện `udm=28` là JS-heavy → phải render bằng trình duyệt.
- Cách làm: đổi dependency sang `@crawlee/playwright` + `playwright`, đổi base image Docker sang
  `apify/actor-node-playwright-chrome`, mở trang `google.com/search?q=...&udm=28`, cuộn lazy-load,
  rồi dùng lại logic heuristic của `parseHtml.js` (chuyển sang `page.evaluate`).
- **Ưu:** đúng dữ liệu Google như ảnh demo. **Nhược:** chậm/tốn tài nguyên hơn, **bắt buộc proxy RESIDENTIAL**.

#### Hướng 4 — SERP API trả phí (SerpApi / Oxylabs / Bright Data)

- Trả JSON Google Shopping sạch, không lo chống bot. **Nhược:** trả phí theo request + cần API key.
- Chưa hiện thực trong actor này (có thể thêm sau nếu cần).

> **Khuyến nghị:** dùng **Hướng 1** (Tiki/Lazada/Chợ Tốt) làm nguồn chính miễn phí cho dữ liệu VN;
> cần Shopee/Google thì cân nhắc **Hướng 3 (Playwright)** hoặc **Hướng 4 (SERP API)**.

### Tích hợp với app daisan-search

Output đã chuẩn hóa sẵn. Trỏ edge function `apify-run` / `apify-runner`
(trong repo daisan-search, `supabase/functions/`) tới actor này thay vì actor marketplace —
các field (`title`, `url`, `price`, `salePrice`, `image`, `currency`) đã trùng tên nên hàm
`normalize()` gần như không cần sửa.

# Actor input Schema

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

List of keywords. Each keyword is scraped on every selected source.

## `sources` (type: `array`):

tiki/lazada/chotot = free JSON API (reliable over plain HTTP). bing = experimental (HTML, usually needs proxy/Playwright).

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

Cap on the TOTAL products for the whole run, split evenly across sources (round-robin) with cross-fill. 0 = unlimited (use maxItemsPerQuery). Set 100 to get at most 100 products.

## `maxItemsPerQuery` (type: `integer`):

Limit per (keyword × source). Ignored when maxItems (total) is set.

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

Result ordering. Applied at the source where supported (Tiki/Lazada), plus a final client-side sort for price/best-selling. Chợ Tốt only supports default order.

## `minPrice` (type: `integer`):

Only keep products with selling price >= this value. 0 = no minimum.

## `maxPrice` (type: `integer`):

Only keep products with selling price <= this value. 0 = no maximum.

## `productLanguage` (type: `string`):

Keep only products whose title matches this language. 'any' = no language filter; 'vi' = Vietnamese titles; 'en' = English (Latin, no Vietnamese diacritics). Foreign scripts (Chinese/Thai/...) are dropped for vi/en.

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

Two-letter country code for regional search (e.g. vn for Vietnam). Used by Bing Shopping when enabled.

## `language` (type: `string`):

Interface language code for regional search (e.g. vi for Vietnamese). Used by Bing Shopping when enabled.

## `maxRequestsPerCrawl` (type: `integer`):

Hard cap on HTTP requests per run (safety guard against runaway loops).

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

Tiki/Chợ Tốt usually work without a proxy. Enable Apify Proxy (RESIDENTIAL) for Lazada/Bing if blocked.

## Actor input object example

```json
{
  "queries": [
    "váy",
    "áo khoác nữ"
  ],
  "sources": [
    "tiki",
    "lazada",
    "chotot"
  ],
  "maxItems": 0,
  "maxItemsPerQuery": 40,
  "sortBy": "relevance",
  "minPrice": 0,
  "maxPrice": 0,
  "productLanguage": "vi",
  "country": "vn",
  "language": "vi",
  "maxRequestsPerCrawl": 100,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `overview` (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 = {
    "queries": [
        "váy"
    ],
    "sources": [
        "tiki",
        "lazada",
        "chotot"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("getdataforu/products-shopping").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": ["váy"],
    "sources": [
        "tiki",
        "lazada",
        "chotot",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("getdataforu/products-shopping").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": [
    "váy"
  ],
  "sources": [
    "tiki",
    "lazada",
    "chotot"
  ]
}' |
apify call getdataforu/products-shopping --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=getdataforu/products-shopping",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Vietnam Shopping Products Scraper",
        "description": "Scrape products by keyword from Tiki, Lazada, Chợ Tốt and Google Shopping. Returns URL, title, price, sale price, discount, image, brand, seller, rating and sold count. Supports language/price filters, sorting and URL dedup across sources.",
        "version": "1.0",
        "x-build-id": "glAaHBFWquFqmAsGU"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/getdataforu~products-shopping/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-getdataforu-products-shopping",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/getdataforu~products-shopping/runs": {
            "post": {
                "operationId": "runs-sync-getdataforu-products-shopping",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/getdataforu~products-shopping/run-sync": {
            "post": {
                "operationId": "run-sync-getdataforu-products-shopping",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "queries"
                ],
                "properties": {
                    "queries": {
                        "title": "Search keywords",
                        "type": "array",
                        "description": "List of keywords. Each keyword is scraped on every selected source.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "sources": {
                        "title": "Sources",
                        "type": "array",
                        "description": "tiki/lazada/chotot = free JSON API (reliable over plain HTTP). bing = experimental (HTML, usually needs proxy/Playwright).",
                        "items": {
                            "type": "string",
                            "enum": [
                                "tiki",
                                "lazada",
                                "chotot",
                                "bing"
                            ],
                            "enumTitles": [
                                "Tiki",
                                "Lazada",
                                "Chợ Tốt"
                            ]
                        },
                        "default": [
                            "tiki",
                            "lazada",
                            "chotot"
                        ]
                    },
                    "maxItems": {
                        "title": "Max total products (whole run)",
                        "minimum": 0,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Cap on the TOTAL products for the whole run, split evenly across sources (round-robin) with cross-fill. 0 = unlimited (use maxItemsPerQuery). Set 100 to get at most 100 products.",
                        "default": 0
                    },
                    "maxItemsPerQuery": {
                        "title": "Max products per keyword per source",
                        "minimum": 1,
                        "maximum": 200,
                        "type": "integer",
                        "description": "Limit per (keyword × source). Ignored when maxItems (total) is set.",
                        "default": 40
                    },
                    "sortBy": {
                        "title": "Sort by",
                        "enum": [
                            "relevance",
                            "newest",
                            "best_selling",
                            "price_asc",
                            "price_desc"
                        ],
                        "type": "string",
                        "description": "Result ordering. Applied at the source where supported (Tiki/Lazada), plus a final client-side sort for price/best-selling. Chợ Tốt only supports default order.",
                        "default": "relevance"
                    },
                    "minPrice": {
                        "title": "Min price (VND)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only keep products with selling price >= this value. 0 = no minimum.",
                        "default": 0
                    },
                    "maxPrice": {
                        "title": "Max price (VND)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only keep products with selling price <= this value. 0 = no maximum.",
                        "default": 0
                    },
                    "productLanguage": {
                        "title": "Product language",
                        "enum": [
                            "any",
                            "vi",
                            "en"
                        ],
                        "type": "string",
                        "description": "Keep only products whose title matches this language. 'any' = no language filter; 'vi' = Vietnamese titles; 'en' = English (Latin, no Vietnamese diacritics). Foreign scripts (Chinese/Thai/...) are dropped for vi/en.",
                        "default": "vi"
                    },
                    "country": {
                        "title": "Country (cc)",
                        "type": "string",
                        "description": "Two-letter country code for regional search (e.g. vn for Vietnam). Used by Bing Shopping when enabled.",
                        "default": "vn"
                    },
                    "language": {
                        "title": "Language (hl)",
                        "type": "string",
                        "description": "Interface language code for regional search (e.g. vi for Vietnamese). Used by Bing Shopping when enabled.",
                        "default": "vi"
                    },
                    "maxRequestsPerCrawl": {
                        "title": "Max HTTP requests",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Hard cap on HTTP requests per run (safety guard against runaway loops).",
                        "default": 100
                    },
                    "proxyConfiguration": {
                        "title": "Proxy",
                        "type": "object",
                        "description": "Tiki/Chợ Tốt usually work without a proxy. Enable Apify Proxy (RESIDENTIAL) for Lazada/Bing if blocked.",
                        "default": {
                            "useApifyProxy": false
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
