{
  "openapi": "3.0.1",
  "info": {
    "title": "Taobao & Tmall Products Scraper",
    "description": "Scrape Taobao & Tmall products by keyword, province, category, shop or product URL: title, price, discount, shop, shop rating, images. No login. Export to JSON, CSV or Excel.",
    "version": "0.0",
    "x-build-id": "5gdgHH7inEQuYhtCH"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/nice_dev~taobao-products-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-nice_dev-taobao-products-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/nice_dev~taobao-products-scraper/runs": {
      "post": {
        "operationId": "runs-sync-nice_dev-taobao-products-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/nice_dev~taobao-products-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-nice_dev-taobao-products-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "startUrls": {
            "title": "Taobao / Tmall URLs",
            "maxItems": 1000,
            "type": "array",
            "description": "Any mix of: keyword pages (`https://www.taobao.com/list/product/蓝牙耳机.htm`, or a search link such as `https://s.taobao.com/search?q=iphone`, read as its keyword), category pages (`https://www.taobao.com/list/category/50005050.htm`), shop pages (`https://world.taobao.com/dianpu/239494884.htm`) and product pages (`https://item.taobao.com/item.htm?id=1042700373143`, `https://detail.tmall.com/item.htm?id=1042700373143`, `https://world.taobao.com/item/1042700373143.htm`, or e.tb.cn / m.tb.cn share links). When this list is not empty, the keyword fields below are ignored; filters, caps and monitoring still apply. Max 1 000 URLs.",
            "default": [],
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "query": {
            "title": "Search keyword",
            "maxLength": 200,
            "type": "string",
            "description": "Keyword, as typed on Taobao. Chinese keywords work best (e.g. `蓝牙耳机` = Bluetooth earphones); short English words like `iphone` or `sneakers` work too. Taobao publishes a public page for common product terms only: a keyword without one returns nothing and is named in the run log (not charged)."
          },
          "searchQueries": {
            "title": "More search keywords",
            "maxItems": 100,
            "uniqueItems": true,
            "type": "array",
            "description": "Several keywords in one run: one search per keyword (times each province below, max 500 searches). Added to **Search keyword**; products found by several searches are saved once.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "location": {
            "title": "Ships from (province)",
            "maxLength": 200,
            "type": "string",
            "description": "Only products shipped from this Chinese province, as Taobao lists them (e.g. `广东` / `Guangdong`, `浙江` / `Zhejiang`, `上海` / `Shanghai`): Taobao's own 'province' filter. Empty = all of China."
          },
          "locations": {
            "title": "More provinces",
            "maxItems": 100,
            "uniqueItems": true,
            "type": "array",
            "description": "Several provinces in one run: every keyword is searched in every province (3 keywords × 4 provinces = 12 searches, max 500). Added to **Ships from (province)**.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "categoryIds": {
            "title": "Category IDs",
            "maxItems": 100,
            "uniqueItems": true,
            "type": "array",
            "description": "Taobao category numbers, read in a category URL (`/category/50005050.htm` → `50005050`) or in the `categoryId` field of a previous run. Use the most precise category: a top-level category (e.g. `50011972`) has no public page.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "shopIds": {
            "title": "Shop IDs",
            "maxItems": 500,
            "uniqueItems": true,
            "type": "array",
            "description": "Taobao / Tmall shop numbers (the `shopId` field of a previous run, or the number in a `world.taobao.com/dianpu/239494884.htm` URL): the shop's listed products (up to 60 per shop).",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "productUrls": {
            "title": "Product URLs or IDs",
            "maxItems": 1000,
            "uniqueItems": true,
            "type": "array",
            "description": "Single products to read, as URLs (`https://item.taobao.com/item.htm?id=1042700373143`, `https://detail.tmall.com/item.htm?id=1042700373143`, e.tb.cn share links) or bare product IDs (`1042700373143`). Each one is read from its product page, so it is charged as a product with **Product page** (see Pricing). Affiliate links (s.click.taobao.com) need a Taobao login and are skipped with a log line.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "maxItems": {
            "title": "Max products",
            "minimum": 0,
            "maximum": 100000,
            "type": "integer",
            "description": "Maximum number of products to save for the whole run (after deduplication and filters). 0 = no limit.",
            "default": 100
          },
          "maxItemsPerQuery": {
            "title": "Max products per search",
            "minimum": 0,
            "maximum": 100000,
            "type": "integer",
            "description": "Cap for EACH search (keyword, category, shop or search URL), so that the first search cannot use up the whole **Max products** budget. 0 = no per-search cap.",
            "default": 0
          },
          "deepScan": {
            "title": "Go past the first 20 results",
            "type": "boolean",
            "description": "Without an account, Taobao shows 20 products per keyword or category page and no page 2. On: the Actor reads the same search again in several orders, price ranges and brands, and keeps the new products each time, so a search returns hundreds of products instead of 20. On a small catalogue, some of the extra products may only have your keyword in their title: Taobao widens the search. The province filter is approximate too: about 2 products in 15 ship from another province. Off = 20 per keyword or category (faster). No fee of its own: you pay per product saved (with a filter on, each product it drops pays its filter fee, and more products are read).",
            "default": true
          },
          "sortBy": {
            "title": "Sort",
            "enum": [
              "sales",
              "price-desc",
              "default"
            ],
            "type": "string",
            "description": "Order of the search results, as on Taobao. Taobao has no 'lowest price first' order on these pages (it returns nothing): use **Max price** instead. Taobao has no 'newest' order: use **Only new products** below to get the new ones at each run.",
            "default": "sales"
          },
          "minPrice": {
            "title": "Min price (CNY)",
            "minimum": 0,
            "maximum": 100000000,
            "type": "number",
            "description": "Only products from this price, in Chinese yuan (CNY). Sent to Taobao and checked again on each product."
          },
          "maxPrice": {
            "title": "Max price (CNY)",
            "minimum": 0,
            "maximum": 100000000,
            "type": "number",
            "description": "Only products up to this price, in Chinese yuan (CNY). Sent to Taobao and checked again on each product. Empty or 0 = no maximum."
          },
          "freeShippingOnly": {
            "title": "Free shipping only",
            "type": "boolean",
            "description": "Taobao filter 'free shipping' (包邮, within mainland China). Applied to keyword and category searches.",
            "default": false
          },
          "language": {
            "title": "Chinese script",
            "enum": [
              "zh-CN",
              "zh-TW"
            ],
            "type": "string",
            "description": "Script of the titles and shop names: simplified Chinese (mainland China, as the sellers write them) or traditional Chinese (Hong Kong, Taiwan). Prices are the same.",
            "default": "zh-CN"
          },
          "translateKeywords": {
            "title": "Translate keywords to Chinese",
            "type": "boolean",
            "description": "Translate the keywords that are not in Chinese (English, French, Spanish...) with DeepL before searching, into the script chosen above: `sneakers` is searched as `运动鞋`. Needs your own DeepL API key below: the translation is done and billed by DeepL on YOUR account (their free plan is enough for keywords). One extra request for the whole list. Keywords already in Chinese are left as they are. If DeepL refuses or does not answer, the keywords are searched as written, with a warning in the log. Each row says the word you typed in `originalKeyword`. Not applied to keywords inside **Taobao / Tmall URLs**.",
            "default": false
          },
          "deeplApiKey": {
            "title": "DeepL API key",
            "type": "string",
            "description": "Your DeepL API key (DeepL account > API keys; a key ending in `:fx` is the free plan). Only used by **Translate keywords to Chinese**; stored encrypted, never written in the log or in the results."
          },
          "extractDetails": {
            "title": "Product page",
            "type": "boolean",
            "description": "Read each product's page (1 extra request per product): Taobao or Tmall, ship-from city, original and promotion price, seller type and credit level, shop opening date and number of products, the shop's 3 scores against its category, the share of positive / neutral / negative buyer ratings, payment methods and the coupon link. Charged per product read (event `item-details`).",
            "default": false
          },
          "includeReviews": {
            "title": "Latest review and review keywords",
            "type": "boolean",
            "description": "Add the latest buyer review shown on the product page (rating, text, date, variant bought, follow-up review, photo URLs) and the review keywords with how many buyers used them (e.g. `long battery life: 330`). Reads the product page, so it turns **Product page** on. Charged per product that has them (event `review`). Taobao shows only this one review without a login.",
            "default": false
          },
          "maxReviewsPerProduct": {
            "title": "Reviews per product (needs your cookie)",
            "minimum": 1,
            "maximum": 100,
            "type": "integer",
            "description": "How many of the latest reviews to save for each product, in the `reviews` list (newest first). 1 = only the latest review, as above, no cookie needed. Above 1 needs your Taobao cookie (see **Your Taobao cookie**) and **Latest review and review keywords** switched on: the run refuses to start without them. Still charged once per product that has reviews (event `review`).",
            "default": 1
          },
          "includeShopProfile": {
            "title": "One row per shop",
            "type": "boolean",
            "description": "Add one row per shop (`type` = `shop`): shop name and logo, seller ID, the shop's 3 scores and the size of its whole catalogue. For the shops listed above, and also for each shop of the products found (1 extra request per shop). Charged per shop row (event `shop`).",
            "default": false
          },
          "cookie": {
            "title": "Your Taobao cookie (optional)",
            "type": "string",
            "description": "Give the cookie of YOUR Taobao account to add, with **Product page** on, the variants of each product (`variants`: colour, size, price and stock of each), its monthly sales (`monthlySales`), its video (`videoUrl`) and, with **Reviews per product** above 1, the reviews past the first (`reviews`). How to copy it: log in to taobao.com in your browser, open the developer tools (F12) > Network, click any request to taobao.com and copy the whole `Cookie` request header. It must contain `_m_h5_tk=`; the parts used are `_m_h5_tk`, `_m_h5_tk_enc`, `cookie2`, `_tb_token_`, `unb`, `sgcookie` and `t`. It is used only to read public pages at a visitor's pace, never written to the dataset or the log. If Taobao refuses it (expired, logged out) the run stops with a message asking you to copy a fresh one. Use an account of your own: Taobao may ask it to log in again after heavy use. Not tested with a real account yet: tell us in the Issues tab if something fails."
          },
          "excludeKeywords": {
            "title": "Exclude keywords",
            "maxItems": 50,
            "uniqueItems": true,
            "type": "array",
            "description": "Drop the products whose title contains one of these WHOLE words (case and accents ignored; simplified and traditional Chinese both matched): `art` drops \"Art deco\" but keeps \"Smart watch\". Several words in one entry (`hand made`) must appear together, in that order. Chinese, Japanese, Korean, Thai, Lao, Khmer and Burmese words are found anywhere in the title (no spaces there).",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "minRating": {
            "title": "Min shop score",
            "minimum": 0,
            "maximum": 5,
            "type": "number",
            "description": "Only products whose shop scores at least this for 'item as described' (out of 5, e.g. `4.8`), as shown in the search results. Products without a score are dropped."
          },
          "tmallOnly": {
            "title": "Tmall only",
            "type": "boolean",
            "description": "Only products sold by Tmall shops (brand and official stores). Taobao shows it on the product page only: needs **Product page** (without it this filter is ignored). A dropped product is charged a detail filter fee (see Pricing).",
            "default": false
          },
          "onlyNew": {
            "title": "Only new products",
            "type": "boolean",
            "description": "Skip the products that a previous run (same **Memory key**) already delivered: they are not saved and not charged, and their page is not even opened. First run = everything is new. \"New\" means never delivered to you, not newly listed: Taobao has no listing date, so a later run can bring older products the earlier runs did not reach.",
            "default": false
          },
          "includePriceChanges": {
            "title": "Also products whose price changed",
            "type": "boolean",
            "description": "With **Only new products**: also return the products already delivered whose price went up or down since the last run, with the previous price and the change in %. Charged per changed product (event `price-change`).",
            "default": false
          },
          "minPriceChangePercent": {
            "title": "Min price change (%)",
            "minimum": 0,
            "maximum": 100,
            "type": "number",
            "description": "With **Also products whose price changed**: a product comes back only if its price (`price`, CNY) moved by at least this many % since the last time it was delivered.",
            "default": 3
          },
          "stateKey": {
            "title": "Memory key",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$",
            "maxLength": 64,
            "type": "string",
            "description": "Name of the memory used by **Only new products**. Give each schedule / task its own key (e.g. `earphones-tmall`) so that they do not share their memory. Letters, digits, `-` and `_`.",
            "default": "default"
          },
          "resetState": {
            "title": "Reset the memory",
            "type": "boolean",
            "description": "Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every product again. Untick it afterwards.",
            "default": false
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Apify Proxy or your own proxies. Keep the default: it is included in the price, and the Actor switches IP by itself when Taobao turns one away. Sorting, price, province and free-shipping filters and **Go past the first 20 results** go through the Actor's own connections, also included in the price. The residential Apify proxy is not available in this Actor.",
            "default": {
              "useApifyProxy": true
            }
          },
          "maxConcurrency": {
            "title": "Max concurrency",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "Maximum number of requests processed in parallel.",
            "default": 5
          },
          "maxRequestsPerMinute": {
            "title": "Max requests per minute",
            "minimum": 10,
            "maximum": 2000,
            "type": "integer",
            "description": "Most requests to Taobao in any 60 seconds, all of them counted: search pages, product pages and shop pages. A budget, not an even pace: up to this many can leave at once when the minute starts (spread them with the minimum delay below). Lower it if the log shows many 'turned away' lines.",
            "default": 120
          },
          "minRequestIntervalMs": {
            "title": "Min delay between requests",
            "minimum": 0,
            "maximum": 60000,
            "type": "integer",
            "description": "Smallest gap between two requests, in milliseconds. Unlike the per-minute rate, this spreads the requests evenly instead of letting them go out in a burst. 0 = no gap.",
            "default": 0
          },
          "maxRequestRetries": {
            "title": "Max request retries",
            "minimum": 0,
            "maximum": 20,
            "type": "integer",
            "description": "Retries per request before it is marked as failed. Behind a proxy, a request Taobao turns away is also retried on a new proxy session up to 10 times without using up these retries.",
            "default": 5
          },
          "debugLog": {
            "title": "Debug log",
            "type": "boolean",
            "description": "Include debug messages in the run log.",
            "default": false
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}