# Dienmayxanh Scraper - Products, Prices, Specs & Reviews (`abotapi/dienmayxanh-scraper`) Actor

Scrape dienmayxanh.com home appliances and electronics with full specifications, current & original price, discount, brand, category, variants, images, description, customer rating and reviews. Search by keyword with brand, price, rating and sort filters, or paste product / category / search URLs.

- **URL**: https://apify.com/abotapi/dienmayxanh-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** E-commerce, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 5 total users, 0 monthly users, 93.1% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 product results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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

## Điện Máy Xanh Scraper: Prices, Deals and Customer Reviews

Điện Máy Xanh Scraper turns dienmayxanh.com into a clean product data feed for one of Vietnam's largest home appliance and consumer electronics retailers. Get the current price, the genuine original ("was") price and discount for every product that is actually on special, Flash Sale and seasonal promo deals, full specifications and variants, the image gallery, the full category path, the aggregate customer rating, and the star rated reviews shown on each product page. Search by keyword with brand, price and rating filters, browse the permanent Flash Sale hub with a toggle, or paste product, category, search or promo page links, then export to JSON, CSV or Excel, or pull results straight into your app through the API.

### Why This Scraper?

- **Two ways to collect.** Search by keyword with brand, price range, minimum rating and six sort orders, or paste product, category, search or promo page links directly, no URL building required.
- **Genuine discount tracking, never fabricated.** The original ("was") price, discount amount and discount percentage are only ever populated for a product that is actually on special; an ordinary product reports `isOnSpecial: false` with those fields empty. The gift offer and installment label are read directly from the page whenever the site shows them, independent of whether the product is on special.
- **Flash Sale and seasonal promo pages.** Browse the site's permanent Flash Sale hub with one toggle, or paste any seasonal category promo page link to pull its deals.
- **Full product detail on demand.** Specifications, variants (where a model has them, with per-variant price and stock status), image gallery, full category breadcrumb, description and aggregate rating, switched on per run.
- **Star rated customer reviews.** Author, date, rating and review text collected from the product page itself, with unrated question-and-answer entries excluded.
- **Filters and sorting apply everywhere.** Brand, price range, minimum rating and the six sort orders act on whatever set of products was collected, whether from a keyword search or a pasted URL.
- **Resume and recurring tracking.** Continue one interrupted run without paying to recollect what you already have, or turn on Incremental mode to track the same search across scheduled runs and get only what changed.

### Use Cases

- **Price trackers and deal alert tools:** monitor Flash Sale and seasonal promo discounts, was price and savings, to alert shoppers to genuine drops.
- **E-commerce competitor research:** compare appliance and electronics pricing, brand coverage and specifications across categories.
- **Review and reputation analysis:** collect star rated customer reviews and aggregate ratings to gauge sentiment on specific models.
- **Catalogue and inventory audits:** pull full specifications, variants and stock status for a brand or category to keep a downstream catalogue in sync.
- **Recurring monitoring:** schedule the actor with Incremental mode to get only newly listed, price-changed or restocked products instead of re-downloading the whole catalogue every time.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live record.

| Field | Example |
| --- | --- |
| `code` | `"241187"` |
| `productCode` | `"4092214003355"` |
| `sku` | `"241187"` |
| `name` | `"Tủ lạnh Halvex Inverter 250 lít HV25R-INV"` |
| `url` | `"https://www.dienmayxanh.com/tu-lanh/halvex-inverter-250-lit-hv25r-inv"` |
| `brand` | `"Halvex"` |
| `category` / `categoryPath` | `"Tủ lạnh"` / `["Tủ lạnh", "Tủ lạnh Halvex"]` |
| `color` | `"Trắng"` |
| `price` | `6490000` |
| `originalPrice` | `7990000` |
| `discount` / `discountPercent` | `"-18.8%"` / `18.8` |
| `savings` | `1500000` |
| `isOnSpecial` | `true` |
| `currency` | `"VND"` |
| `rating` / `reviewCount` | `4.7` / `356` |
| `ratingBreakdown` | `{ "bestRating": 5, "worstRating": 1 }` |
| `specifications` | `{ "Kiểu tủ": "Ngăn đá dưới", "Dung tích": "250 lít", "Công nghệ Inverter": "Có" }` |
| `variants` | `[{ "name": "250L - Trắng", "price": 6490000, "availability": "InStock" }]` |
| `images` | `["https://cdn.tgdd.vn/Products/Images/2054/241187/halvex-hv25r-inv-1.jpg"]` |
| `description` | `"Tủ lạnh Halvex Inverter 250 lít - ngăn đá dưới, làm lạnh đa chiều, tiết kiệm điện..."` |
| `searchMode` | `"search"` (also `"url"`) |
| `source` | `"dienmayxanh.com"` |

Each record also carries `productGroupId` and `productId` (two more of the site's own identifiers), `promoGift` and `installmentOffer` (only when a genuine gift or 0%-installment label is shown on the product), `imageUrl` (a convenience copy of the first gallery image), `availability` and `label` (a card badge, when shown), and, with **Fetch customer reviews** on, a `reviews` array of `{author, date, rating, body}`. With **Incremental mode** on, each record also gains `changeType`, `changedFields`, `firstSeenAt` and `lastSeenAt` (see "Resume and recurring updates" below).

### How to Use

1. Pick a **mode**: `search` (keyword and filters) or `url` (paste links).
2. In search mode, enter one or more keywords, or turn on **Flash sale only** to browse the permanent deals hub instead.
3. Turn on **Fetch product details** for full specs, variants, gallery and rating, and **Fetch customer reviews** for the star rated reviews on each product page.
4. Set **Max products** to control run size and cost, then click **Start**.

**Search with brand, price and sort filters:**

```json
{
  "mode": "search",
  "queries": ["tủ lạnh"],
  "brand": "Samsung",
  "minPrice": 5000000,
  "maxPrice": 15000000,
  "sortBy": "priceAsc",
  "maxItems": 10
}
```

**Browse the Flash Sale deals hub:**

```json
{
  "mode": "search",
  "specialsOnly": true,
  "fetchDetails": false,
  "maxItems": 20
}
```

**Paste a category link, with detail and reviews on:**

```json
{
  "mode": "url",
  "urls": ["https://www.dienmayxanh.com/tu-lanh"],
  "fetchDetails": true,
  "fetchReviews": true,
  "maxReviewsPerProduct": 10,
  "maxItems": 15
}
```

**Track a search over repeated scheduled runs:**

```json
{
  "mode": "search",
  "queries": ["tủ lạnh"],
  "fetchDetails": true,
  "incrementalMode": true,
  "emitExpired": true,
  "maxItems": 0
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/dienmayxanh-scraper").call(run_input={"mode": "search", "queries": ["tủ lạnh"], "maxItems": 10})
for product in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(product["name"], product["price"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/dienmayxanh-scraper').call({ mode: 'search', queries: ['tủ lạnh'], maxItems: 10 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### Flash Sale and seasonal promo pages

#### URL mode: supported link shapes

| Shape | Example | Behaviour |
|---|---|---|
| Category listing | `https://www.dienmayxanh.com/tu-lanh` (also `/may-giat`) | Full grid, paged (20 products per request). |
| Keyword search | `https://www.dienmayxanh.com/tim-kiem?key=tu+lanh` | Search grid (the site redirects it to a category page with `?key=&sc=new`, which is handled too). |
| Product detail | `https://www.dienmayxanh.com/tu-lanh/samsung-rt22m4032by-sv` | One product. |
| Product with `?code=` | `.../samsung-rt22m4032by-sv?code=3051097001790` | One product. |
| Brand in category | `https://www.dienmayxanh.com/tu-lanh-samsung` | Full grid for that brand, paged. |
| Price filter | `https://www.dienmayxanh.com/tu-lanh?p=duoi-8-trieu` | Full filtered grid, paged. Partial scope. |
| Flash Sale hub | `https://www.dienmayxanh.com/flashsale` | Single curated page. |
| Seasonal promotion | `https://www.dienmayxanh.com/khuyen-mai-tu-lanh` | Promotion grid. |
| `?page=2` | `https://www.dienmayxanh.com/tu-lanh?page=2` | The site ignores the parameter; the grid is read from the start and a warning is logged. Partial scope: never marks products EXPIRED. |
| `?g=` / `?o=` | `https://www.dienmayxanh.com/tu-lanh?g=samsung&o=gia-thap-den-cao` | The site drops these; `g` is applied as the Brand filter and `o=gia-thap-den-cao` / `gia-cao-den-thap` as the sort, each with a logged warning. Partial scope. |
| Apex or mobile host | `https://dienmayxanh.com/tu-lanh` | Normalised to `www.dienmayxanh.com`. |
| Unsupported | `https://www.dienmayxanh.com/tu-lanh/samsung` (404) | Logged as a warning and skipped. |

**Default behaviour change:** the URLs field now has a default listing nine links: a category, a category on the bare domain, a keyword search, a product detail page with its reviews, the Flash Sale hub, a seasonal promotion, a brand-in-category page, a price-filter link and a price-sorted category link (`?o=gia-thap-den-cao`). The Search keywords field now defaults to `["tủ lạnh"]`. A run that leaves the field untouched scrapes those examples instead of nothing. Incremental baselines you already saved for explicit keywords or URLs keep working (the state key for them is unchanged).

Điện Máy Xanh's promotional surface has two kinds of pages. **Flash Sale** is a permanent, site-wide landing page of curated, time-limited deals: turn on **Flash sale only** in search mode, or paste its own link in URL mode. It is a single curated page with no further pagination of its own, so Max products (and Max listing pages) simply cap how many of its listed deals are returned. **Seasonal category promotions** are campaign pages that rotate with the current promotion cycle, so they are not exposed as a fixed picklist; paste the page's own link in URL mode to scrape it, and the same was-price and discount fields populate.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one specific interrupted run: paste its run id or dataset id and every product already collected there is skipped from the output and never billed again. Resume changes what gets pushed and charged at the end, not how many pages are fetched, and it does not extend the walk to compensate: a capped run still stops at its normal page and product limits, so if the same top-ranked products surface again, a resumed run on the same search can come back with very few, or zero, genuinely new products even though later pages were never reached. To keep collecting deeper, raise Max products or change the sort order rather than relying on Resume alone.
- **Incremental mode** (`incrementalMode`) tracks the same search or URLs across many scheduled runs on its own, no id to paste. Each run compares against a baseline it remembers itself (keyed by your search settings, or your own **State key**) and classifies every product as `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED`, `REAPPEARED` or `EXPIRED`. Unchanged products are neither returned nor billed unless **Emit unchanged products** is on. A product is only ever reported `EXPIRED` when **Emit expired products** is on and a run completes a full, uncapped, non-resumed scan of the whole search; that same completed scan is also the only thing that marks a missing product's stored state as no longer present. `REAPPEARED` can therefore only fire for a product that a previous run, with Emit expired products on, had already marked gone in a completed scan, and a later run finds again; it never fires just because a run happened to skip that product. A product is `UPDATED` when any returned field changes (price, discount, availability, promo gift, installment offer, rating, review count, details); the reviews list and image order never count. **Ignore fields when detecting changes** (`ignoreFieldsForChanges`) excludes more fields, including nested ones, without causing a wave of UPDATED rows when you change it. A pasted listing URL that starts at `?page=N` or carries filter parameters is a partial scan and never marks products EXPIRED.
- The baseline is keyed on your search settings (mode, keywords, brand, sort, price/rating filters, Flash Sale toggle, URLs, fetch details/reviews), not on Max products, Max listing pages, Max reviews per product or the connector export cap, so raising a limit keeps your existing baseline instead of starting over and re-billing everything.

#### Dataset views and billing

The dataset has four views: **Products** (the listing rows), **Product details** (specifications, variants, gallery), **Reviews** (one row per customer review, needs Fetch customer reviews) and **Changes** (Incremental mode change type and changed fields). Each run also writes an `OUTPUT` summary record.

Reviews: **Max reviews per product** defaults to 20 and is capped at 1000 (`0` means 1000). Billing is the pay-per-event model shown on the Pricing tab: a run start event, a result event for every product row, and the detail-enrichment event for every product whose detail page was read. Reviews are included in that same detail-enrichment unit: a product is charged one unit however many reviews it returns, as each product is saved. Incremental mode does not bill unchanged rows unless Emit unchanged is on.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped products into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape: the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each product, not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify → Settings → Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` (keyword and filters) or `url` (paste links). |
| `queries` | array | prefill: `["tủ lạnh"]` | Keywords to search, one query at a time; search mode only. |
| `specialsOnly` | boolean | `false` | Also browse the site-wide Flash Sale deals page alongside any keywords above. |
| `urls` | array | nine example links covering the main shapes in the URL shape table | Product, category, search or promotion links to scrape; url mode only. |
| `brand` | string | (none) | Keep only products whose brand contains this text. Applies to both modes. |
| `sortBy` | string | `relevance` | Reorders whatever set of products was collected: `relevance`, `priceAsc`, `priceDesc`, `ratingDesc`, `reviewsDesc` or `nameAsc`. |
| `minPrice` | integer | (none) | Keep only products priced at or above this amount, in VND. |
| `maxPrice` | integer | (none) | Keep only products priced at or below this amount, in VND. |
| `minRating` | integer | (none) | Keep only products with an average rating at or above this value (1 to 5); needs product details on. |
| `fetchDetails` | boolean | `false` | Add specifications, variants, image gallery, category path, description and aggregate rating; one extra request per product. Off by default for fast, low-cost listing runs. |
| `fetchReviews` | boolean | `false` | Also collect the star rated reviews on each product page. Read from the same detail page as Fetch product details; triggers that same detail-page fetch and surcharge on its own, Fetch product details does not need to be on. |
| `maxReviewsPerProduct` | integer | `20` | Cap on reviews collected per product, at most `1000`; `0` means the maximum of `1000`. |
| `maxItems` | integer | `20` | Maximum products returned across the whole run; `0` for unlimited. |
| `maxPages` | integer | (none; falls back to an internal safety cap) | Safety cap on listing pages fetched per search or category (about 20 products per page). |
| `resumeFromRunId` | string | (none) | Continue one interrupted run: paste its run id or dataset id and already-collected products are skipped. |
| `incrementalMode` | boolean | `false` | Track this same search or URLs over repeated scheduled runs, returning only NEW, UPDATED, REAPPEARED and (optionally) EXPIRED products. |
| `stateKey` | string | (none) | Optional name for the Incremental mode baseline. Empty auto-derives one from your search settings. |
| `emitUnchanged` | boolean | `false` | Incremental mode: also return (and bill) products with no change since the last run. |
| `emitExpired` | boolean | `false` | Incremental mode: also return (and bill) products no longer found, once a run completes a full scan. |
| `ignoreFieldsForChanges` | array | `[]` | Incremental mode only: field names that never make a product UPDATED (still returned in the output). A plain name matches at any depth, a dotted path matches one nested place. The reviews list and image order are always ignored. |
| `proxy` | object | residential, country `VN` | Connection settings. Residential in Vietnam is the default and is needed for page 2 onward, price sorts and reviews beyond the first ten; first pages also load from datacenter. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each product to apps authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which product pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on products written to each connector per run; does not affect the dataset. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live record.

```json
{
  "code": "241187",
  "productCode": "4092214003355",
  "sku": "241187",
  "name": "Tủ lạnh Halvex Inverter 250 lít HV25R-INV",
  "url": "https://www.dienmayxanh.com/tu-lanh/halvex-inverter-250-lit-hv25r-inv",
  "brand": "Halvex",
  "category": "Tủ lạnh",
  "categoryPath": ["Tủ lạnh", "Tủ lạnh Halvex"],
  "color": "Trắng",
  "price": 6490000,
  "originalPrice": 7990000,
  "discount": "-18.8%",
  "discountPercent": 18.8,
  "savings": 1500000,
  "isOnSpecial": true,
  "promoGift": "Quà tặng bình đun siêu tốc 200.000₫",
  "installmentOffer": "Trả chậm 0% trả trước 0đ",
  "currency": "VND",
  "rating": 4.7,
  "reviewCount": 356,
  "ratingBreakdown": { "bestRating": 5, "worstRating": 1 },
  "specifications": {
    "Kiểu tủ": "Ngăn đá dưới",
    "Dung tích": "250 lít",
    "Công nghệ Inverter": "Có"
  },
  "variants": [
    { "name": "250L - Trắng", "sku": "241187", "price": 6490000, "availability": "InStock" }
  ],
  "images": [
    "https://cdn.tgdd.vn/Products/Images/2054/241187/halvex-hv25r-inv-1.jpg"
  ],
  "description": "Tủ lạnh Halvex Inverter 250 lít - ngăn đá dưới, làm lạnh đa chiều, tiết kiệm điện...",
  "availability": "InStock",
  "reviews": [
    { "author": "Ngọc Hà", "date": "2/14/2026", "rating": 5, "body": "Máy chạy êm, dung tích rộng, đóng gói cẩn thận." }
  ],
  "searchMode": "search",
  "source": "dienmayxanh.com"
}
```

### Plan Requirement

Measured on 2026-10-20: the category, product, Flash Sale and promotion pages answer with real content on both the Apify datacenter pool and Residential in Vietnam, but the site's product-paging and customer-review requests (everything after the first page of a listing, price sorts and reviews beyond the first ten) answered only from Residential in Vietnam (the datacenter pool got an empty reply). A residential plan is therefore recommended for full listings and reviews; without it the run still returns the first page of each listing and the first ten reviews per product. The default connection is residential in Vietnam, so a default run starts on Apify residential (Vietnam), then falls back to Apify datacenter, then to backup connections; if you do not select the residential group the order starts with datacenter instead. The run learns what your account may use from the connection itself. A connection the site merely refuses or that times out never retires a lane, only a proxy-level refusal does. A custom proxy URL you supply is used as given.

What you see when your plan has no residential access (verbatim from the run):

- Log warning: "The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable. For residential access, upgrade at https://apify.com/pricing or supply your own proxy URLs."
- Log info when a backup served data: "Served over the backup connection (the default connection was unavailable)."
- Failure, proxy refused for the account: "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required: https://apify.com/pricing. If you entered your own proxy URLs, check that their credentials are valid."
- Failure, no residential and the backup could not load pages: "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Dienmayxanh pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again."
- Failure, nothing loaded: "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later."

Pasting a single product link in url mode always reads that product's detail page, so it is charged the detail-enrichment event on that one item even when Fetch product details is off.

### FAQ

#### How much does it cost?

You pay a fixed run start fee, a per-product-result fee for every row in the dataset, and a detail-enrichment surcharge for every product whose detail page was actually read. Fetch product details is off by default, so an ordinary listing or search run pays no surcharge; turning it on, or turning on Fetch customer reviews alone, means the surcharge applies to essentially every product returned, since the detail page almost always yields at least some detail data once it loads. A single pasted product link is always charged the surcharge, regardless of the Fetch product details setting, because its detail page is read to report the product at all. The **Pricing** tab shows the live rates for each event. With **Fetch customer reviews** on, the reviews of a product are included in its single detail-enrichment unit. Detail-enrichment is charged per product as each one is saved, not at the end of the run. Use **Max products** and **Max reviews per product** to cap the cost of any run.

#### Is it legal to scrape Điện Máy Xanh?

This actor collects only publicly available product data. You are responsible for how you use it: follow the site's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Prices and specifications are generally facts, but product photos may be subject to third-party rights.

#### Why did my run fail instead of returning an empty dataset?

A run whose pages could not be loaded ends as failed with one of the three messages quoted under Plan Requirement, never as a successful empty run. A run that reached the site and genuinely found nothing finishes successfully with an empty dataset.

#### Can I get only new or changed products on a schedule?

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. Each run then returns only NEW, UPDATED and REAPPEARED products by default, and unchanged ones are not billed. EXPIRED rows, and the ability to detect a REAPPEARED product at all, only start showing up once a run with **Emit expired products** on has completed a full, uncapped scan of your search; a run limited by Max products, or resumed from a previous run, is skipped for that detection instead of guessing.

#### Does Resume skip re-crawling the listing?

No. Resume prevents already-collected products from being pushed and billed again, but it does not extend the walk to reach further pages in exchange, so a resumed run over the same search can surface mostly, or entirely, products you already have. Already-collected products are never billed again even though their detail pages may still be fetched before being dropped, so the savings are in charges, not in requests made.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

### 🔗 Want more electronics data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🛒 <a href="https://apify.com/abotapi/thegioididong-scraper"><b>Thegioididong Scraper</b></a><br>Scrape thegioididong.com products with full specifications, current &amp; original price...</td><td>🔌 <a href="https://apify.com/abotapi/pbtech-co-nz-scraper"><b>PB Tech Scraper</b></a><br>Scrape pbtech.co.nz products with full specifications, price, brand, condition, per-store...</td></tr>
<tr><td>🔌 <a href="https://apify.com/abotapi/darty-com-scraper"><b>Darty Scraper</b></a><br>Scrape Darty (darty.com) products: current price plus strike-through reference price and...</td><td>🔌 <a href="https://apify.com/abotapi/currys-co-uk"><b>Currys UK Scraper</b></a><br>Scrape Currys UK electronics by keyword or URL. Extract prices, brands, stock status...</td></tr>
<tr><td>🔌 <a href="https://apify.com/abotapi/biccamera-com-scraper"><b>Bic Camera Scraper</b></a><br>Scrape Bic Camera (biccamera.com) products: JPY price, list price and discount, Bic Point...</td><td>🔌 <a href="https://apify.com/abotapi/yodobashi-com-scraper"><b>Yodobashi Scraper</b></a><br>Scrape yodobashi.com electronics and appliances: JPY price, list price and discount...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/dienmayxanh-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

## `mode` (type: `string`):

Choose 'search' to use keywords, or 'url' to scrape specific product, category or search URLs you paste below.

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

One or more keywords to search, for example 'tủ lạnh', 'máy giặt inverter' or 'tivi samsung'. Each keyword is searched separately. To browse a whole category instead, switch to URL mode and paste its link (for example https://www.dienmayxanh.com/tu-lanh).

## `specialsOnly` (type: `boolean`):

Also browse Điện Máy Xanh's site-wide Flash Sale deals page (limited-time discounted prices), in addition to any search keywords above. Every result carries the current price plus the original price, discount % and savings where discounted. To scrape a seasonal category-specific promotion page instead (for example a 'khuyen-mai-tu-lanh' fridge deals page), switch to URL mode and paste its link.

## `urls` (type: `array`):

Product, category, search or promotion URLs to scrape, for example https://www.dienmayxanh.com/tu-lanh/samsung-rt22m4032by-sv, https://www.dienmayxanh.com/tu-lanh, https://www.dienmayxanh.com/flashsale (site-wide Flash Sale) or https://www.dienmayxanh.com/khuyen-mai-tu-lanh (a seasonal category promotion page). Multiple URLs supported.

## `brand` (type: `string`):

Optional. Keep only products whose brand contains this text, for example 'Samsung', 'LG' or 'Toshiba'.

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

Ordering applied to whatever set of results was collected, whether from a keyword search or a pasted URL. Price sorts are requested from the site while paging (verified live: pages come back in price order), so the cheapest or dearest products come first when a limit is set; the other sorts reorder the collected results. Sorting never filters items.

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

Optional. Only keep products priced at or above this amount (VND).

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

Optional. Only keep products priced at or below this amount (VND).

## `minRating` (type: `integer`):

Optional. Only keep products with an average customer rating at or above this value (1 to 5). Needs product details enabled.

## `fetchDetails` (type: `boolean`):

Add full specifications, variants, image gallery, brand, category, description and aggregate rating for each product. This opens each product page (one extra request per product), so it is off by default — leave it off for fast, low-cost listing runs, and turn it on when you need the full detail fields.

## `fetchReviews` (type: `boolean`):

Also collect the customer reviews shown on each product page (review text, author, date, star rating). Read from the product page, so it needs product details enabled; no extra request.

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

Cap on reviews collected per product when 'Fetch customer reviews' is on. Use 0 for the maximum of 1000 reviews.

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

Maximum number of products to return across the whole run. Use 0 for unlimited.

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

Safety cap on category / search listing pages fetched per query (each page holds about 20 products). Leave empty for the default cap; the run also stops at Max products or when a listing is exhausted.

## `proxy` (type: `object`):

Apify Proxy with residential access in Vietnam is required for reliable results and correct local pricing and stock. The run rotates fresh exits automatically. On the free plan, coverage may be limited and some runs may return no results.

## `resumeFromRunId` (type: `string`):

Paste a previous run id or dataset id to continue an interrupted crawl: products already collected there are skipped so this run returns only what's missing. A one-off continuation, distinct from Incremental mode below, which tracks a search across many scheduled runs on its own.

## `incrementalMode` (type: `boolean`):

For a scheduled/recurring run of the SAME search or URLs: remembers what was collected last time and returns only NEW, UPDATED, REAPPEARED and (optionally) EXPIRED products. A product is UPDATED when any output field changes (price, original price, discount, availability, label, promo gift, installment offer, rating, review count, details, ...); the customer-reviews list never counts, nor does the order of the image gallery, and you can exclude more with 'Ignore fields when detecting changes'. Off by default (returns everything, like a one-off run). Distinct from 'Resume from run/dataset id' above, which continues one specific interrupted run instead of tracking a recurring search.

## `stateKey` (type: `string`):

Optional name for the saved baseline used by Incremental mode. Leave empty to auto-derive one from your search settings (mode, keywords, brand, sort, price/rating filters, Flash Sale toggle, URLs, fetch details/reviews) — two different filter setups never share a baseline. Set your own to explicitly separate or share monitoring campaigns.

## `emitUnchanged` (type: `boolean`):

When on, Incremental mode also returns products with no change since the last run (changeType UNCHANGED). Off by default: unchanged products are neither returned nor billed, only NEW/UPDATED/REAPPEARED/EXPIRED are. Turning this on returns — and bills — every product every run.

## `emitExpired` (type: `boolean`):

When on, Incremental mode also returns products that were tracked before but are no longer found (changeType EXPIRED), once a run completes a full scan of the search. Off by default. Turning this on returns — and bills — an extra row per product that disappeared.

## `ignoreFieldsForChanges` (type: `array`):

Field names that must NOT make a product count as UPDATED, e.g. rating, reviewCount, promoGift, installmentOffer. A plain name matches at any depth; use a dotted path like specs.name for one nested place. The fields are still returned in the output. Changing this list never causes a wave of UPDATED rows. The reviews list is always ignored.

## `mcpConnectors` (type: `array`):

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write/digest. Leave empty to skip; never changes the dataset output. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL or id of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "queries": [
    "tủ lạnh"
  ],
  "specialsOnly": false,
  "urls": [
    "https://www.dienmayxanh.com/tu-lanh",
    "https://dienmayxanh.com/may-giat",
    "https://www.dienmayxanh.com/tim-kiem?key=tu+lanh",
    "https://www.dienmayxanh.com/tu-lanh/samsung-rt22m4032by-sv#reviews",
    "https://www.dienmayxanh.com/flashsale",
    "https://www.dienmayxanh.com/khuyen-mai-tu-lanh",
    "https://www.dienmayxanh.com/tu-lanh-samsung",
    "https://www.dienmayxanh.com/tu-lanh?p=duoi-8-trieu",
    "https://www.dienmayxanh.com/tu-lanh?o=gia-thap-den-cao"
  ],
  "sortBy": "relevance",
  "fetchDetails": false,
  "fetchReviews": false,
  "maxReviewsPerProduct": 20,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "VN"
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `detail` (type: `string`):

No description

## `reviews` (type: `string`):

No description

## `changes` (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 = {
    "mode": "search",
    "queries": [
        "tủ lạnh"
    ],
    "urls": [
        "https://www.dienmayxanh.com/tu-lanh",
        "https://dienmayxanh.com/may-giat",
        "https://www.dienmayxanh.com/tim-kiem?key=tu+lanh",
        "https://www.dienmayxanh.com/tu-lanh/samsung-rt22m4032by-sv#reviews",
        "https://www.dienmayxanh.com/flashsale",
        "https://www.dienmayxanh.com/khuyen-mai-tu-lanh",
        "https://www.dienmayxanh.com/tu-lanh-samsung",
        "https://www.dienmayxanh.com/tu-lanh?p=duoi-8-trieu",
        "https://www.dienmayxanh.com/tu-lanh?o=gia-thap-den-cao"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "VN"
    },
    "ignoreFieldsForChanges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/dienmayxanh-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 = {
    "mode": "search",
    "queries": ["tủ lạnh"],
    "urls": [
        "https://www.dienmayxanh.com/tu-lanh",
        "https://dienmayxanh.com/may-giat",
        "https://www.dienmayxanh.com/tim-kiem?key=tu+lanh",
        "https://www.dienmayxanh.com/tu-lanh/samsung-rt22m4032by-sv#reviews",
        "https://www.dienmayxanh.com/flashsale",
        "https://www.dienmayxanh.com/khuyen-mai-tu-lanh",
        "https://www.dienmayxanh.com/tu-lanh-samsung",
        "https://www.dienmayxanh.com/tu-lanh?p=duoi-8-trieu",
        "https://www.dienmayxanh.com/tu-lanh?o=gia-thap-den-cao",
    ],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "VN",
    },
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/dienmayxanh-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 '{
  "mode": "search",
  "queries": [
    "tủ lạnh"
  ],
  "urls": [
    "https://www.dienmayxanh.com/tu-lanh",
    "https://dienmayxanh.com/may-giat",
    "https://www.dienmayxanh.com/tim-kiem?key=tu+lanh",
    "https://www.dienmayxanh.com/tu-lanh/samsung-rt22m4032by-sv#reviews",
    "https://www.dienmayxanh.com/flashsale",
    "https://www.dienmayxanh.com/khuyen-mai-tu-lanh",
    "https://www.dienmayxanh.com/tu-lanh-samsung",
    "https://www.dienmayxanh.com/tu-lanh?p=duoi-8-trieu",
    "https://www.dienmayxanh.com/tu-lanh?o=gia-thap-den-cao"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "VN"
  },
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/dienmayxanh-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/dienmayxanh-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/InOKSKSb75CncxyGz/builds/cU8eJsxgGgQTXLGUX/openapi.json
