# AliExpress Scraper (`juanoox/aliexpress-scraper`) Actor

Scrape AliExpress search results: product title, sale price, original price, discount, star rating, units sold and images, from any search term, with pagination.

- **URL**: https://apify.com/juanoox/aliexpress-scraper.md
- **Developed by:** [Juan ignacio Veltri](https://apify.com/juanoox) (community)
- **Categories:** E-commerce, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

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

## AliExpress Scraper — search results with price, discount, rating and units sold

Scrape AliExpress search results: product title, sale price, original price, discount percentage,
star rating, **units sold** and images — 60 products per page, with pagination.

### Why this one keeps working

Every guide on scraping AliExpress tells you to read `window.runParams`. **That object no longer
exists** on the current site, which is why a lot of copied-from-a-tutorial scrapers quietly return
nothing.

This Actor reads `window._dida_config_._init_data_`, the state AliExpress's own front end renders
from. No CSS selectors are involved, so a redesign does not break it.

***

### Quick start

```json
{ "searchTerms": ["headphones"] }
```

Find what actually sells, not just what is listed:

```json
{
  "searchTerms": ["phone case", "screen protector"],
  "minSold": 100,
  "minRating": "4.5",
  "maxPagesPerSearch": 10
}
```

`minSold` is the most useful filter here. AliExpress lists an enormous number of products that have
never sold a unit; requiring a sales history is the fastest way to a list worth reading.

Discount hunting:

```json
{ "searchTerms": ["mechanical keyboard"], "onlyDiscounted": true, "maxPrice": "40" }
```

***

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `searchTerms` | array | `["headphones"]` | What to search for |
| `startUrls` | array | — | Result pages you already filtered on the site |
| `maxPagesPerSearch` | integer | `3` | 60 products per page |
| `minPrice` / `maxPrice` | string | — | Sale price range, e.g. `5`, `49.99` |
| `minRating` | string | — | Star rating floor, e.g. `4.5` |
| `minSold` | integer | — | Minimum units sold |
| `onlyDiscounted` | boolean | `false` | Only products genuinely below list price |
| `keywords` | array | — | Only titles mentioning any of these |
| `maxItems` | integer | `300` | Total cap. `0` = no cap |
| `includeSeen` | boolean | `true` | Off = only products not seen in previous runs |

***

### Output

```json
{
  "id": "aliexpress:3256812596783345",
  "url": "https://www.aliexpress.com/item/3256812596783345.html",
  "title": "Wireless Over-Ear Headphones, 5.3 Smart Chip, HiFi Music Gaming",
  "price": { "amount": 0.99, "currency": "USD", "raw": "US $0.99" },
  "listPrice": { "amount": 21.72, "currency": "USD", "raw": "US $21.72" },
  "discountPercent": 95,
  "rating": 5,
  "soldQuantity": 51,
  "condition": "new",
  "images": ["https://ae-pic-a1.aliexpress-media.com/kf/Sfa03eb...jpg"],
  "sku": "3256812596783345",
  "seller": null,
  "reviewsCount": null
}
```

Three deliberate choices:

- **`listPrice` is only set when there is a real discount.** With no offer running, AliExpress
  repeats the same number in both price fields; copying it would show a discount that does not
  exist.
- **`soldQuantity` is a number.** The site publishes `"51 sold"` as text, and you cannot sort or
  filter a string by sales volume.
- **Products with no price are not returned at all.** The results page mixes in promoted cards that
  carry no price in the page state; a product row you cannot compare, sort or filter by price is not
  a result, and you are not charged for it. On a real run that was 17% of the raw cards.
- **`seller`, `reviewsCount` and `stockQuantity` are `null`.** They live on the product page, which
  is a separate request per product — a search results page simply does not carry them. That is
  information, not a gap.

***

### Notes and limits

- **AliExpress rate-limits hard.** From an ordinary connection the first request succeeds and the
  second comes back as a 2 KB challenge page. This Actor runs behind Apify's unblocking proxy, so
  you do not have to configure anything — but it is why runs are slower than a plain HTTP scraper,
  and why raising `maxRequestsPerMinute` a lot is how runs start failing.
- **Prices are in the market's currency**, which depends on the country the request is made from.
  Runs are pinned to the US market so a dataset stays comparable across runs.
- Products with no price are dropped by `minPrice`/`maxPrice`, because claiming they fall in a range
  they never published would misreport the filter you asked for.

***

### Pricing

Pay per result. You are charged for products that actually land in your dataset — filtered out and
duplicate rows cost nothing.

# Actor input Schema

## `searchTerms` (type: `array`):

What to search for, e.g. headphones, usb c cable. Each term is searched separately.

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

Paste AliExpress result pages you already filtered on the site. Use this instead of search terms to keep their exact filters.

## `maxPagesPerSearch` (type: `integer`):

Each page holds 60 products.

## `minPrice` (type: `string`):

Sale price floor, e.g. 5 or 9.99. Products with no price are dropped, since it cannot be claimed they fall in range.

## `maxPrice` (type: `string`):

Sale price ceiling, e.g. 50.

## `minRating` (type: `string`):

Star rating floor, e.g. 4 or 4.5.

## `minSold` (type: `integer`):

Only products with at least this many units sold. The fastest way to separate what actually sells from what is merely listed.

## `onlyDiscounted` (type: `boolean`):

Only products whose sale price is genuinely below their list price.

## `keywords` (type: `array`):

Only products whose title mentions any of these. Ignores case and accents.

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

Total cap for the run. 0 = no cap.

## `includeSeen` (type: `boolean`):

Turn it off to skip products returned by previous runs.

## `maxConcurrency` (type: `integer`):

Parallel requests.

## `maxRequestsPerMinute` (type: `integer`):

Rate ceiling.

## `maxRequestRetries` (type: `integer`):

How many times to retry a failed request before dropping it.

## Actor input object example

```json
{
  "searchTerms": [
    "headphones"
  ],
  "maxPagesPerSearch": 3,
  "onlyDiscounted": false,
  "maxItems": 300,
  "includeSeen": true,
  "maxConcurrency": 3,
  "maxRequestsPerMinute": 30,
  "maxRequestRetries": 3
}
```

# Actor output Schema

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

No description

## `runSummary` (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 = {
    "searchTerms": [
        "headphones"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("juanoox/aliexpress-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 = { "searchTerms": ["headphones"] }

# Run the Actor and wait for it to finish
run = client.actor("juanoox/aliexpress-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 '{
  "searchTerms": [
    "headphones"
  ]
}' |
apify call juanoox/aliexpress-scraper --silent --output-dataset

```

## MCP server setup

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