# AliExpress Products Scraper (`devilscrapes/aliexpress-products-scraper`) Actor

Scrape AliExpress product data by search keyword, product URL, or product ID -- price, rating, order count, per-variant stock levels, and shipping-cost estimates to your destination country, delivered as clean typed rows for dropshippers and product-sourcing research.

- **URL**: https://apify.com/devilscrapes/aliexpress-products-scraper.md
- **Developed by:** [DevilScrapes](https://apify.com/devilscrapes) (community)
- **Categories:** E-commerce
- **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

<div align="center">
  <img src=".actor/icon.svg" width="160" alt="Devil Scrapes mark" />

## AliExpress Products Scraper

**💰 $2.05 / 1 000 results**  ·  pay only for results  ·  no credit card to try

*We do the dirty work so your dataset stays clean.* 😈

Scrape AliExpress product data by search keyword, product URL, or product ID — price, rating, and an explicit order-count badge, delivered as clean typed rows for dropshippers and product-sourcing research.

</div>

***

### 🎯 What this scrapes

AliExpress runs no public product-data API for shoppers, and its product-detail page is a client-side-rendered app shell with zero product data in the raw HTML — we execute it in a real, fingerprint-resistant browser so the numbers are actually there. This Actor resolves products three ways — search keyword, direct product URL, or product ID — and returns one clean schema across all three: price, currency, rating, review count, and an explicit `order_count` (the "500+ sold" badge) most AliExpress scrapers skip past.

### 🔥 What we handle for you

- 🛡️ **Browser fingerprint rotation** — `curl-cffi` impersonates real Chrome / Firefox / Safari TLS handshakes so the target sees a browser, not Python.
- 🌐 **Residential proxy rotation** via Apify Proxy — fresh session and exit IP on every block.
- 🔁 **Retries with exponential backoff** on `408 / 429 / 5xx` — up to 5 attempts per page, `Retry-After` honoured.
- 🧱 **Rate-limit-aware pacing** — when the target pushes back, we slow down instead of getting banned.
- 🧊 **Clean, typed dataset rows** — Pydantic-validated, ISO-8601 timestamps, stable product IDs, JSON / CSV / Excel export straight from the Apify Console.
- 💰 **Pay-Per-Event pricing** — you only pay for results that hit your dataset. No data, no charge.

### 💡 Use cases

- **Dropshipping product validation** — check price, rating, and order count before you list a product.
- **Amazon private-label sourcing research** — cross-reference candidate SKUs by order volume instead of eyeballing the storefront.
- **Competitor price monitoring** — track price movement across a candidate catalog by search keyword or product ID.
- **Catalog enrichment** — resolve a list of product URLs or IDs into title, price, rating, and images in one call.
- **Market-price snapshots** — run the same keyword across a run schedule to build your own price-history series (AliExpress doesn't publish one).

### ⚙️ How to use it

1. Click **Try for free** at the top of the page.
2. Fill in the input form — most fields have sensible defaults.
3. Click **Start**. Output streams into the run's dataset.
4. Export from **Storage → Dataset** as JSON, CSV, or Excel — or fetch via the API.

### 📥 Input

| Field | Type | Required | Default | Notes |
|---|---|:--:|---|---|
| `searchKeywords` | `array` | no\* | `[]` | Search terms; each yields up to `maxResultsPerKeyword` products. |
| `productUrls` | `array` | no\* | `[]` | Direct `aliexpress.com/item/{id}.html` URLs; the product ID is extracted automatically. |
| `productIds` | `array` | no\* | `[]` | Direct numeric product IDs (8-16 digits), fetched via `/item/{id}.html`. |
| `maxResultsPerKeyword` | `integer` | no | `20` | Cap on rows emitted per search keyword (1-200). |
| `shippingDestinationCountry` | `string` | no | `"US"` | ISO 3166-1 alpha-2 country code that `shipping_cost_estimate` is computed against. |
| `proxyConfiguration` | `object` | no | `{"useApifyProxy": true}` | Apify Proxy spec. |

\* At least one of `searchKeywords`, `productUrls`, `productIds` is required — combine all three freely, rows are de-duplicated by `product_id` across modes.

#### Example input

```json
{
  "searchKeywords": [
    "wireless earbuds"
  ],
  "maxResultsPerKeyword": 3,
  "shippingDestinationCountry": "US",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

### 📤 Output

Every row is one dataset item.

| Field | Type | Notes |
|---|---|---|
| `product_id` | `string` | Input, or extracted from `productUrls`. |
| `title` | `string` | Product title. |
| `price` | `number` | Current listed price. |
| `currency` | `string` | ISO 4217 code accompanying `price`. |
| `rating` | `number \| null` | Average star rating, 0.0-5.0, when published. |
| `review_count` | `integer \| null` | Number of reviews backing the rating. |
| `order_count` | `integer \| null` | Parsed orders/sold badge (e.g. "500+ sold"); `null` when absent — never fabricated. Populated for `searchKeywords` rows; not currently exposed on `productUrls`/`productIds` rows (see Limitations). |
| `variants` | `array` | One `{variant_name, sku, stock_count}` entry per variant option; currently always `[]` — see Limitations. |
| `shipping_cost_estimate` | `number \| null` | Cost to `shipping_destination`; currently always `null` — see Limitations. |
| `shipping_destination` | `string` | Echoes `shippingDestinationCountry`. |
| `product_url` | `string` | Canonical `aliexpress.com/item/{product_id}.html` URL. |
| `image_urls` | `array` | Product gallery image URLs. |
| `seller_name` | `string \| null` | Store/seller display name; currently always `null` — see Limitations. |
| `category` | `string \| null` | Breadcrumb category string; currently always `null` — see Limitations. |
| `search_keyword` | `string \| null` | Populated only for `searchKeywords`-mode rows. |
| `scraped_at` | `string` | ISO-8601 UTC row-creation timestamp. |

#### Example output

```json
{
  "product_id": "3256811548194791",
  "title": "Air Pro ANC Wireless Earphone Bluetooth Headsets Pro 2 Active Noise Cancellation",
  "price": 3.67,
  "currency": "USD",
  "rating": 4.8,
  "review_count": 334,
  "order_count": null,
  "variants": [],
  "shipping_cost_estimate": null,
  "shipping_destination": "US",
  "product_url": "https://www.aliexpress.com/item/3256811548194791.html",
  "image_urls": [
    "https://ae-pic-a1.aliexpress-media.com/kf/S883875aebfd44d7ab6eed07c5fe2fae09.jpg"
  ],
  "seller_name": null,
  "category": null,
  "search_keyword": null,
  "scraped_at": "2026-08-31T06:45:00.368Z"
}
```

### 💰 Pricing

Pay-Per-Event — you pay only when these events fire:

| Event | USD | What it is |
|---|---:|---|
| `actor-start` | $0.05 | One-off warm-up charge per run |
| `product-scraped` | $0.002 | Per product row written to the dataset |

Example: 1 000 results at the rates above ≈ **$2.05**. No subscription, no minimum, no card to start — Apify gives every new account free credit to try it.

### 🚧 Limitations

`searchKeywords` and `productUrls`/`productIds` rows come from genuinely different fetch paths, so their field coverage differs today:

- **`searchKeywords` rows**: title, price, currency, rating, and `order_count` all come from the search results page directly.
- **`productUrls`/`productIds` rows**: AliExpress's product-detail page ships zero product data in its raw HTML — every field comes from a structured-data block a real browser render exposes. That block carries title, price, currency, rating, review count, and images, but not `order_count`.
- **`variants`, `seller_name`, `category`, `shipping_cost_estimate` are currently always `null`/`[]`** on every row, both modes. AliExpress doesn't expose per-variant stock, seller name, or category on any page surface we've found a reliable source for yet, and its shipping-cost endpoint isn't publicly reachable. We'd rather ship an honest `null` than a guessed value — these are on our roadmap as the storefront's endpoints get mapped further.
- **`productUrls`/`productIds` lookups render the live page in a real browser**, and an individual render can occasionally fail to resolve — we retry once with a fresh session automatically, and a still-unresolved entry is skipped (not billed) and named in the run's status message rather than silently dropped. `searchKeywords` never touches a browser and doesn't carry this risk.
- English/USD `aliexpress.com` storefront only — no other locales in v1.
- Review **text** isn't included, only `rating`/`review_count` (see the companion AliExpress Reviews Scraper for review text).
- No historical price time-series or coupon/cart-level pricing.

### ❓ FAQ

**Do I need an AliExpress account or API key?**

No. This Actor reads the same public search and product pages a signed-out visitor sees — no login, no key.

**What does a `null` `order_count` or `shipping_cost_estimate` mean?**

It means the source page didn't expose that field for that product — we never fabricate a number. The rest of the row still ships with every field it did recover.

**Can I mix search keywords, URLs, and product IDs in one run?**

Yes — provide any combination of the three input fields. Rows are de-duplicated by `product_id` across all three modes so you're never charged twice for the same product.

**Why did my run return zero rows — is that a failure?**

Not necessarily. A search keyword that genuinely matches nothing on AliExpress **succeeds** with an empty dataset and a status message saying so — an empty result is not a failure. The run only ends non-zero (fails) when none of your inputs could be resolved at all (a genuine fetch/render problem), and the status message names exactly what didn't resolve and why.

### 💬 Your feedback

Spotted a bug, hit a weird edge case, or need a new field? Open an
issue on the Actor's **Issues** tab on Apify Console — we ship
fixes weekly and we read every report.

***

<div align="center">

Built by **[Devil Scrapes](https://apify.com/DevilScrapes)** 😈 — a small fleet of
opinionated public-data Actors. Honest pricing, real engineering, zero fine print.

</div>

# Actor input Schema

## `searchKeywords` (type: `array`):

Search terms to run against AliExpress. Each keyword returns up to <code>maxResultsPerKeyword</code> products.

## `productUrls` (type: `array`):

Direct AliExpress product-detail URLs (<code>aliexpress.com/item/{id}.html</code>). The product ID is extracted automatically.

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

Direct AliExpress numeric product IDs (8-16 digits), fetched via <code>/item/{id}.html</code>.

## `maxResultsPerKeyword` (type: `integer`):

Cap on the number of products returned per search keyword.

## `shippingDestinationCountry` (type: `string`):

ISO 3166-1 alpha-2 country code that <code>shipping\_cost\_estimate</code> is computed against.

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

Apify Proxy spec. The Actor defaults to a RESIDENTIAL proxy pinned to shippingDestinationCountry when this is left at {"useApifyProxy": true} -- AliExpress returns wrong-locale data (not an error) from a mismatched exit, and blocks datacenter IPs on the search page. Override apifyProxyGroups/apifyProxyCountry here to change it.

## Actor input object example

```json
{
  "searchKeywords": [
    "wireless earbuds"
  ],
  "productUrls": [],
  "productIds": [],
  "maxResultsPerKeyword": 20,
  "shippingDestinationCountry": "US",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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 = {
    "searchKeywords": [
        "wireless earbuds"
    ],
    "maxResultsPerKeyword": 20,
    "shippingDestinationCountry": "US",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/aliexpress-products-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 = {
    "searchKeywords": ["wireless earbuds"],
    "maxResultsPerKeyword": 20,
    "shippingDestinationCountry": "US",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/aliexpress-products-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 '{
  "searchKeywords": [
    "wireless earbuds"
  ],
  "maxResultsPerKeyword": 20,
  "shippingDestinationCountry": "US",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call devilscrapes/aliexpress-products-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,devilscrapes/aliexpress-products-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/CbAVwttRBnkHF4ZBA/builds/Ie7o0AGCqwSE8Vf79/openapi.json
