# 1688 Taobao Product Dataset Normalizer USD MOQ (`zinin/1688-taobao-product-dataset-normalizer`) Actor

Normalize supplied 1688 and Taobao product exports into price ranges, MOQ, currencies and supplier summaries with dated FX evidence and duplicate tracking.

- **URL**: https://apify.com/zinin/1688-taobao-product-dataset-normalizer.md
- **Developed by:** [Tim Zinin](https://apify.com/zinin) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## 1688 Taobao Product Dataset Normalizer USD MOQ

Normalize supplied 1688 and Taobao product exports into comparable CNY price ranges, MOQ, units and USD/EUR conversions. This Actor works on your existing product records, preserves quantity tiers, deduplicates product identities and adds free supplier summaries without opening marketplace pages.

**Evidence status: private build 0.1.3 accepted on 2026-09-06.** Every input/output example below is an exact Dataset record or OUTPUT record from the accepted acceptance runs on Apify's network with the pay-per-event tariff active. The listing is not public yet; no scheduled task or review history is claimed.

Planned pay-per-event price: **$0.005 per run start + $0.002 per product**. Incomplete and error rows are free of result charges.

### What you get

- Ranges and quantity tiers stay intact; zero price is flagged instead of treated as missing.
- USD and EUR share one run-level FX observation or the documented dated pin.
- Pinyin and traditional-script titles are generated locally for search.
- URL/ID deduplication retains duplicate indexes before a product becomes billable.
- Supplier summaries describe the products actually delivered and have no result event.
- Runs on Apify: schedule it, monitor it, call it from your API workflow, and export results to JSON, CSV or Excel.

![Input, evidence and result boundary](assets/readme-hero.svg)

### How to run it

1. Open the Actor input form and start with the clearly marked synthetic prefill.
2. Inspect the result dataset and OUTPUT before replacing the demo with authorized buyer data.
3. Supply either your inline records or your dataset ID, then choose the documented settings and limits.
4. Start a small run, inspect partial/error records, and export the relevant complete result types.

### Pricing

The accepted Wave B build plan specifies **$0.005 per run start + $0.002 per product**. At that planned base price, 100 complete units in one run are $0.205, and 1,000 are $2.005. This arithmetic excludes any separate upstream export purchase or downstream service cost. There is no monthly seat charge in this planned Actor tariff.

The actual deployed tariff has not been changed or verified by this build. The orchestrator must reconcile the Store price, event definitions and acceptance receipts before making this a final listing. The platform's current free-plan credit availability is separate from this Actor's result-event semantics; do not treat free result rows as a promise of a zero-cost run.

Billing unit: **product**. Bill result-found once per normalized product after URL/ID deduplication. Supplier\_summary, rejected products and notices must have zero result events. A dated FX pin with fxStale=true is a complete billable conversion by contract. Claude must bind a purchased product-export dataset for cloud acceptance and reconcile unique product count, result receipts and duplicate indexes.

### Input contract

The table describes the actual input schema. Structural restrictions that Apify's form dialect cannot express are checked again at runtime. Defaults and prefill are distinct: the email form's prefill sets checkMx=false for the offline demo even though non-demo validation normally enables MX.

| Field | Type and bound | Meaning |
|---|---|---|
| `rows` | array; max 5000 items | Replace the clearly marked synthetic prefill with your own authorized data. Explicit datasetId suppresses unchanged demo rows. Runtime: 10 MiB input, 64 KiB per row, depth 16 and 100 items per nested array. |
| `datasetId` | string; max 128 chars | Optional Apify dataset ID in your account. Read in pages of 100, at most 5000 rows and 10 MiB. No dataset URL. Remove custom inline rows when setting this. |
| `fieldMap` | object | Optional target-name to dotted-path map. At most 20 paths of 80 characters; prototype and executable paths rejected at runtime. See README for allowed target names. |
| `targetCurrencies` | array; max 2 items | Only USD and EUR, without duplicates. One FX request per run; dated pin on failure. |
| `deduplicate` | boolean | Pay for one normalized product per URL/ID group, with duplicate indexes retained. |
| `includePinyin` | boolean | Deterministic local pinyin transliteration for search. |
| `includeTraditional` | boolean | Local OpenCC script conversion, not translation. |
| `maxItems` | integer; 1–5000 | Working output cap; remaining units are reported as unprocessed in OUTPUT. Error notices and free supplier summaries are additional. |

#### Recorded happy-path input and output

Run `GVKtlbBOc0swcL16T` on build 0.1.3, 2026-09-06, 5 s, Dataset records: 33, charged events: `{"apify-actor-start": 1, "result-found": 29}`. The input is the form prefill; every one of the 29 paid records carries the demo marker because the prefill is synthetic.

Input:

```json
{
 "fieldMap": {},
 "deduplicate": true,
 "includePinyin": true,
 "includeTraditional": true,
 "maxItems": 30
}
```

First Dataset record (exact):

```json
{
 "schemaVersion": "1.0",
 "type": "product",
 "sourceUrl": null,
 "found": true,
 "status": "ok",
 "resultCount": 1,
 "partial": false,
 "error": "",
 "warnings": [],
 "checkedAt": "2026-09-06T02:18:05.339Z",
 "evidence": "buyer_supplied_data",
 "confidence": null,
 "action": "review",
 "demo": true,
 "inputIndex": 0,
 "productId": "demo-product-0",
 "sourceProductUrl": "https://example.com/products/0",
 "supplierId": "demo-supplier-0",
 "platform": null,
 "title": "红色棉质短袖 M",
 "titleTraditional": "紅色棉質短袖 M",
 "titlePinyin": "hong se mian zhi duan xiu   M",
 "priceMinCny": 12.5,
 "priceMaxCny": 15,
 "tiers": [],
 "moq": null,
 "unit": "piece",
 "attributes": [
  {
   "attribute": "material",
   "value": "cotton",
   "evidence": {
    "source": "title_dictionary",
    "token": "棉"
   }
  },
  {
   "attribute": "color",
   "value": "red",
   "evidence": {
    "source": "title_dictionary",
    "token": "红色"
   }
  },
  {
   "attribute": "size",
   "value": "M",
   "evidence": {
    "source": "title_dictionary",
    "token": "M"
   }
  }
 ],
 "suspiciousPriceFlags": [],
 "duplicateInputIndexes": [
  29
 ],
 "mappingEvidence": {
  "title": "title",
  "productId": "id",
  "sourceProductUrl": "url",
  "supplierId": "supplierId",
  "price": "price"
 },
 "synthetic": true,
 "pricesUsd": {
  "min": 1.862625,
  "max": 2.23515,
  "tiers": []
 },
 "pricesEur": {
  "min": 1.602625,
  "max": 1.92315,
  "tiers": []
 },
 "rateDate": "2026-09-04",
 "rateSource": "frankfurter.dev",
 "fxStale": false,
 "rateStale": false
}
```

#### Recorded partial input and output

Run `7CgDadqjOkwXbsMWv` on build 0.1.3, 2026-09-06, 4 s, Dataset records: 3, charged events: `{"apify-actor-start": 1, "result-found": 1}`. The free notice keeps the remaining work count; the complete neighbouring result still carries its own result event.

Input:

```json
{
 "maxItems": 1,
 "fieldMap": {},
 "deduplicate": true,
 "includePinyin": true,
 "includeTraditional": true
}
```

Free notice record (exact):

```json
{
 "schemaVersion": "1.0",
 "type": "notice",
 "sourceUrl": null,
 "found": false,
 "status": "partial",
 "resultCount": 0,
 "partial": true,
 "error": "max_items",
 "warnings": [],
 "checkedAt": "2026-09-06T02:18:17.224Z",
 "evidence": "buyer_supplied_data",
 "confidence": null,
 "action": "review",
 "demo": true,
 "unprocessed": 28
}
```

#### supplied dataset — real 1688 wholesale export bought in the Store (zen-studio)

Run `w3xjTge3y19IO28We` on build 0.1.3, 2026-09-06, 4 s, Dataset records: 36, charged events: `{"apify-actor-start": 1, "result-found": 20}`. 20 paid records. The dataset was passed through `datasetId`; the Actor never contacted the platform the export came from.

Input:

```json
{
 "datasetId": "nomD9AuTw4znWSVqn",
 "maxItems": 30,
 "fieldMap": {},
 "deduplicate": true,
 "includePinyin": true,
 "includeTraditional": true
}
```

First paid Dataset record (exact):

```json
{
 "schemaVersion": "1.0",
 "type": "product",
 "sourceUrl": null,
 "found": true,
 "status": "ok",
 "resultCount": 1,
 "partial": false,
 "error": "",
 "warnings": [],
 "checkedAt": "2026-09-06T02:18:24.427Z",
 "evidence": "buyer_supplied_data",
 "confidence": null,
 "action": "review",
 "demo": false,
 "inputIndex": 0,
 "productId": "927875250705",
 "sourceProductUrl": "https://detail.1688.com/offer/927875250705.html",
 "supplierId": "佛山市南海区三丰手机配件有限公司",
 "platform": null,
 "title": "新款苹果18promax手机壳磁吸16防摔磨砂iphone17pm跨境保护壳批发",
 "titleTraditional": "新款蘋果18promax手機殼磁吸16防摔磨砂iphone17pm跨境保護殼批發",
 "titlePinyin": "xin kuan ping guo 1 8 p r o m a x shou ji ke ci xi 1 6 fang shuai mo sha i p h o n e 1 7 p m kua jing bao hu ke pi fa",
 "priceMinCny": 7.5,
 "priceMaxCny": 8,
 "tiers": [
  {
   "minQuantity": 50,
   "maxQuantity": 499,
   "unitPriceCny": 8,
   "unit": "piece"
  },
  {
   "minQuantity": 500,
   "maxQuantity": 2999,
   "unitPriceCny": 7.8,
   "unit": "piece"
  },
  {
   "minQuantity": 3000,
   "maxQuantity": null,
   "unitPriceCny": 7.5,
   "unit": "piece"
  }
 ],
 "moq": 50,
 "unit": "piece",
 "attributes": [
  {
   "attribute": "材质",
   "value": "优质TPU",
   "evidence": {
    "source": "buyer_attribute"
   }
  },
  {
   "attribute": "工艺",
   "value": "注塑",
   "evidence": {
    "source": "buyer_attribute"
   }
  },
  {
   "attribute": "款式",
   "value": "后盖款",
   "evidence": {
    "source": "buyer_attribute"
   }
  },
  {
   "attribute": "品牌",
   "value": "三丰",
   "evidence": {
    "source": "buyer_attribute"
   }
  },
  {
   "attribute": "功能",
   "value": "防震,磁吸,防磨,防摔",
   "evidence": {
    "source": "buyer_attribute"
   }
  },
  "… 15 more entries omitted here for length"
 ],
 "suspiciousPriceFlags": [],
 "duplicateInputIndexes": [],
 "mappingEvidence": {
  "title": "title",
  "productId": "offerId",
  "sourceProductUrl": "detailUrl",
  "supplierId": "supplier.companyName",
  "unit": "unit",
  "tiers": "quantityPrices",
  "price": "price",
  "moq": "minOrderQuantity",
  "attributes": "specs"
 },
 "synthetic": false,
 "pricesUsd": {
  "min": 1.117575,
  "max": 1.19208,
  "tiers": [
   {
    "minQuantity": 50,
    "maxQuantity": 499,
    "unitPrice": 1.19208
   },
   {
    "minQuantity": 500,
    "maxQuantity": 2999,
    "unitPrice": 1.162278
   },
   {
    "minQuantity": 3000,
    "maxQuantity": null,
    "unitPrice": 1.117575
   }
  ]
 },
 "pricesEur": {
  "min": 0.961575,
  "max": 1.02568,
  "tiers": [
   {
    "minQuantity": 50,
    "maxQuantity": 499,
    "unitPrice": 1.02568
   },
   {
    "minQuantity": 500,
    "maxQuantity": 2999,
    "unitPrice": 1.000038
   },
   {
    "minQuantity": 3000,
    "maxQuantity": null,
    "unitPrice": 0.961575
   }
  ]
 },
 "rateDate": "2026-09-04",
 "rateSource": "frankfurter.dev",
 "fxStale": false,
 "rateStale": false
}
```

### Output and field dictionary

The overview table exposes every field used by the complete, summary and notice records produced by this Actor. A field may be absent on unrelated record types. Keep the type discriminator when flattening a mixed dataset.

#### `schemaVersion`

Version of the output contract. Compare it before appending rows to a table created for an earlier schema.

#### `type`

Discriminator for this dataset record. Filter by it before aggregating values, because result rows and free operational notices share one dataset.

#### `sourceUrl`

An inert source reference when the record has one. It is never an instruction for this Actor to fetch a social, product or contact page.

#### `found`

True means a complete billable result under this Actor's selected unit. False includes useful free previews and summaries as well as absent, rejected or partial results.

#### `status`

Compact processing state. Use it together with found, partial and error; a single status label is not a substitute for the full result contract.

#### `resultCount`

One for a complete billable result, zero for free records. This is a per-record count, not the total number of rows processed in the run.

#### `partial`

True means this row or notice represents incomplete work. Never promote a partial row to a complete result just because other fields are populated.

#### `error`

Empty for correct no-data and complete results; a bounded classification for a failure. Provider error bodies and input secrets are not copied here.

#### `warnings`

Readable qualifications that can accompany a complete result. A warning is not automatically an error or a reason to drop the row.

#### `checkedAt`

ISO observation time for this Actor's output. It does not replace the supplied post timestamp, the exchange-rate date or an upstream export collection time.

#### `evidence`

Origin label for the result's evidence. Supplied data, local syntax checks and DNS observations establish different boundaries.

#### `confidence`

Null when the Actor has no measured confidence model. Null is deliberate and should not be filled with an arbitrary 100 percent score.

#### `action`

A conservative review hint. It is not an executed downstream action or authorization to contact, purchase, publish or delete anything.

#### `demo`

True on synthetic demonstration output. Keep this field visible when combining demo runs with real buyer data in an internal workbook.

#### `unprocessed`

Remaining units reported by a free notice. Consult OUTPUT for the run-level remainder and the reason the working limit stopped processing.

#### `inputIndex`

Zero-based position in the supplied inline list or loaded dataset. Keep the original export if you need to resolve this index later.

#### `productId`

Supplied product identifier. Identity is scoped by supplied platform or source host before deduplication.

#### `sourceProductUrl`

Original inert product reference. The Actor may normalize its identity string for deduplication but does not open the page.

#### `supplierId`

Supplied supplier or shop identity. It may be a source label rather than a verified company number; null means unknown supplier.

#### `platform`

Source platform in analytics or destination platform in webhook records. For products, this is an optional supplied identity scope, not marketplace verification.

#### `title`

Trimmed original product title. It remains the primary text alongside local script and pinyin search variants.

#### `titleTraditional`

Local OpenCC script conversion when enabled. It is a search variant and does not certify the translation of a product description.

#### `titlePinyin`

Tone-free local pinyin transliteration when enabled. Polyphonic names can need human review before use as a catalog identity.

#### `priceMinCny`

Minimum explicitly parsed CNY price in a product or delivered-supplier summary. Compare only like units and inspect tiers.

#### `priceMaxCny`

Maximum explicitly parsed CNY price. A range is preserved rather than replaced by a mean or a suggested transaction price.

#### `tiers`

At most twenty quantity/price entries. Currency conversion adds matching tier values within the same product, without extra result events.

#### `moq`

Known positive integer minimum order quantity. Null means the supplied record did not establish a reliable threshold.

#### `unit`

Normalized piece, box, set or kilogram unit. Unknown units stay null; packaging is not converted without a supported explicit contract.

#### `pricesUsd`

Converted minimum, maximum and tier prices using the run's dated CNY-to-USD rate. Null when USD was not requested.

#### `pricesEur`

Converted minimum, maximum and tier prices using the same run-level observation as USD. Null when EUR was not requested.

#### `rateDate`

Date attached to the FX observation. It is separate from the Actor run time and any product collection date.

#### `rateSource`

frankfurter.dev for a valid response, dated\_pin for the fixed fallback. It is never labelled live after an unavailable provider response.

#### `fxStale`

True when fallback was used or a live observation is older than the documented freshness window. Staleness remains visible on complete products.

#### `rateStale`

Compatibility alias for fxStale, kept to reflect both reviewed naming conventions. Both flags have identical values.

#### `attributes`

Bounded attribute entries with source evidence. Dictionary matches do not establish certifications, safety properties or unspecified composition.

#### `suspiciousPriceFlags`

Explicit inspection reasons such as zero\_price or wide\_price\_range. They are not probabilities of fraud or supplier-quality ratings.

#### `duplicateInputIndexes`

Indexes collapsed into the representative post or product. They explain deduplication without creating extra billable rows.

#### `mappingEvidence`

Selected target-to-source paths. Inspect this evidence when an exporter changes names or when a manual mapping overrides automatic detection.

#### `synthetic`

Additional provenance marker for synthetic records. The explicit demo field remains the common filter across all four B2 Actors.

#### `products`

Number of delivered products in a free supplier summary. It does not count rejected, duplicate or unprocessed source records.

#### `suspiciousProducts`

Delivered products in this supplier group with at least one price flag. One product contributes at most one to this count.

#### `units`

Distinct units among delivered products in the supplier group, including null when unknown. Mixed units should not be ranked by price alone.

#### `scope`

Supplier-summary boundary, delivered\_products. It makes clear that a cap-limited run is not a full supplier-catalog inventory.

### Who uses it

Sourcing analysts, catalog managers and procurement operations teams use normalized products to compare explicit ranges and route missing or suspicious quotes for review.

#### Normalize a product, preserve its commercial meaning

A product price range often reflects quantity, variant or packaging context. This Actor keeps a range as `priceMinCny` and `priceMaxCny`; it never replaces the range with its midpoint and calls that a quoted price. The string `¥12.5-15.0/件` becomes 12.5 through 15 CNY per piece. The string `≥100件 ¥9.8` produces a tier beginning at 100 pieces with a 9.8 CNY unit price. A box remains a box unless the source itself supplies a separate conversion that your downstream system understands.

The default input contains 30 synthetic records, including a duplicate identity, zero prices and several units. Deduplication yields 29 complete products. Supplier summaries are additional free records, so dataset row count is larger than the count of billed products. The default demonstrates normalization of existing data. It does not establish that these products exist on a marketplace, are in stock, or can be purchased at those synthetic prices.

#### Field mapping and identity scope

Automatic product IDs include `id`, `offerId`, `offer_id`, `itemId`, `item_id`, and `productId`. Source URL aliases include `url`, `detailUrl`, `productUrl`, and `offerUrl`. Titles can come from `title`, `subject`, `name`, or `productName`. Price aliases include `price`, `priceRange`, `priceText`, `salePrice`, and `priceCny`. A manual `fieldMap` selects an exact dotted path for a target field and overrides its automatic candidates.

The purchased `zen-studio/1688-wholesale-scraper` export maps automatically without `fieldMap`: `offerId`, `detailUrl`, `title`, `minOrderQuantity` and `unit` identify the product and MOQ (`个` becomes `piece`); `price: {min, max, currency, priceType, promoLabel}` preserves the two CNY endpoints in `priceMinCny`/`priceMaxCny`; `quantityPrices: [{quantityMin, quantityMax, price, quantityRange}]` supplies tiers, with a null `quantityMax` leaving the upper bound open and an empty list yielding no tiers. Supplier identity uses `supplier.companyName`, falling back to `supplier.memberId`; `specs: [{name, value}]` supplies attributes with buyer-source evidence. Object prices require CNY currency; another or missing currency produces a free `rejected_input` row with a warning and no currency conversion. Promotional metadata, images, descriptions, shipping and sales counters are ignored. Explicit buyer mappings retain priority.

Supplier identity can be a supplied supplier ID, nested supplier ID, seller ID, company name or shop name. It remains supplied evidence, not a verified corporate identity. If no supplier identity is available, a free summary may use null to group the delivered products without a known supplier. Do not treat that null group as one real company. If a precise supplier identifier is essential, map it explicitly and inspect source records before downstream procurement decisions.

Deduplication joins records that share a normalized source URL or a scoped product ID. URL normalization removes fragments and recognized tracking parameters while preserving meaningful query parameters. Product IDs are scoped by an explicit platform when supplied, otherwise by the URL hostname, otherwise by an unspecified-source namespace. This prevents identical numeric IDs on different marketplace hosts from being merged automatically. Source URLs are parsed as strings; none are fetched.

When duplicate groups connect through a bridge record, the groups merge and preserve the earliest normalized input record as the representative. The remaining input indexes are recorded. A malformed earlier row does not suppress a later valid product because normalization happens before deduplication. Conflicting prices across duplicates are not averaged. Use the indexes to inspect the source export if two snapshots disagree materially.

#### Supported price and tier forms

Numeric nonnegative CNY values are accepted directly. Text prices support the yuan symbols, optional CNY/RMB prefix, a decimal range and a recognized unit suffix. A negative price, reversed range, blank value or phrase such as “contact supplier” is not silently converted to zero. Such a record becomes a free rejected product. The parser intentionally prefers a bounded set of explicit forms to a broad number-extraction heuristic that might mistake an order quantity for a price.

Tier arrays contain at most 20 entries. Object tiers accept a minimum quantity, optional maximum quantity and a CNY unit price. String tiers use the explicit minimum-quantity notation. Quantities must be positive integers. Repeated starting quantities and overlapping explicitly closed quantity intervals are rejected as conflicting tiers. Increasing prices at higher quantities can be retained with a suspicion flag, because unusual commercial pricing is different from an unparseable structure.

The product range covers the supplied headline range and the tier prices. If no headline price exists but usable tiers do, the range comes from those tiers. The minimum order quantity comes from the supplied MOQ, otherwise from a known tier threshold. An unknown MOQ stays null. The Actor does not invent a minimum of one simply because that is convenient for a spreadsheet.

Recognized unit tokens include 件, 个, 箱, 套, kg and 公斤. Piece, box, set and kilogram remain distinct normalized units. A price per box cannot be compared directly with a price per piece without an independently known pack size. The title might mention a quantity, but this version does not treat every number in a title as packaging evidence. That avoids an accidental hundredfold conversion when a model number resembles a pack count.

#### One FX observation for the whole run

The Actor makes one bounded HTTPS request to `https://api.frankfurter.dev/v1/latest?from=CNY&to=USD,EUR` when it has normalized products to convert. It expects amount 1, base CNY, a valid dated rate record, and positive finite rates for both currencies. Redirects are rejected. Empty, malformed, mismatched-base or invalid-rate responses use the agreed dated fallback rather than a second provider request.

The fallback is fixed at 2026-09-04: one CNY equals 0.14901 USD and 0.12821 EUR. `rateSource` becomes `dated_pin`, and both `fxStale` and the compatibility field `rateStale` are true. This is an explicitly supported complete result, so a successfully normalized product still produces its result event. A live rate record older than seven days is also marked stale. All products in one run share the same rate observation and date.

Converted ranges are rounded to six decimal places, with converted tier prices alongside them. The Actor does not fetch a daily historical rate for each product's own observation time. The numbers are comparison aids based on the recorded conversion date, not a bank quote, a payable invoice, a landed cost or a promise that exchange costs are zero. Shipping, tax, duty, payment fees and supplier negotiation are outside the output contract.

#### Local title and attribute enrichment

OpenCC converts a simplified title into a traditional-script form. Pinyin-pro supplies tone-free pinyin for search. Both are local deterministic transformations and can be disabled. Neither operation translates a Chinese title into an English marketing title. Proper names, brand readings and polyphonic words can require human review; retain the original title as the primary identity-bearing text.

Attribute extraction uses a small explicit dictionary for selected materials, colors and sizes. Each extracted attribute includes the matched source token as evidence. Supplied scalar attributes can also be retained with a buyer-attribute source marker. At most 50 total attribute entries are allowed after enrichment. The Actor does not infer unspecified composition, certifications, safety properties or manufacturing origin from a photograph or a category name.

A zero price is preserved with `zero_price`, a very wide range can receive `wide_price_range`, an unusually high number can receive `high_price`, and tier increases can receive `tier_price_increases`. These are inspection flags, not fraud scores. A clearly parsed suspicious price is still a normalized product and is billable. A missing or contradictory price is incomplete and is free. Keep those categories separate in an approval workflow.

#### Supplier summaries and procurement routing

Supplier summaries are computed only from products actually delivered in this run. They contain product count, known price range, unit set and a count of products carrying suspicion flags. When `maxItems` or the budget stops the run early, the summary is a view of that delivered subset. The `scope` field makes this boundary explicit. A supplier summary is never a claim about the supplier's entire catalog or current inventory.

A sourcing analyst can route products with a recognized unit and a clean parsed range into a comparison sheet. Products with zero price or wide ranges should enter a manual quote queue. Records with missing price should return to the export or mapping owner. Keep products with different units in separate price comparisons even if their converted numerical values are close.

A catalog manager can use pinyin and script variants as additional search fields while retaining product ID and source URL as stable references. The output should not overwrite a manually approved catalog title automatically. A purchasing team can use supplier summaries to decide which groups deserve a quote request, but this Actor does not send quote requests, contact suppliers or execute purchases.

### Evidence and boundaries

The observations on this page come from accepted platform runs (see Sources and release evidence); local SDK 3.7.2 tests replace external services with deterministic fixtures and cover the paths a platform run cannot show.

The Actor reads data supplied by the buyer. Choosing a dataset ID uses the buyer's permitted Apify storage access; it does not authorize access to someone else's private dataset. A dataset ID is an identifier, not a fetch URL. The original source dataset is read only. The Actor writes its own default result dataset and one OUTPUT summary. It does not overwrite upstream rows or silently publish exports somewhere else.

Synthetic input and output carry explicit demo provenance. Keep `demo` visible when reviewing a run and inspect `demoInput` in OUTPUT. A dataset ID suppresses the unchanged form prefill. If a custom inline list is also supplied, the Actor rejects the ambiguous combination instead of merging buyer records with demonstration records. Empty input is meaningful and produces a correct free no-data record; it does not reactivate the default demo.

#### Rights and supplied personal data

Use exports and addresses that you are entitled to process for your stated purpose. A purchased export or an accessible API response does not by itself grant unlimited redistribution rights over every text, identifier or personal detail it contains. The buyer is responsible for applicable source terms, permissions, retention and privacy obligations, including relevant PIPL and GDPR responsibilities. This Actor does not determine the legal basis of an individual dataset or supply consent for a later communication.

Source URLs and references remain data. This batch does not request Douyin, Xiaohongshu, Weibo, Zhihu, consumer WeChat, Bilibili, Baidu, Taobao, 1688, JD, Toutiao, Juejin or 36kr pages. It does not log into those platforms, use account cookies, open attachments, execute supplied code or follow embedded links. The specific corporate webhook exception is limited to the sender's reviewed destination endpoints and requires buyer-supplied configuration.

### Decision routing

Start with OUTPUT, then inspect the relevant dataset record types. A nonempty dataset is not enough to establish success: it may contain free rejected-input records, previews or a partial notice. A clean process exit is not a delivery receipt from an external platform. Likewise, a free result row can be useful and intentional rather than a defect. The correct interpretation depends on the Actor's billable unit and selected mode.

Route `partial=true` records to a separate review or retry path. Keep valid complete neighboring results; do not discard an entire run simply because one supplied record was malformed. For a correct empty input, `found=false`, `error=""`, and `resultCount=0` describe absence without failure. For infrastructure errors, the error classification remains nonempty. For fatal billing or persistence uncertainty, stop automated continuation until the run is reconciled.

`replaySafe=false` is deliberate. Repeating a run can create new result records and new result events. The Actor does not maintain a cross-run exactly-once ledger, transactional outbox or reservation service. A repeated webhook request can have an external effect; a repeated analytics or normalization run can create duplicate rows in your downstream warehouse if your own import does not use a run identifier. Plan your joins and retries accordingly.

#### Before an unattended schedule

Run the smallest useful input and inspect both the result dataset and OUTPUT. Verify that the expected field paths are populated, that null values are understood and that the selected cap is appropriate. Save a task only after its settings represent the intended recurring workload. A schedule automates those saved settings; it does not repair an exporter schema change, grant source permissions or reconcile uncertain delivery for you.

Keep one operational owner for the source dataset and one for the consumer of the result. A source owner can explain changed column names or missing counters; a result owner can decide whether a partial observation should delay a report or notification. The Actor returns concrete evidence to support that decision instead of inventing missing data to keep a pipeline superficially green.

### Integration recipes

#### Console to a workbook

Begin with the synthetic prefill so you can inspect the shape quickly. Replace it with a small authorized sample and rerun. Use the Dataset table's `overview` view to see all result and summary fields, then filter by `type` before exporting. A CSV is convenient for scalar columns; nested arrays and objects are better preserved in JSON. If your spreadsheet flattens nested values, retain the original JSON export for later investigation.

Add the run ID and selected settings to your workbook as separate metadata. A row's `checkedAt` says when this Actor produced it, but cannot replace every upstream timestamp or source observation date. Do not append two runs blindly and assume the combined row count is a unique count of products, people, posts or deliveries. Use the Actor-specific identity and deduplication rules when constructing a downstream key.

#### An upstream Actor and a dataset ID

Let your authorized upstream process finish and obtain its dataset ID. Supply that ID in `datasetId`, remove any custom inline records and choose the exact field map or email field your workflow needs. The Actor requests at most 100 records per page, caps input at 5,000 records and rejects more than 10 MiB of UTF-8 record data. It does not accept a public dataset URL in place of an ID.

Preserve the upstream run reference in your own orchestration record. If the upstream exporter changes its output shape, compare a raw record with the automatic mapping candidates or selected dotted paths. A mapping error should be corrected explicitly; repeating the same run with a higher maxItems value cannot create a missing source field. Local fixture tests cover known shapes, while actual cloud acceptance must verify the purchased export in the buyer account.

#### API orchestration without a second write channel

Create and run the Actor through your normal Apify workflow, then read its default dataset and OUTPUT record. This package does not contain a separate export-to-CRM credential or an implicit message destination. A consumer that writes to a warehouse, CRM or chat service should make that action explicit in its own configuration and retain the source run ID. This keeps a result computation reviewable before it triggers another business process.

Check the platform run status, OUTPUT fatal field and partial counts before ingesting complete rows. If a request to start a run times out in your orchestration layer, inspect whether a run was created before starting another one. A client-side timeout does not establish that no run exists. This general reconciliation habit is particularly important when your downstream action is not easily reversible.

#### JSON and CSV handling

Use JSON when you need exact nested evidence, such as mapping paths, tiers, MX hosts or rendered payloads. Use CSV after selecting a single record type and a deliberate set of scalar columns. An array rendered as a JSON string inside a CSV cell is still one cell, not a guarantee that a spreadsheet can calculate on its contents. Document the flattening rule in your import job rather than silently dropping nested values.

Null, zero, false and the empty string have distinct meanings. Null means unavailable or inapplicable; zero is a known numerical value; false is an explicit boolean state; an empty error string is a correct absence of error. A data-cleaning step that replaces all four with blanks can destroy the boundaries this Actor is designed to preserve. Keep these values distinct in a database or typed dataframe.

### Operating guide

#### Input size and structure

The runtime checks both array lengths and byte sizes. One source record is limited to 64 KiB. Opaque nested arrays have a maximum of 100 elements, nesting depth is capped at sixteen (real Xiaohongshu exports nest to nine) and source objects have a bounded number of properties. Specialized structures such as product tiers, webhook destinations and field maps have smaller Actor-specific limits. These checks run even when the input schema cannot express the restriction in Apify's supported dialect.

Dotted paths are literal property navigation. Prototype-related components, executable templates and remote references are rejected. The Actor does not use field names as code. Invalid types and nonfinite numbers are errors instead of implicit string coercions in important metric and limit fields. A buyer should prefer a small normalized export to embedding oversized page documents or unneeded binary content in each row.

The input schema intentionally uses Apify-supported controls rather than unsupported general JSON Schema composition. Runtime validation provides the additional structural guarantees. The build records the output of `apify validate-schema .actor/input_schema.json` for this exact schema. Passing that command confirms the Console schema dialect; it does not establish the correctness of the domain calculations, which are checked separately by the tests and examples.

#### Spending and result reconciliation

Run-start pricing is separate from result pricing. A free result record can still be part of a run whose startup event was charged. The planned tariff uses one named `result-found` event per complete billable unit; a plain dataset push is used for free notices and other explicitly free row types. There is no manual second charge for the same unit, and the automatic dataset-item event must have zero price.

Before a paid push, the Actor reads pricing and the remaining run budget, checks the next combined charge at the microdollar boundary and serializes paid pushes. If pricing is absent on the platform, the automatic dataset-item event is unexpectedly priced, or the budget cannot be read, it fails closed. It does not continue with a guessed budget or announce a clean financial result. The real SDK tests exercise those cases rather than replacing the charging manager with a permissive mock.

An exception during a paid push can occur after the dataset write but before charge confirmation. In that case the Actor reports uncertain delivery and fails the run. A row can therefore exist even when the local paid count was not incremented. Reconcile the actual dataset and platform charge evidence before retrying. Do not infer the bill from raw dataset length when free records or uncertain writes are present.

#### OUTPUT counters

`requested` counts the source input units defined for this Actor. `processed` counts the work units completed by its loop, which can differ from input units for a report builder or a grouped sender. `delivered` counts complete result rows accepted by the delivery guard. `paid` counts confirmed monetized result events; local nonmonetized runs can deliver useful rows with paid zero. `free` counts ordinary dataset pushes, and `failed` counts free rows carrying an error classification.

`unprocessed` records remaining Actor work units, with an Actor-specific reason where a cap or deadline stopped the run. `partial` combines domain incompleteness, free partial rows, a remainder and fatal uncertainty. `fatal` is separate from ordinary per-record errors. `deliveryUncertain` identifies persistence/charge uncertainty at the delivery guard. For webhook API ambiguity, inspect the deliveryStatus record as well. These distinctions are useful when deciding whether to retain complete neighboring rows, fix input or reconcile a run.

#### Diagnosing a changed input shape

First reproduce the issue with a few sanitized records from the same export. Check whether the relevant field is absent, null, a stringified number, an object, or located at a different path. Compare the record with the input examples and exact field map contract. A field that visually looks numeric in a spreadsheet can still arrive as a localized string or a blank after CSV conversion. Fix the source conversion or mapping rather than guessing a value downstream.

For a support report, include the Actor version, run reference, sanitized input shape, expected interpretation and actual error/status fields. Remove webhook URLs, signing secrets and unnecessary personal data. If the issue involves a price range, include the exact relevant string and unit; if it involves timing, include the original timestamp and timezone setting; if it involves DNS, include the MX classification rather than a list of unrelated addresses. These details make the discrepancy reproducible without broadening exposure.

### Commercial playbooks

A useful paid workflow starts with a decision that the output can actually support. Decide whether the customer needs a report, a normalized catalog, a delivery receipt or an address-quality observation. Use the matching result unit when estimating volume and price. Avoid promising a broader source collection or account-verification service simply because those words appear in a source platform name. This Actor's value lies in the bounded transformation and evidence it returns.

For an agency or internal service desk, create an intake checklist tied to the documented fields: authorized source, sample record, chosen settings, desired destination for the result and owner of partial/error review. Keep the first run small and preserve it as the agreed output contract. A larger recurring batch should use the same contract with explicit limits. Changes in source coverage, template meaning or record identity deserve a new review, not just a larger cap.

A service team can price its own analysis or integration work separately, but should keep the Actor's event charges visible. This README states the planned Actor tariff and its unit; it does not promise margin, customer revenue, conversion lift or a particular number of commercial outcomes. Where a task requires a human judgement, such as whether a suspicious price merits a quote request or an unknown delivery should be replayed, assign that judgement to the workflow owner.

### FAQ / Limitations

**Does a successful demo prove the source is live?** No. Synthetic and preview runs establish the local computation or rendering contract. The release acceptance needs its own real supplied-data or authorized delivery evidence. Demo markers remain in the data so they cannot quietly become a market observation.

**Can I pass a URL instead of a dataset ID?** No. Dataset ingestion uses an Apify dataset identifier and the buyer's storage access. URLs contained in supplied source rows are data, not generic network inputs. A custom field map changes which properties are read, not which hosts the Actor can visit.

**Why is a useful row marked found=false?** Some useful record types are explicitly free: operational notices, the product Actor's supplier summaries and the webhook Actor's previews. Interpret type and status before treating found as a universal business predicate. For the email Actor, a completed invalid-syntax check is a billable check even though the address itself is invalid.

**Why did the dataset grow by more rows than the number of paid events?** Free result types and notices share the dataset. Conversely, a persistence/charge failure can leave uncertain evidence that requires reconciliation. Compare the Actor's defined paid unit, the found/partial/error contract and actual platform charge receipts.

**Can I increase every limit to avoid partial work?** No. Hard input, structure, domain and message-product caps protect predictable execution. A working maxItems cap can be adjusted within its schema range, but it cannot bypass the hard runtime contract, the buyer's spend limit or the webhook delivery deadline. Split a larger workload intentionally and preserve source indexes in your own orchestration.

**Does the Actor update my original data?** No. It reads supplied data and writes a result dataset plus OUTPUT for this run. A later import into a CRM, catalog or report is an explicit consumer action. Keep the source reference so that normalized values and mapping decisions can be audited.

**Where should I report a bug or request a change?** Use the Actor page's issue channel when it is available. Provide a small sanitized reproduction and the relevant result classifications. Do not post secrets, private webhook destinations or complete personal-data lists in a public issue. The build draft is intended for review before the final Store listing is accepted.

![Run workflow and review boundary](assets/readme-workflow.svg)

### Recorded platform observations (accepted acceptance runs)

The records below are exact; only `checkedAt` differs between repeated runs.

#### OUTPUT from the accepted happy run

Run `GVKtlbBOc0swcL16T` on build 0.1.3, 2026-09-06, 5 s, Dataset records: 33, charged events: `{"apify-actor-start": 1, "result-found": 29}`.

```json
{
 "requested": 30,
 "processed": 29,
 "unprocessed": 0,
 "normalizedProducts": 29,
 "rejectedInputs": 0,
 "duplicateInputs": 1,
 "partial": false,
 "demoInput": true,
 "limitReason": "max_items",
 "delivered": 29,
 "paid": 29,
 "free": 4,
 "failed": 0,
 "fatal": "",
 "deliveryUncertain": 0,
 "budgetExhausted": false,
 "replaySafe": false,
 "replayNote": "Serialize schedules. No exactly-once ledger; reconcile uncertain delivery before replay.",
 "schemaVersion": "1.0",
 "checkedAt": "2026-09-06T02:18:07.629Z"
}
```

#### Correct empty-input record

Run `2AYjoC1HZwX0nWmV2` on build 0.1.3, 2026-09-06, 4 s, Dataset records: 1, charged events: `{"apify-actor-start": 1, "result-found": 0}`.

```json
{
 "schemaVersion": "1.0",
 "type": "no_data",
 "sourceUrl": null,
 "found": false,
 "status": "no_data",
 "resultCount": 0,
 "partial": false,
 "error": "",
 "warnings": [],
 "checkedAt": "2026-09-06T02:18:12.343Z",
 "evidence": "buyer_supplied_data",
 "confidence": null,
 "action": "review",
 "demo": false
}
```

#### Malformed-input record

Run `qCo7gWWO6Ueo7COMe` on build 0.1.3, 2026-09-06, 3 s, Dataset records: 1, charged events: `{"apify-actor-start": 1, "result-found": 0}`.

```json
{
 "schemaVersion": "1.0",
 "type": "rejected_input",
 "sourceUrl": null,
 "found": false,
 "status": "error",
 "resultCount": 0,
 "partial": true,
 "error": "invalid_product",
 "warnings": [],
 "checkedAt": "2026-09-06T02:18:20.911Z",
 "evidence": "buyer_supplied_data",
 "confidence": null,
 "action": "review",
 "demo": false,
 "inputIndex": 0
}
```

### Result-type examples

These additional records are exact records from the accepted runs above, selected to show distinct result types.

#### supplier\_summary

```json
{
 "schemaVersion": "1.0",
 "type": "supplier_summary",
 "sourceUrl": null,
 "found": false,
 "status": "ok",
 "resultCount": 0,
 "partial": false,
 "error": "",
 "warnings": [],
 "checkedAt": "2026-09-06T02:18:07.504Z",
 "evidence": "buyer_supplied_data",
 "confidence": null,
 "action": "review",
 "demo": true,
 "supplierId": "demo-supplier-0",
 "products": 8,
 "priceMinCny": 12.5,
 "priceMaxCny": 80,
 "suspiciousProducts": 0,
 "units": [
  "piece",
  "set",
  "box"
 ],
 "scope": "delivered_products",
 "synthetic": true
}
```

### 中文说明：1688、淘宝商品数据标准化

本工具只处理买家提供的商品记录，不访问商品页面。保留人民币价格区间、起订量和箱、件、套等单位；不会把一箱自动换成一件。汇率请求失败时使用 2026-09-04 的固定汇率并标记 fxStale。商品去重后计费，供应商汇总免费。默认数据为合成示例，不是报价。

### Sources and release evidence

- Accepted build plan: WAVE\_B\_PLAN.md §4 #10
- [FX API](https://frankfurter.dev/)
- [Exact rate request](https://api.frankfurter.dev/v1/latest?from=CNY\&to=USD,EUR)
- [OpenCC](https://github.com/nk2028/opencc-js)
- [Pinyin-pro](https://github.com/zh-lx/pinyin-pro)

Accepted platform runs on Apify's network (build 0.1.3, 2026-09-06): happy `GVKtlbBOc0swcL16T`, empty input `2AYjoC1HZwX0nWmV2`, cap notice `7CgDadqjOkwXbsMWv`, malformed input `qCo7gWWO6Ueo7COMe`, real 1688 wholesale export bought in the Store (zen-studio) `w3xjTge3y19IO28We`. Charged event counts were read back from the run records; local SDK 3.7.2 tests and proofs cover the failure paths that are not reproduced on the platform on purpose.

#### Related tools

Related tools for adjacent workflows in data pipelines for AI applications, e-commerce.

| Actor | What it does |
|---|---|
| [Shopify Catalog & Merchandising Intelligence](https://apify.com/zinin/shopify-store-intelligence) | Pair it in the e-commerce workflow: Qualify Shopify merchant leads with evidence-backed public catalog coverage, observed price positioning,... |
| [RAG Dataset Builder](https://apify.com/zinin/sitemap-to-knowledge) | Pair it in the data pipelines for AI applications workflow: Turn buyer-authorized public website sitemaps into bounded, source-linked text chunks for RAG, search,... |
| [Zid Product Export Intelligence](https://apify.com/zinin/zid-store-products) | Pair it in the e-commerce workflow: Turn merchant-owned, merchant-authorized, or otherwise licensed Zid product exports into stable evidence,... |
| [Chotot Vietnam Listings Scraper](https://apify.com/zinin/chotot-listings) | Pair it in the e-commerce workflow: Pull live classified ad listings (real estate, vehicles, electronics, jobs and more) straight from... |
| [Competitor Change Monitor — Tech, Hiring & Filings](https://apify.com/zinin/competitor-change-rollup) | Pair it in the e-commerce workflow: Monitor one competitor domain for technology, hiring, and SEC-name changes with explicit baselines,... |

# Actor input Schema

## `rows` (type: `array`):

Replace the clearly marked synthetic prefill with your own authorized data. Explicit datasetId suppresses unchanged demo rows. Runtime: 10 MiB input, 64 KiB per row, depth 16 and 100 items per nested array.

## `datasetId` (type: `string`):

Optional Apify dataset ID in your account. Read in pages of 100, at most 5000 rows and 10 MiB. No dataset URL. Remove custom inline rows when setting this. Dataset access is granted by selecting the resource in the resource picker.

## `fieldMap` (type: `object`):

Optional target-name to dotted-path map. At most 20 paths of 80 characters; prototype and executable paths rejected at runtime. See README for allowed target names.

## `targetCurrencies` (type: `array`):

Only USD and EUR, without duplicates. One FX request per run; dated pin on failure.

## `deduplicate` (type: `boolean`):

Pay for one normalized product per URL/ID group, with duplicate indexes retained.

## `includePinyin` (type: `boolean`):

Deterministic local pinyin transliteration for search.

## `includeTraditional` (type: `boolean`):

Local OpenCC script conversion, not translation.

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

Working output cap; remaining units are reported as unprocessed in OUTPUT. Error notices and free supplier summaries are additional.

## Actor input object example

```json
{
  "rows": [
    {
      "id": "demo-product-0",
      "url": "https://example.com/products/0",
      "title": "红色棉质短袖 M",
      "price": "¥12.5-15.0/件",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-1",
      "url": "https://example.com/products/1",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "≥100件 ¥9.8",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-2",
      "url": "https://example.com/products/2",
      "title": "黑色塑料收纳箱 L",
      "price": "¥80/箱",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-3",
      "url": "https://example.com/products/3",
      "title": "红色棉质短袖 M",
      "price": "¥0/个",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-4",
      "url": "https://example.com/products/4",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "¥25/套",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-5",
      "url": "https://example.com/products/5",
      "title": "黑色塑料收纳箱 L",
      "price": "¥4.5/kg",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-6",
      "url": "https://example.com/products/6",
      "title": "红色棉质短袖 M",
      "price": "¥12.5-15.0/件",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-7",
      "url": "https://example.com/products/7",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "≥100件 ¥9.8",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-8",
      "url": "https://example.com/products/8",
      "title": "黑色塑料收纳箱 L",
      "price": "¥80/箱",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-9",
      "url": "https://example.com/products/9",
      "title": "红色棉质短袖 M",
      "price": "¥0/个",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-10",
      "url": "https://example.com/products/10",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "¥25/套",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-11",
      "url": "https://example.com/products/11",
      "title": "黑色塑料收纳箱 L",
      "price": "¥4.5/kg",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-12",
      "url": "https://example.com/products/12",
      "title": "红色棉质短袖 M",
      "price": "¥12.5-15.0/件",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-13",
      "url": "https://example.com/products/13",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "≥100件 ¥9.8",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-14",
      "url": "https://example.com/products/14",
      "title": "黑色塑料收纳箱 L",
      "price": "¥80/箱",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-15",
      "url": "https://example.com/products/15",
      "title": "红色棉质短袖 M",
      "price": "¥0/个",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-16",
      "url": "https://example.com/products/16",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "¥25/套",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-17",
      "url": "https://example.com/products/17",
      "title": "黑色塑料收纳箱 L",
      "price": "¥4.5/kg",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-18",
      "url": "https://example.com/products/18",
      "title": "红色棉质短袖 M",
      "price": "¥12.5-15.0/件",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-19",
      "url": "https://example.com/products/19",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "≥100件 ¥9.8",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-20",
      "url": "https://example.com/products/20",
      "title": "黑色塑料收纳箱 L",
      "price": "¥80/箱",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-21",
      "url": "https://example.com/products/21",
      "title": "红色棉质短袖 M",
      "price": "¥0/个",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-22",
      "url": "https://example.com/products/22",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "¥25/套",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-23",
      "url": "https://example.com/products/23",
      "title": "黑色塑料收纳箱 L",
      "price": "¥4.5/kg",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-24",
      "url": "https://example.com/products/24",
      "title": "红色棉质短袖 M",
      "price": "¥12.5-15.0/件",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-25",
      "url": "https://example.com/products/25",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "≥100件 ¥9.8",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-26",
      "url": "https://example.com/products/26",
      "title": "黑色塑料收纳箱 L",
      "price": "¥80/箱",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-27",
      "url": "https://example.com/products/27",
      "title": "红色棉质短袖 M",
      "price": "¥0/个",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-28",
      "url": "https://example.com/products/28",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "¥25/套",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-0",
      "url": "https://example.com/products/0",
      "title": "黑色塑料收纳箱 L",
      "price": "¥4.5/kg",
      "supplierId": "demo-supplier-1",
      "demo": true
    }
  ],
  "datasetId": "buyerDatasetId",
  "fieldMap": {},
  "targetCurrencies": [
    "USD",
    "EUR"
  ],
  "deduplicate": true,
  "includePinyin": true,
  "includeTraditional": true,
  "maxItems": 30
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "rows": [
        {
            "id": "demo-product-0",
            "url": "https://example.com/products/0",
            "title": "红色棉质短袖 M",
            "price": "¥12.5-15.0/件",
            "supplierId": "demo-supplier-0",
            "demo": true
        },
        {
            "id": "demo-product-1",
            "url": "https://example.com/products/1",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "≥100件 ¥9.8",
            "supplierId": "demo-supplier-1",
            "demo": true
        },
        {
            "id": "demo-product-2",
            "url": "https://example.com/products/2",
            "title": "黑色塑料收纳箱 L",
            "price": "¥80/箱",
            "supplierId": "demo-supplier-2",
            "demo": true
        },
        {
            "id": "demo-product-3",
            "url": "https://example.com/products/3",
            "title": "红色棉质短袖 M",
            "price": "¥0/个",
            "supplierId": "demo-supplier-3",
            "demo": true
        },
        {
            "id": "demo-product-4",
            "url": "https://example.com/products/4",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "¥25/套",
            "supplierId": "demo-supplier-0",
            "demo": true
        },
        {
            "id": "demo-product-5",
            "url": "https://example.com/products/5",
            "title": "黑色塑料收纳箱 L",
            "price": "¥4.5/kg",
            "supplierId": "demo-supplier-1",
            "demo": true
        },
        {
            "id": "demo-product-6",
            "url": "https://example.com/products/6",
            "title": "红色棉质短袖 M",
            "price": "¥12.5-15.0/件",
            "supplierId": "demo-supplier-2",
            "demo": true
        },
        {
            "id": "demo-product-7",
            "url": "https://example.com/products/7",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "≥100件 ¥9.8",
            "supplierId": "demo-supplier-3",
            "demo": true
        },
        {
            "id": "demo-product-8",
            "url": "https://example.com/products/8",
            "title": "黑色塑料收纳箱 L",
            "price": "¥80/箱",
            "supplierId": "demo-supplier-0",
            "demo": true
        },
        {
            "id": "demo-product-9",
            "url": "https://example.com/products/9",
            "title": "红色棉质短袖 M",
            "price": "¥0/个",
            "supplierId": "demo-supplier-1",
            "demo": true
        },
        {
            "id": "demo-product-10",
            "url": "https://example.com/products/10",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "¥25/套",
            "supplierId": "demo-supplier-2",
            "demo": true
        },
        {
            "id": "demo-product-11",
            "url": "https://example.com/products/11",
            "title": "黑色塑料收纳箱 L",
            "price": "¥4.5/kg",
            "supplierId": "demo-supplier-3",
            "demo": true
        },
        {
            "id": "demo-product-12",
            "url": "https://example.com/products/12",
            "title": "红色棉质短袖 M",
            "price": "¥12.5-15.0/件",
            "supplierId": "demo-supplier-0",
            "demo": true
        },
        {
            "id": "demo-product-13",
            "url": "https://example.com/products/13",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "≥100件 ¥9.8",
            "supplierId": "demo-supplier-1",
            "demo": true
        },
        {
            "id": "demo-product-14",
            "url": "https://example.com/products/14",
            "title": "黑色塑料收纳箱 L",
            "price": "¥80/箱",
            "supplierId": "demo-supplier-2",
            "demo": true
        },
        {
            "id": "demo-product-15",
            "url": "https://example.com/products/15",
            "title": "红色棉质短袖 M",
            "price": "¥0/个",
            "supplierId": "demo-supplier-3",
            "demo": true
        },
        {
            "id": "demo-product-16",
            "url": "https://example.com/products/16",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "¥25/套",
            "supplierId": "demo-supplier-0",
            "demo": true
        },
        {
            "id": "demo-product-17",
            "url": "https://example.com/products/17",
            "title": "黑色塑料收纳箱 L",
            "price": "¥4.5/kg",
            "supplierId": "demo-supplier-1",
            "demo": true
        },
        {
            "id": "demo-product-18",
            "url": "https://example.com/products/18",
            "title": "红色棉质短袖 M",
            "price": "¥12.5-15.0/件",
            "supplierId": "demo-supplier-2",
            "demo": true
        },
        {
            "id": "demo-product-19",
            "url": "https://example.com/products/19",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "≥100件 ¥9.8",
            "supplierId": "demo-supplier-3",
            "demo": true
        },
        {
            "id": "demo-product-20",
            "url": "https://example.com/products/20",
            "title": "黑色塑料收纳箱 L",
            "price": "¥80/箱",
            "supplierId": "demo-supplier-0",
            "demo": true
        },
        {
            "id": "demo-product-21",
            "url": "https://example.com/products/21",
            "title": "红色棉质短袖 M",
            "price": "¥0/个",
            "supplierId": "demo-supplier-1",
            "demo": true
        },
        {
            "id": "demo-product-22",
            "url": "https://example.com/products/22",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "¥25/套",
            "supplierId": "demo-supplier-2",
            "demo": true
        },
        {
            "id": "demo-product-23",
            "url": "https://example.com/products/23",
            "title": "黑色塑料收纳箱 L",
            "price": "¥4.5/kg",
            "supplierId": "demo-supplier-3",
            "demo": true
        },
        {
            "id": "demo-product-24",
            "url": "https://example.com/products/24",
            "title": "红色棉质短袖 M",
            "price": "¥12.5-15.0/件",
            "supplierId": "demo-supplier-0",
            "demo": true
        },
        {
            "id": "demo-product-25",
            "url": "https://example.com/products/25",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "≥100件 ¥9.8",
            "supplierId": "demo-supplier-1",
            "demo": true
        },
        {
            "id": "demo-product-26",
            "url": "https://example.com/products/26",
            "title": "黑色塑料收纳箱 L",
            "price": "¥80/箱",
            "supplierId": "demo-supplier-2",
            "demo": true
        },
        {
            "id": "demo-product-27",
            "url": "https://example.com/products/27",
            "title": "红色棉质短袖 M",
            "price": "¥0/个",
            "supplierId": "demo-supplier-3",
            "demo": true
        },
        {
            "id": "demo-product-28",
            "url": "https://example.com/products/28",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "¥25/套",
            "supplierId": "demo-supplier-0",
            "demo": true
        },
        {
            "id": "demo-product-0",
            "url": "https://example.com/products/0",
            "title": "黑色塑料收纳箱 L",
            "price": "¥4.5/kg",
            "supplierId": "demo-supplier-1",
            "demo": true
        }
    ],
    "fieldMap": {},
    "targetCurrencies": [
        "USD",
        "EUR"
    ],
    "deduplicate": true,
    "includePinyin": true,
    "includeTraditional": true,
    "maxItems": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("zinin/1688-taobao-product-dataset-normalizer").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 = {
    "rows": [
        {
            "id": "demo-product-0",
            "url": "https://example.com/products/0",
            "title": "红色棉质短袖 M",
            "price": "¥12.5-15.0/件",
            "supplierId": "demo-supplier-0",
            "demo": True,
        },
        {
            "id": "demo-product-1",
            "url": "https://example.com/products/1",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "≥100件 ¥9.8",
            "supplierId": "demo-supplier-1",
            "demo": True,
        },
        {
            "id": "demo-product-2",
            "url": "https://example.com/products/2",
            "title": "黑色塑料收纳箱 L",
            "price": "¥80/箱",
            "supplierId": "demo-supplier-2",
            "demo": True,
        },
        {
            "id": "demo-product-3",
            "url": "https://example.com/products/3",
            "title": "红色棉质短袖 M",
            "price": "¥0/个",
            "supplierId": "demo-supplier-3",
            "demo": True,
        },
        {
            "id": "demo-product-4",
            "url": "https://example.com/products/4",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "¥25/套",
            "supplierId": "demo-supplier-0",
            "demo": True,
        },
        {
            "id": "demo-product-5",
            "url": "https://example.com/products/5",
            "title": "黑色塑料收纳箱 L",
            "price": "¥4.5/kg",
            "supplierId": "demo-supplier-1",
            "demo": True,
        },
        {
            "id": "demo-product-6",
            "url": "https://example.com/products/6",
            "title": "红色棉质短袖 M",
            "price": "¥12.5-15.0/件",
            "supplierId": "demo-supplier-2",
            "demo": True,
        },
        {
            "id": "demo-product-7",
            "url": "https://example.com/products/7",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "≥100件 ¥9.8",
            "supplierId": "demo-supplier-3",
            "demo": True,
        },
        {
            "id": "demo-product-8",
            "url": "https://example.com/products/8",
            "title": "黑色塑料收纳箱 L",
            "price": "¥80/箱",
            "supplierId": "demo-supplier-0",
            "demo": True,
        },
        {
            "id": "demo-product-9",
            "url": "https://example.com/products/9",
            "title": "红色棉质短袖 M",
            "price": "¥0/个",
            "supplierId": "demo-supplier-1",
            "demo": True,
        },
        {
            "id": "demo-product-10",
            "url": "https://example.com/products/10",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "¥25/套",
            "supplierId": "demo-supplier-2",
            "demo": True,
        },
        {
            "id": "demo-product-11",
            "url": "https://example.com/products/11",
            "title": "黑色塑料收纳箱 L",
            "price": "¥4.5/kg",
            "supplierId": "demo-supplier-3",
            "demo": True,
        },
        {
            "id": "demo-product-12",
            "url": "https://example.com/products/12",
            "title": "红色棉质短袖 M",
            "price": "¥12.5-15.0/件",
            "supplierId": "demo-supplier-0",
            "demo": True,
        },
        {
            "id": "demo-product-13",
            "url": "https://example.com/products/13",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "≥100件 ¥9.8",
            "supplierId": "demo-supplier-1",
            "demo": True,
        },
        {
            "id": "demo-product-14",
            "url": "https://example.com/products/14",
            "title": "黑色塑料收纳箱 L",
            "price": "¥80/箱",
            "supplierId": "demo-supplier-2",
            "demo": True,
        },
        {
            "id": "demo-product-15",
            "url": "https://example.com/products/15",
            "title": "红色棉质短袖 M",
            "price": "¥0/个",
            "supplierId": "demo-supplier-3",
            "demo": True,
        },
        {
            "id": "demo-product-16",
            "url": "https://example.com/products/16",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "¥25/套",
            "supplierId": "demo-supplier-0",
            "demo": True,
        },
        {
            "id": "demo-product-17",
            "url": "https://example.com/products/17",
            "title": "黑色塑料收纳箱 L",
            "price": "¥4.5/kg",
            "supplierId": "demo-supplier-1",
            "demo": True,
        },
        {
            "id": "demo-product-18",
            "url": "https://example.com/products/18",
            "title": "红色棉质短袖 M",
            "price": "¥12.5-15.0/件",
            "supplierId": "demo-supplier-2",
            "demo": True,
        },
        {
            "id": "demo-product-19",
            "url": "https://example.com/products/19",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "≥100件 ¥9.8",
            "supplierId": "demo-supplier-3",
            "demo": True,
        },
        {
            "id": "demo-product-20",
            "url": "https://example.com/products/20",
            "title": "黑色塑料收纳箱 L",
            "price": "¥80/箱",
            "supplierId": "demo-supplier-0",
            "demo": True,
        },
        {
            "id": "demo-product-21",
            "url": "https://example.com/products/21",
            "title": "红色棉质短袖 M",
            "price": "¥0/个",
            "supplierId": "demo-supplier-1",
            "demo": True,
        },
        {
            "id": "demo-product-22",
            "url": "https://example.com/products/22",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "¥25/套",
            "supplierId": "demo-supplier-2",
            "demo": True,
        },
        {
            "id": "demo-product-23",
            "url": "https://example.com/products/23",
            "title": "黑色塑料收纳箱 L",
            "price": "¥4.5/kg",
            "supplierId": "demo-supplier-3",
            "demo": True,
        },
        {
            "id": "demo-product-24",
            "url": "https://example.com/products/24",
            "title": "红色棉质短袖 M",
            "price": "¥12.5-15.0/件",
            "supplierId": "demo-supplier-0",
            "demo": True,
        },
        {
            "id": "demo-product-25",
            "url": "https://example.com/products/25",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "≥100件 ¥9.8",
            "supplierId": "demo-supplier-1",
            "demo": True,
        },
        {
            "id": "demo-product-26",
            "url": "https://example.com/products/26",
            "title": "黑色塑料收纳箱 L",
            "price": "¥80/箱",
            "supplierId": "demo-supplier-2",
            "demo": True,
        },
        {
            "id": "demo-product-27",
            "url": "https://example.com/products/27",
            "title": "红色棉质短袖 M",
            "price": "¥0/个",
            "supplierId": "demo-supplier-3",
            "demo": True,
        },
        {
            "id": "demo-product-28",
            "url": "https://example.com/products/28",
            "title": "蓝色不锈钢水杯 500ml",
            "price": "¥25/套",
            "supplierId": "demo-supplier-0",
            "demo": True,
        },
        {
            "id": "demo-product-0",
            "url": "https://example.com/products/0",
            "title": "黑色塑料收纳箱 L",
            "price": "¥4.5/kg",
            "supplierId": "demo-supplier-1",
            "demo": True,
        },
    ],
    "fieldMap": {},
    "targetCurrencies": [
        "USD",
        "EUR",
    ],
    "deduplicate": True,
    "includePinyin": True,
    "includeTraditional": True,
    "maxItems": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("zinin/1688-taobao-product-dataset-normalizer").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 '{
  "rows": [
    {
      "id": "demo-product-0",
      "url": "https://example.com/products/0",
      "title": "红色棉质短袖 M",
      "price": "¥12.5-15.0/件",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-1",
      "url": "https://example.com/products/1",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "≥100件 ¥9.8",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-2",
      "url": "https://example.com/products/2",
      "title": "黑色塑料收纳箱 L",
      "price": "¥80/箱",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-3",
      "url": "https://example.com/products/3",
      "title": "红色棉质短袖 M",
      "price": "¥0/个",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-4",
      "url": "https://example.com/products/4",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "¥25/套",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-5",
      "url": "https://example.com/products/5",
      "title": "黑色塑料收纳箱 L",
      "price": "¥4.5/kg",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-6",
      "url": "https://example.com/products/6",
      "title": "红色棉质短袖 M",
      "price": "¥12.5-15.0/件",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-7",
      "url": "https://example.com/products/7",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "≥100件 ¥9.8",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-8",
      "url": "https://example.com/products/8",
      "title": "黑色塑料收纳箱 L",
      "price": "¥80/箱",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-9",
      "url": "https://example.com/products/9",
      "title": "红色棉质短袖 M",
      "price": "¥0/个",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-10",
      "url": "https://example.com/products/10",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "¥25/套",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-11",
      "url": "https://example.com/products/11",
      "title": "黑色塑料收纳箱 L",
      "price": "¥4.5/kg",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-12",
      "url": "https://example.com/products/12",
      "title": "红色棉质短袖 M",
      "price": "¥12.5-15.0/件",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-13",
      "url": "https://example.com/products/13",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "≥100件 ¥9.8",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-14",
      "url": "https://example.com/products/14",
      "title": "黑色塑料收纳箱 L",
      "price": "¥80/箱",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-15",
      "url": "https://example.com/products/15",
      "title": "红色棉质短袖 M",
      "price": "¥0/个",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-16",
      "url": "https://example.com/products/16",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "¥25/套",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-17",
      "url": "https://example.com/products/17",
      "title": "黑色塑料收纳箱 L",
      "price": "¥4.5/kg",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-18",
      "url": "https://example.com/products/18",
      "title": "红色棉质短袖 M",
      "price": "¥12.5-15.0/件",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-19",
      "url": "https://example.com/products/19",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "≥100件 ¥9.8",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-20",
      "url": "https://example.com/products/20",
      "title": "黑色塑料收纳箱 L",
      "price": "¥80/箱",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-21",
      "url": "https://example.com/products/21",
      "title": "红色棉质短袖 M",
      "price": "¥0/个",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-22",
      "url": "https://example.com/products/22",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "¥25/套",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-23",
      "url": "https://example.com/products/23",
      "title": "黑色塑料收纳箱 L",
      "price": "¥4.5/kg",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-24",
      "url": "https://example.com/products/24",
      "title": "红色棉质短袖 M",
      "price": "¥12.5-15.0/件",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-25",
      "url": "https://example.com/products/25",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "≥100件 ¥9.8",
      "supplierId": "demo-supplier-1",
      "demo": true
    },
    {
      "id": "demo-product-26",
      "url": "https://example.com/products/26",
      "title": "黑色塑料收纳箱 L",
      "price": "¥80/箱",
      "supplierId": "demo-supplier-2",
      "demo": true
    },
    {
      "id": "demo-product-27",
      "url": "https://example.com/products/27",
      "title": "红色棉质短袖 M",
      "price": "¥0/个",
      "supplierId": "demo-supplier-3",
      "demo": true
    },
    {
      "id": "demo-product-28",
      "url": "https://example.com/products/28",
      "title": "蓝色不锈钢水杯 500ml",
      "price": "¥25/套",
      "supplierId": "demo-supplier-0",
      "demo": true
    },
    {
      "id": "demo-product-0",
      "url": "https://example.com/products/0",
      "title": "黑色塑料收纳箱 L",
      "price": "¥4.5/kg",
      "supplierId": "demo-supplier-1",
      "demo": true
    }
  ],
  "fieldMap": {},
  "targetCurrencies": [
    "USD",
    "EUR"
  ],
  "deduplicate": true,
  "includePinyin": true,
  "includeTraditional": true,
  "maxItems": 30
}' |
apify call zinin/1688-taobao-product-dataset-normalizer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zinin/1688-taobao-product-dataset-normalizer"
        }
    }
}

```

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/HRt6kziejRWCTJ4ka/builds/v3XKnBhZw2uiy5DZU/openapi.json
