# AliExpress Product & Variant Scraper (`chain_link/aliexpress-catalog-variant-scraper`) Actor

Scrape AliExpress search results, category pages and product URLs into clean JSON: prices, discounts, orders sold, ratings, store info, shipping cost/ETA for your chosen country, and full SKU-level variant pricing and stock.

- **URL**: https://apify.com/chain_link/aliexpress-catalog-variant-scraper.md
- **Developed by:** [James White](https://apify.com/chain_link) (community)
- **Categories:** E-commerce
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 1,000 product scrapeds

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## AliExpress Product & Variant Scraper

Turn AliExpress search results, category pages and product links into clean, ready-to-use
product data — including the **SKU-level variant table** (every colour/size option with its
own price and stock) that most catalogue scrapers leave out.

Give the Actor a few keywords, listing URLs or bare product IDs. It returns one row per
product with title, image gallery, current price, pre-discount price, discount percentage,
rating, review and orders count, store details, dispatch country, shipping cost and
delivery estimate, breadcrumb category path, and the full variant list.

No browser is used: the Actor reads the JSON that AliExpress embeds in its own pages, so
runs are fast and cheap.

### Price

**$0.0015 per product returned** (pay-per-event `product-scraped`). You are only charged for
rows that actually land in your dataset — pages that fail or are filtered out cost nothing.
Apify platform usage is billed separately by Apify as usual.

100 products ≈ $0.15. 10,000 products ≈ $15.

### Typical uses

- Dropshipping and product research: find winning items by price, orders and rating.
- Competitive price monitoring, including per-variant prices your competitors hide.
- Building a supplier catalogue feed with images, options and stock levels.
- Checking landed cost for one market: shipping cost and delivery ETA for your country.

### Inputs

| Field | Type | Default | What it does |
|---|---|---|---|
| `searchQueries` | array of strings | `[]` | Keyword phrases to search, e.g. `mechanical keyboard`. Each query is paginated until `maxItems` is reached. |
| `startUrls` | array of strings | `[]` | AliExpress search, category or product URLs to scrape directly. Product URLs are fetched as single products. |
| `productIds` | array of strings | `[]` | Bare AliExpress item IDs, e.g. `1005006238899018`. |
| `maxItems` | integer | `100` | Hard cap on how many products are output across all inputs. The run stops fetching as soon as it is reached. |
| `shipToCountry` | string | `US` | ISO-2 country code used to resolve prices, shipping cost and delivery estimate, e.g. `US`, `DE`, `BR`. |
| `currency` | string | `USD` | Currency requested for returned prices, e.g. `USD`, `EUR`, `GBP`. |
| `language` | string | `en` | Site language for titles and attribute names, e.g. `en`, `es`, `fr`. |
| `sortBy` | string | `default` | Listing order: `default`, `price_asc`, `price_desc`, `orders_desc`, `newest`. |
| `minPrice` | integer | `0` | Drop products cheaper than this (in the chosen currency). `0` disables. |
| `maxPrice` | integer | `0` | Drop products more expensive than this. `0` disables. |
| `includeVariants` | boolean | `true` | Also open each product page to collect per-variant price, stock and attributes, plus store, gallery, shipping and category data. Slower, much richer. |
| `freeShippingOnly` | boolean | `false` | Keep only products confirmed to ship free to the selected country. |

At least one of `searchQueries`, `startUrls` or `productIds` must be filled.

#### Example input

```json
{
  "searchQueries": ["mechanical keyboard", "usb c cable"],
  "startUrls": ["https://www.aliexpress.com/w/wholesale-smart-watch.html"],
  "productIds": ["1005006238899018"],
  "maxItems": 200,
  "shipToCountry": "US",
  "currency": "USD",
  "language": "en",
  "sortBy": "orders_desc",
  "minPrice": 5,
  "maxPrice": 120,
  "includeVariants": true,
  "freeShippingOnly": false
}
```

### Output

One dataset row per product.

| Field | Type | Description |
|---|---|---|
| `productId` | string | AliExpress item ID. |
| `url` | string | Canonical product URL. |
| `title` | string | Product title. |
| `imageUrl` | string | Main product image. |
| `images` | array | Gallery image URLs (filled when the product page is opened). |
| `price` | number | Current sale price. |
| `originalPrice` | number | Pre-discount list price when shown, otherwise `null`. |
| `discountPercent` | number | Discount off the list price, otherwise `null`. |
| `currency` | string | Currency code of the returned prices. |
| `ratingAvg` | number | Average stars out of 5, when shown. |
| `reviewCount` | integer | Number of reviews, when shown. |
| `ordersCount` | integer | Units sold / orders as shown by AliExpress. |
| `storeName` | string | Seller store name. |
| `storeId` | string | Seller store ID. |
| `storeUrl` | string | Seller store URL. |
| `shipsFrom` | string | Declared dispatch country. |
| `shippingCost` | number | Shipping cost to the selected country, `0` when free. |
| `deliveryEstimate` | string | Delivery window text for the selected country. |
| `variants` | array | SKU rows: `skuId`, `attributes`, `price`, `originalPrice`, `stock`, `inStock`. |
| `categoryPath` | array | Breadcrumb category names. |
| `sourceQuery` | string | The query, URL or ID that produced the row. |
| `scrapedAt` | string | ISO 8601 extraction timestamp. |

#### Example output row

```json
{
  "productId": "1005009494458560",
  "url": "https://www.aliexpress.com/item/1005009494458560.html",
  "title": "AJAZZ NK61 Wired Gaming Mechanical Keyboard 60% RGB Hot-Swappable 61 Keys Red Switch Mini Keyboard for Gamer PC",
  "imageUrl": "https://ae-pic-a1.aliexpress-media.com/kf/S21fa9e98da3547c5a2e840c1917ce9cdI.png_480x480.png",
  "images": [
    "https://ae-pic-a1.aliexpress-media.com/kf/S21fa9e98da3547c5a2e840c1917ce9cdI.png",
    "https://ae-pic-a1.aliexpress-media.com/kf/S4b1f7b7a1a6f4c0aa7b1b0a9a1d0f1e2.png"
  ],
  "price": 31.49,
  "originalPrice": 43.16,
  "discountPercent": 27.0,
  "currency": "USD",
  "ratingAvg": 4.7,
  "reviewCount": 2841,
  "ordersCount": 15288,
  "storeName": "AJAZZ Official Store",
  "storeId": "1102283018",
  "storeUrl": "https://www.aliexpress.com/store/1102283018",
  "shipsFrom": "CN",
  "shippingCost": 0,
  "deliveryEstimate": "Delivery: Feb 18 - Mar 02",
  "variants": [
    {
      "skuId": "12000049283740115",
      "attributes": { "Color": "Black", "Switch": "Red Switch" },
      "price": 31.49,
      "originalPrice": 43.16,
      "stock": 812,
      "inStock": true
    },
    {
      "skuId": "12000049283740116",
      "attributes": { "Color": "White", "Switch": "Brown Switch" },
      "price": 33.99,
      "originalPrice": 45.99,
      "stock": 0,
      "inStock": false
    }
  ],
  "categoryPath": ["Computer & Office", "Keyboards & Mice", "Keyboards"],
  "sourceQuery": "mechanical keyboard",
  "scrapedAt": "2024-06-05T09:41:12Z"
}
```

### Limits and honest notes

- **Only what AliExpress publishes.** Fields such as `reviewCount`, `shippingCost`,
  `deliveryEstimate`, `shipsFrom` or `originalPrice` are returned when the page exposes
  them and are `null` otherwise. Nothing is guessed.
- **Variants require `includeVariants: true`**, which opens one extra page per product. With
  it off the run is faster but `variants`, `images`, store and shipping fields stay mostly empty.
- **Ship-to country, currency and language** are requested through AliExpress's own site
  preference mechanism. AliExpress may still answer in its regional default for some
  routes; the `currency` field always reports the currency of the prices actually returned.
- **Sponsored cards** appear in AliExpress listings and are returned like any other product.
- **Pagination depth** is limited by AliExpress itself (roughly a few dozen pages per
  query). Use several narrower queries or price bands for large harvests.
- **If AliExpress blocks the run** (HTTP 403 / 429 or an anti-bot challenge), the Actor logs
  this clearly and stops instead of trying to get around it. You keep everything already
  scraped and are billed only for delivered rows.
- Requests are sent with the honest User-Agent `Mozilla/5.0 (compatible;
  aliexpress-catalog-variant-scraper/1.0)`, at most 4 in parallel, with retries and a pause
  between listing pages.

### Terms

This Actor reads only publicly reachable AliExpress catalogue pages; it never logs in and
collects no buyer, reviewer or other personal data. AliExpress's terms of use discourage
automated collection and redistribution of site content, so you are responsible for making
sure your use of the output complies with those terms and with applicable law in your
jurisdiction. Prices, stock and delivery estimates change constantly — treat every row as a
snapshot taken at `scrapedAt`.

# Actor input Schema

## `searchQueries` (type: `array`):

Keyword phrases to search on AliExpress, e.g. "mechanical keyboard". Each query is paginated until maxItems is reached.

## `startUrls` (type: `array`):

AliExpress search, category or product URLs to scrape directly.

## `productIds` (type: `array`):

Bare AliExpress item IDs (e.g. "1005006238899018") to fetch as product detail pages.

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

Maximum number of products to output across all inputs.

## `shipToCountry` (type: `string`):

ISO-2 country code used to resolve shipping cost and delivery estimate, e.g. US, DE, BR.

## `currency` (type: `string`):

Currency code for returned prices, e.g. USD, EUR, GBP.

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

Site language locale for titles and attributes, e.g. en, es, fr.

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

Search result ordering: default, price_asc, price_desc, orders_desc, newest.

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

Filter out products priced below this value in the chosen currency. 0 disables.

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

Filter out products priced above this value in the chosen currency. 0 disables.

## `includeVariants` (type: `boolean`):

Open each product page and extract per-variant price, stock and attributes. Slower but much richer.

## `freeShippingOnly` (type: `boolean`):

Keep only products that ship free to the selected country.

## Actor input object example

```json
{
  "searchQueries": [],
  "startUrls": [],
  "productIds": [],
  "maxItems": 100,
  "shipToCountry": "US",
  "currency": "USD",
  "language": "en",
  "sortBy": "default",
  "includeVariants": true
}
```

# Actor output Schema

## `results` (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 = {
    "searchQueries": [],
    "startUrls": [],
    "productIds": [],
    "maxItems": 100,
    "shipToCountry": "US",
    "currency": "USD",
    "language": "en",
    "sortBy": "default",
    "minPrice": 0,
    "maxPrice": 0,
    "includeVariants": true,
    "freeShippingOnly": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("chain_link/aliexpress-catalog-variant-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchQueries": [],
    "startUrls": [],
    "productIds": [],
    "maxItems": 100,
    "shipToCountry": "US",
    "currency": "USD",
    "language": "en",
    "sortBy": "default",
    "minPrice": 0,
    "maxPrice": 0,
    "includeVariants": True,
    "freeShippingOnly": False,
}

# Run the Actor and wait for it to finish
run = client.actor("chain_link/aliexpress-catalog-variant-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [],
  "startUrls": [],
  "productIds": [],
  "maxItems": 100,
  "shipToCountry": "US",
  "currency": "USD",
  "language": "en",
  "sortBy": "default",
  "minPrice": 0,
  "maxPrice": 0,
  "includeVariants": true,
  "freeShippingOnly": false
}' |
apify call chain_link/aliexpress-catalog-variant-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,chain_link/aliexpress-catalog-variant-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/3CrMX5HBJcd3WdZ5A/builds/VT7vgwJ0hnLdpiL01/openapi.json
