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

Extract public AliExpress product pages and direct search cards with product ID, title, price, rating, orders, store, image, and URL. Keyless direct HTTP first; optional residential fallback makes one retry only after a block.

- **URL**: https://apify.com/dami\_studio/aliexpress-products-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** E-commerce
- **Stats:** 1 total users, 0 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/platform/actors/running/actors-in-store#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 Products Scraper

Search AliExpress and get structured product rows back: product ID, title, current price, the price
it was before the discount, discount percentage, star rating, order count, image and product URL.

No AliExpress account, no API key, no browser, no proxy of your own. Type a search term, get rows.

### Price

**$0.12 per 1,000 products**, plus $0.001 to start a run.

That is the lowest price for AliExpress product data on Apify. The next cheapest charges $0.14 per
1,000 with a $0.005 start fee; after that the field jumps to $0.90, and the two most-installed
AliExpress scrapers charge $1.50 and $2.00 per 1,000.

You are charged per product row returned. A run that finds nothing costs only the start fee, and
sample and diagnostic rows are never charged.

| Products | Cost |
|---|---|
| 500 | $0.06 |
| 1,000 | $0.12 |
| 10,000 | $1.20 |
| 100,000 | $12.00 |

### Prices come back in one currency

AliExpress decides display currency from wherever the request came from. Left alone, a scraper that
rotates through proxies returns some rows in USD, some in CAD, some in EUR — with nothing in the row
saying which, unless you check every one. This happened during development: identical searches came
back in CAD and USD depending on the exit address.

This Actor pins currency and ship-to country for every request, so `price` means one thing across the
whole dataset. Set `currency` to USD, EUR, GBP, CAD, AUD, BRL, RUB, JPY, KRW or INR. Verified on a
real run: 150 rows requested in EUR came back 150/150 in EUR.

### What a row looks like

```json
{
  "productId": "1005010018401645",
  "title": "Leather Phone Case For iPhone 17 Pro Max 16 18 Pro Max 13 11 15 14 Plus 12 Shockproof Soft TPU Funda Cover",
  "productUrl": "https://www.aliexpress.com/item/1005010018401645.html",
  "price": 1.39,
  "originalPrice": 2.96,
  "discountPercent": 53,
  "currency": "EUR",
  "rating": 4.6,
  "orders": 18096,
  "ordersText": "10,000+ sold",
  "imageUrl": "https://ae-pic-a1.aliexpress-media.com/kf/Sc2976671fe8c4f6b83e3de29cab49c3fH.jpg",
  "isChoice": true,
  "isAd": false,
  "searchKeyword": "phone case",
  "page": 1,
  "position": 7,
  "scrapedAt": "2026-08-09T07:02:11.031Z"
}
```

`orders` is the exact number AliExpress tracks internally. `ordersText` is the rounded badge shown on
the page — "10,000+ sold" for the same product above. Both are included because the badge is what a
buyer sees and the number is what you can sort on.

#### Field coverage

Measured over a real 150-row run:

| Field | Present |
|---|---|
| `productId`, `title`, `productUrl`, `price`, `currency`, `imageUrl` | 100% |
| `orders`, `ordersText` | 99% |
| `rating` | 97% |
| `discountPercent` | 39% |
| `originalPrice` | 29% |

`originalPrice` and `discountPercent` are only present where the seller is actually running a
markdown. Most listings are sold at one price, and those rows get `null` rather than a copy of the
current price dressed up as a discount.

### Input

| Field | What it does |
|---|---|
| `searchQueries` | What to search for. One row per product found. |
| `productUrls` | Or paste AliExpress search URLs — the keyword is read out of the URL. |
| `maxItems` | Total products across all terms. Default 40, ceiling 5,000. |
| `currency` | Currency every price is returned in. Default USD. |
| `country` | Two-letter ship-to country used for pricing. Default US. |
| `requestDelayMs` | Gap between page requests. Default 800. |

```json
{
  "searchQueries": ["phone case", "wireless earbuds"],
  "maxItems": 1000,
  "currency": "USD",
  "country": "US"
}
```

Run it with no input and you get one labelled sample row, uncharged, so you can see the shape before
spending anything.

### Limits

Read this part before you build on it.

- **No sorting.** AliExpress's mobile listings serve one order — its own relevance ranking. The
  desktop sort parameters were tested against it and do nothing: `sort=price_asc` returned results
  identical to the default, and `sortType=...` returned a page with no results at all. Rather than
  expose a dropdown that silently changes nothing, there isn't one. Sort the dataset yourself.
- **About 20–25% of rows are paid placements.** They are real listings and are marked `isAd: true`,
  so you can filter them.
- **No seller or store fields.** AliExpress removed store name, seller ID and seller country from its
  search cards. Nothing in the response carries them, so no store column is returned rather than one
  that is always empty.
- **No review text or shipping cost.** Both live on the product page, which this does not open.
- **`orders` is lifetime**, not recent — it is the cumulative count AliExpress reports.
- **20 products per page**, so a 1,000-product run is 50 requests.
- **Results reshuffle between pages.** Products are de-duplicated by ID as they are collected, so
  `maxItems` means unique products.

### FAQ

**Do I need an AliExpress account or API key?**
No. Everything it reads is public.

**Do I need residential proxies?**
No, and it deliberately does not offer them. See "How it works".

**How fast is it?**
1,000 products in 139 seconds on the default settings.

**What does it cost to scrape 1,000 AliExpress products?**
$0.12, plus the $0.001 start fee.

**How deep can it go on one search term?**
Page 60 was still serving a full 20 results in testing, with no ceiling found. Depth is limited by
`maxItems`, not by the site.

**Can I get prices in my own currency?**
Yes — set `currency` and `country`. Every row in the run comes back in that currency.

**Is `isChoice` the same as the AliExpress Choice badge?**
Yes, it flags listings in the Choice programme.

**Can I export to CSV or Excel?**
Yes — Apify exports the dataset as JSON, CSV, Excel or XML, with a REST endpoint for the same data.

**Is this affiliated with AliExpress or Alibaba?**
No. It reads public listing data. Check AliExpress's terms and your own local rules before using the
output commercially.

### How it works

`www.aliexpress.com` is behind Alibaba's punish gate. It serves results for a while — roughly twenty
requests during testing — and then refuses every exit address and keeps refusing. Measured after
that point: Apify datacenter 0 of 10, rented static-ISP addresses 0 of 3, and an ordinary home
connection, all returning the same 2 KB challenge script. Switching TLS fingerprints did not help.
This is why AliExpress scrapers usually cost what they cost: they answer it with headless browsers
and residential bandwidth, and bill that through.

`m.aliexpress.com` is a different gate. On the very same address that `www` had just refused, the
mobile host returned a full 290 KB result page, and plain datacenter addresses then served pages 1
through 60 without a single refusal. It also server-renders its results into the HTML, so there is
one request per 20 products and no API to reverse-engineer.

No browser, no residential bandwidth, no Chinese IP. That is the whole reason this can be the
cheapest AliExpress scraper on the platform and still make money.

# Actor input Schema

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

What to search AliExpress for. One row is returned per product found.

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

Or paste AliExpress search URLs instead of typing terms — the keyword is read out of the URL.

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

Total products across all search terms.

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

Currency prices are returned in. AliExpress decides this from the exit address unless it is pinned, so leaving it set keeps every row in one currency.

## `country` (type: `string`):

Country used for pricing and availability, as a two-letter code.

## `requestDelayMs` (type: `integer`):

Gap between page requests. Raise it if runs start hitting rate limits.

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

Leave empty to use rotating Apify datacenter addresses, which is what this Actor is tuned for. Supply your own only if you have a reason to.

## Actor input object example

```json
{
  "searchQueries": [
    "phone case"
  ],
  "maxItems": 40,
  "currency": "USD",
  "country": "US",
  "requestDelayMs": 800,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Results in the default dataset. Only genuine product rows with ok: true are billable.

# 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": [
        "phone case"
    ],
    "maxItems": 40,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/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 = {
    "searchQueries": ["phone case"],
    "maxItems": 40,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/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 '{
  "searchQueries": [
    "phone case"
  ],
  "maxItems": 40,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call dami_studio/aliexpress-products-scraper --silent --output-dataset

```

## MCP server setup

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