# AliExpress Search API & Scraper (`sourcing-data-studio/aliexpress-search-api`) Actor

AliExpress scraper and search API: enter keywords and get one clean row per search result with price, discount, currency, rating, sold count, image and item link. No login; pay only for saved results. Unofficial: not affiliated with or endorsed by AliExpress or Alibaba Group.

- **URL**: https://apify.com/sourcing-data-studio/aliexpress-search-api.md
- **Developed by:** [Sourcing Data Studio](https://apify.com/sourcing-data-studio) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 product results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

Find what a product sells for on AliExpress before you source it. AliExpress Search API & Scraper runs your keywords on aliexpress.com and returns one clean row per result: price as shown, one-time new-user deals flagged in `priceType`, discount, rating, sold count, image and link. Use it for product research, price comparison sheets and AI agents. You pay only for results saved to your dataset: $0.003 per product on the Free tier, so a typical query (one keyword, first page of about 60 results) costs $0.18.

Unofficial: not affiliated with or endorsed by AliExpress or Alibaba Group.

Source: public search result pages of aliexpress.com (https://www.aliexpress.com), read without logging in.

Importers and online sellers use this AliExpress scraper to compare retail prices of goods from China and to find products worth testing. As an AliExpress search scraper it does one job: it runs an AliExpress product search for each keyword and returns every result as a clean row, optionally sorted by orders or by price, inside a price range, or limited to results with a minimum rating or sold count. It works as an AliExpress price API for an AliExpress price comparison sheet, and as a feed of AliExpress product data for your own tools. Read "Which price do I get?" below before you compare prices: AliExpress shows a first-time visitor many one-time deals, and the Actor says in `priceType` which rows carry one.

### What does AliExpress Search API & Scraper do?

- Runs an AliExpress keyword search for every term you enter and reads the public result pages.
- Returns one row per result: item id, title, price, price type, new-user deal price, original price, discount, currency, rating, sold text, sold count, image and item link.
- Gives `price` as the result shows it, and says in `priceType` and `isNewUserPrice` whether that price is a one-time new-user deal, a regular price or not known. The crossed-out price stays in `originalPrice`, also next to a deal.
- Follows the result pages of each term (about 60 results per page) until your **Maximum results** limit is reached.
- Sorts the results when you set **Sort order**: most orders first, lowest price first or highest price first. AliExpress does the sorting, and it sorts inside each result page: every page comes in that order and the next page starts again. The rows of several pages are therefore not one sorted list; sort them yourself by `salesCount` or `price`. Without a sort order the results come in the default order of AliExpress.
- Limits the results to a price range when you set **Minimum price** and **Maximum price**. AliExpress applies the range, in the currency it shows for the request, which the Actor cannot choose.
- Keeps only results with a **Minimum rating** and a **Minimum sold count** when you set them. The Actor checks the rows it has read: a row whose rating (or sold count) is missing or below the minimum is not saved and not charged.
- Limits the paging of a search term while a minimum rating or sold count is set, because a page that holds only rows left out is loaded but brings nothing to save: the term stops after 3 result pages in a row that add no saved row, or after 20 pages, whichever comes first.
- Records the currency the page showed on every row as an ISO code. Prices are never converted or rounded.
- Saves each item once per run, even when several terms find it, and rejects results without a readable price or currency.
- Charges one event per saved result. Blocked pages, duplicates, incomplete results and results left out by a minimum rating or sold count are never charged.
- Writes a run summary with totals, the status of every search term (with the rows read, the rows left out by a minimum and, where a minimum ended the term, why), blocked or failed pages and your feedback to the key-value store.
- Reads the pages with a plain, unmodified browser that says what it is. The run summary shows under `browser` what the browser reported about itself: its user agent, and that software controls it.
- Works from Apify Console, the Apify API, n8n, Make and AI agents through the Apify MCP server.

### Output example

These rows come from a real run.

```json
[
  {
    "productId": "3256813145859984",
    "title": "2D Flat Soft Silicone Phone Case For iPhone 17 Pro Max 16 18 Pro 13 11 15 14 Plus 12 17 16E 17Promax Shockproof Transparent Funda Cover",
    "price": 2.46,
    "originalPrice": 14.42,
    "discountPercent": 83,
    "newUserPrice": null,
    "isNewUserPrice": false,
    "priceType": "regular",
    "currency": "USD",
    "rating": null,
    "reviewCount": null,
    "salesSignal": "1 sold",
    "salesCount": 1,
    "imageUrl": "https://ae-pic-a1.aliexpress-media.com/kf/S4110e6e4621d4ff882e82e8ea318c6612.jpg",
    "productUrl": "https://www.aliexpress.com/item/3256813145859984.html",
    "source": "aliexpress.com",
    "region": null,
    "searchQuery": "phone case",
    "position": 4,
    "retrievedAt": "2026-10-07T03:20:39.894Z"
  },
  {
    "productId": "3256811990811737",
    "title": "Transparent Original Magnetic Phone Case for iPhone 17 16 15 14 Plus 13 12 mini 11 Pro XS Max XR for Magsafe Acrylic Clear Cover",
    "price": 1.09,
    "originalPrice": 11.92,
    "discountPercent": 90,
    "newUserPrice": 1.09,
    "isNewUserPrice": true,
    "priceType": "new_user_deal",
    "currency": "USD",
    "rating": 4.9,
    "reviewCount": null,
    "salesSignal": "1,000+ sold",
    "salesCount": 1156,
    "imageUrl": "https://ae-pic-a1.aliexpress-media.com/kf/Sb92b8f6e6fe94093a6f3989ba70457f24.jpg",
    "productUrl": "https://www.aliexpress.com/item/3256811990811737.html",
    "source": "aliexpress.com",
    "region": null,
    "searchQuery": "phone case",
    "position": 6,
    "retrievedAt": "2026-10-07T03:20:39.894Z"
  },
  {
    "productId": "3256806723190144",
    "title": "Flower Phone Case For iPhone 17 18 Pro Max 16 13 14 12 11 15 Pro Max 16e Air 7 Plus SE Shockproof Transparent Cover Soft Funda",
    "price": 1.09,
    "originalPrice": 3.82,
    "discountPercent": 71,
    "newUserPrice": 1.09,
    "isNewUserPrice": true,
    "priceType": "new_user_deal",
    "currency": "USD",
    "rating": 4.6,
    "reviewCount": null,
    "salesSignal": "10,000+ sold",
    "salesCount": 23286,
    "imageUrl": "https://ae-pic-a1.aliexpress-media.com/kf/S2a0aa764b3384451adc3adea18f6c071L.jpg",
    "productUrl": "https://www.aliexpress.com/item/3256806723190144.html",
    "source": "aliexpress.com",
    "region": null,
    "searchQuery": "phone case",
    "position": 7,
    "retrievedAt": "2026-10-07T03:20:39.894Z"
  }
]
```

This sample comes from a run on the Apify platform through the default Apify Proxy, so the titles are in English and the prices in USD. From another address AliExpress answers in that country's language and currency: the same search from Bahrain returned Arabic titles and BHD prices.

### What data can you get with AliExpress Search API & Scraper?

| Field | Type | Description |
|---|---|---|
| `productId` | string | AliExpress item id (digits only), the same number as in the item page address. |
| `title` | string | Product title as shown in the search result, in the language the page was served in. |
| `price` | number | Price of the result as the result shows it to a first-time, logged-out visitor, in major units of the currency in the currency field, with the decimals the page shows. Never converted. When the result shows a one-time new-user deal, this is the deal price (see priceType) and the crossed-out price next to it is in originalPrice. |
| `originalPrice` | number | Crossed-out price shown next to the price, in the same currency. Null when the result shows none, when it is not higher than the price, or when it is in another currency. Next to a new-user deal it is the list price the deal is compared with. |
| `discountPercent` | integer | Discount in percent as shown on the result, or computed from price and originalPrice when the page gives no figure. Null when the result shows no discount. |
| `newUserPrice` | number | One-time price for first-time buyers (AliExpress welcome deal or new-user allowance), in the same currency, when the result is marked with one. It is the same amount as price on such a row. Null when the result carries no such mark; short result cards never carry one. |
| `isNewUserPrice` | boolean | True when the result shows a one-time new-user deal, so that price is the deal price. False otherwise, also on short result cards, where this cannot be told (see priceType). |
| `priceType` | string | What kind of price price is. new_user_deal: the result is marked as a one-time deal for new users and price is the deal price. regular: the result carries its campaign information and none of it is a new-user deal. unknown: the result carries no such information (short result cards), so it cannot be told whether price is a deal. |
| `currency` | string | ISO 4217 code of the currency the page showed (for example USD, EUR, BHD). AliExpress picks it from the address the request comes from, so it follows the proxy. |
| `rating` | number | Average star rating from 0 to 5 with one decimal. Null when the result shows no rating. |
| `reviewCount` | integer | Number of reviews. Always null today: AliExpress search pages do not show a review count. |
| `salesSignal` | string | Sold text exactly as shown on the result, in the page language, for example 5,000+ sold. Null when the result shows none. |
| `salesCount` | integer | Units sold as a number: the exact count carried in the page data of the result, which can be present when no sold text is displayed. Without an exact count, the lower bound of the sold text when it can be read with certainty (10K+ sold gives 10000). Null otherwise. |
| `imageUrl` | string | URL of the main product image. |
| `productUrl` | string | Item page address in the form https://www.aliexpress.com/item/<productId>.html, without tracking parameters. |
| `source` | string | Source site domain, always aliexpress.com. |
| `region` | string | Always null: AliExpress search has no regional storefront in the address. Use the currency field to see which market the page was served for. |
| `searchQuery` | string | The search term from the input that found this result. |
| `position` | integer | 1-based display position of the result within its search term, counted across pages. Sponsored results are counted in display order. |
| `retrievedAt` | string | ISO 8601 UTC time when the search page was read. |

Some notes on the fields:

- `currency` and the language of `title` and `salesSignal` follow the address the request comes from. Every row states its currency.
- `rating`, `salesSignal`, `salesCount`, `originalPrice`, `discountPercent` and `newUserPrice` exist only on full result cards. AliExpress also serves a shorter card that has only the title, the image and one price, and these fields are null there and `priceType` is `unknown`. Which form a page gets changes: in our earlier tests full cards came only among the first 30 to 60 results of a term, and in platform runs on 2026-10-09 the first three pages (180 results) were all full cards. See "Limits".
- `salesCount` is the exact count the page carries for the result. A few results carry a count although they display no sold text, so `salesCount` can be filled while `salesSignal` is null.
- `reviewCount` is always null, because the search page does not show it. `region` is always null.
- Sponsored results are included in display order and are not marked.
- To look for AliExpress best sellers for a keyword, set **Sort order** to Most orders first, read several result pages (for example **Maximum results** 300) and sort the rows by `salesCount`, the AliExpress sold count. One page is not enough: AliExpress sorts inside each page, and in our test of 300 rows only 36 of the 60 highest sold counts were on the first page. Results that AliExpress shows as free-gift offers without a price are not saved, so some top sellers of a term can be missing (see "Limits").

#### Which price do I get?

`price` is the price the result shows, in the currency of the `currency` field. The Actor visits AliExpress the way a first-time visitor without an account does. To such a visitor AliExpress shows many one-time prices for new users ("welcome deals"). On the first result page of our test searches, 23 of 33 priced results (through a United States address) and 48 of 55 (from Bahrain) were marked that way, and many of them showed the same low price. `priceType` says what kind of price you got:

- `new_user_deal`: the result is marked as a new-user deal, and `price` is the deal price. `newUserPrice` repeats it and `isNewUserPrice` is true. When the result also shows a crossed-out price, it is in `originalPrice`: the list price AliExpress compares the deal with ("New shoppers save $2.05"). It can be well above what the item sells for: a returning customer may pay less, and the result does not show that amount. Filter these rows out if you do not want deal prices in a comparison.
- `regular`: the result carries its campaign information and none of it is a new-user deal. `price` is the price shown, with `originalPrice` and `discountPercent` when the result shows them.
- `unknown`: the result carries no campaign information, so the Actor cannot tell whether its price is a deal; `newUserPrice` is null and `isNewUserPrice` is false there. That is the case for short result cards, and we have also seen it on a full card. In our tests the same item always had a different price in a short card than in a full one. One item showed 0.96 BHD in a short card and, a minute later in a full card, a deal price of 0.43 BHD next to a crossed-out 3.89 BHD.

Compare prices only between rows of the same run that have the same `priceType`. Between two runs the price of the same item often differs: see "Why does the same item have different prices in two runs?" below. Prices are in major units with the decimals the page shows: two for most currencies, three where the page shows three.

### How to use AliExpress Search API & Scraper

1. Click **Try for free** on this page.
2. Enter one or more **Search terms**, one per line, as you would type them in the AliExpress search box.
3. Set **Maximum results**. It counts across all terms together, and the run stops as soon as that many rows are saved.
4. Optional: in the **Sort order and filters** section, choose a **Sort order**, set a **Minimum price** and a **Maximum price**, or set a **Minimum rating** or a **Minimum sold count**. Left as they are, the results come in the default order of AliExpress, with no price range and no minimum.
5. Click **Start**. Results appear in the **Output** tab while the run is going.
6. Download the results as JSON, CSV or Excel, or read them through the API.

The currency is chosen by AliExpress from the address the request comes from. With the default Apify Proxy our test runs returned USD or EUR prices. Check the `currency` field and keep only the rows with the currency you need; do not add up prices of different currencies. A price range is read in that currency too. The language of the titles and the item ids follow that address as well: on 2026-10-09 one run returned English titles, USD prices and item ids starting with 3256, and a run of the same search fifteen minutes later returned German titles, EUR prices and item ids starting with 1005, with no item id in common between the two. Setting a country in **Proxy configuration** did not change this in our test, so the Actor cannot promise the same language, currency or item ids from run to run.

#### Sort order, price range and minimums

All five inputs are optional. With none of them set, the Actor asks for the same search pages and saves the same rows as without them.

- **Sort order** (`sort`): `relevance` (the default, the order AliExpress uses), `orders` (most orders first), `priceAsc` (lowest price first) or `priceDesc` (highest price first). AliExpress does the sorting: the Actor adds the order to the address of the search page it reads. AliExpress applies the order inside each result page (about 60 results) and starts again on the next page. In platform test runs on 2026-10-09, 300 rows for "yoga mat" with `orders` came from 7 pages, each page in falling order of `salesCount` and each beginning again above where the page before ended (the pages began at 12,665, 9,086, 6,366, 5,974, 3,707, 330 and 496); of the 60 highest sold counts among the 300 rows, 36 were on the first page. With `priceAsc` and `priceDesc` the pages behaved the same way (150 rows each: in order inside a page, starting again on the next). So for a ranking, read several pages and sort the rows yourself. The price shown is the new-user deal price where the result shows one: in a test with `priceAsc` and a price range from 1 to 10, all 60 rows carried such a price, so read `priceType` and `originalPrice` before you call a row the cheapest.
- **Minimum price** and **Maximum price** (`minPrice`, `maxPrice`): numbers of 0 or more. **Maximum price** must be at least **Minimum price** when both are set. Leave one empty (or 0) for no limit on that side. AliExpress applies the range, in the currency it shows for the request, which the Actor cannot choose: check the `currency` field. In platform test runs on 2026-10-09 (prices in USD), a range from 2 to 5 for "led strip lights" returned 60 rows, all priced from 2.03 to 4.88. AliExpress applies the range to the price it shows, new-user deal prices included (22 of the 60 rows); the crossed-out price (`originalPrice`) can lie outside the range. With **Sort order** set to `priceAsc` as well, a range from 1 to 10 gave rows in rising order from 1.09. In a test from Bahrain the range was read in BHD. The Actor does not check the prices of the rows against the range.
- **Minimum rating** (`minRating`, 0 to 5) and **Minimum sold count** (`minSoldCount`, a whole number): the Actor applies them to the rows it has read. A row passes only if its `rating` (and its `salesCount`) is there and at least the minimum; with both set, a row must pass both. A row that does not pass is not saved and not charged. A missing value does not pass: a product without reviews shows no rating, and the rows of a short result card, which has no rating and no sold count, never pass a minimum. In a platform test run on 2026-10-09 ("yoga mat thick", most orders first, minimum rating 4.5, minimum sold count 100) the Actor read 658 rows on 11 pages, saved 47 and left out 611. Leave a minimum empty (or 0) to switch it off.
- While a minimum rating or sold count is set, a search term stops after 3 result pages in a row that add no saved row, or after 20 pages, whichever comes first. Pages are loaded one by one, about 10 seconds apart, whether or not they hold rows you keep.
- The run summary (key-value store record `RUN_SUMMARY`) echoes the five inputs under `input`. Under `listings`, each search term shows `rowsRead` (the readable rows that were not saved before in this run: the rows the minimums were applied to), `leftOutByFilters` (how many of them a minimum left out) and, where a minimum ended the term, `stoppedBy`: `no-saved-row-in-3-pages` or `page-limit-20`.

### Input examples

#### Quick test

```json
{
  "searchQueries": [
    "phone case"
  ],
  "maxItems": 10
}
```

#### Cheapest in a price range

```json
{
  "searchQueries": [
    "usb c cable",
    "led strip lights",
    "wireless earbuds"
  ],
  "maxItems": 180,
  "sort": "priceAsc",
  "minPrice": 1,
  "maxPrice": 10
}
```

#### Best sellers with good ratings

```json
{
  "searchQueries": [
    "yoga mat thick",
    "yoga mat cork",
    "travel yoga mat",
    "resistance bands set",
    "fabric resistance bands"
  ],
  "maxItems": 300,
  "sort": "orders",
  "minRating": 4.5,
  "minSoldCount": 100,
  "maxRequestRetries": 5
}
```

### How much does AliExpress Search API & Scraper cost?

| Event | You pay for | Free | Bronze | Silver | Gold |
|---|---|---|---|---|---|
| Product result | One AliExpress search result saved to the dataset. Blocked pages, duplicates and incomplete rows are never charged. | $0.003 | $0.003 | $0.0027 | $0.0024 |

Prices are per event. Your tier follows your Apify subscription plan.

On the Free tier, $0.003 per product means:

- 100 products cost $0.30.
- 1,000 products cost $3.00.
- A typical query (one keyword, first page of about 60 results) is 60 products and costs $0.18.

Apify also charges a tiny start fee per run (apify-actor-start, $0.00005 per GB of memory). Blocked pages, duplicates, incomplete results and results left out by a minimum rating or sold count are never charged. To cap your spending, set **Maximum cost per run** in the run options; the run stops cleanly when that budget is used.

### Use AliExpress Search API & Scraper from the API, n8n, Make or an AI agent

#### Apify API

Use it as an AliExpress API from any programming language. Run the Actor and get the search results in one call:

**curl**

```bash
curl -X POST "https://api.apify.com/v2/acts/sourcing-data-studio~aliexpress-search-api/run-sync-get-dataset-items" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchQueries":["phone case"],"maxItems":10}'
```

**JavaScript** (Node.js, `npm install apify-client`)

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const input = {
    "searchQueries": [
        "phone case"
    ],
    "maxItems": 10
};

const run = await client.actor('sourcing-data-studio/aliexpress-search-api').call(input);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**Python** (`pip install apify-client`)

```python
import os

from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])

run_input = {
    "searchQueries": [
        "phone case"
    ],
    "maxItems": 10
}

run = client.actor("sourcing-data-studio/aliexpress-search-api").call(run_input=run_input)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

The synchronous call waits up to 300 seconds. The Actor loads one page about every 10 seconds, so for more than a few hundred results start the run with the normal run endpoint and read the dataset when it has finished.

#### n8n and Make

Use an HTTP request module with the same URL, method POST and a JSON body like the input examples above. Store your Apify API token as a credential, never in the workflow itself.

#### AI agents through the Apify MCP server

Connect your agent to the Apify MCP server and call `sourcing-data-studio/aliexpress-search-api` with the same input: an array of plain keywords in `searchQueries` and a number in `maxItems`. Agents can use the **Feedback for the developer** field to report missing fields or problems.

### For AI agents

- Minimal input: `{"searchQueries": ["phone case"], "maxItems": 10}`. At the Free tier price, 10 rows cost $0.03 plus the platform's start fee.
- Read these fields first: `price` with `currency`, `priceType`, `salesCount` and `productUrl`. Compare prices only between rows of one run with the same `priceType`. Prices, the currency, the language of the titles and the item ids can differ from run to run, so do not join two runs on `productId` or compare their prices item by item.
- Outcomes are in the run status message and in the `RUN_SUMMARY` record of the run's key-value store. Its `listings` object gives one status per search term (`ok`, `no-match`, `blocked`, `failed` or `stopped`) with the number of `retries`, and `failures` lists the pages that failed or were blocked. Nothing is charged for such a page.
- Optional inputs: `sort` (`relevance`, `orders`, `priceAsc`, `priceDesc`), `minPrice` and `maxPrice` (in the currency the rows show), `minRating` (0 to 5) and `minSoldCount`. A row whose rating (or sold count) is missing does not pass the minimum for it, and rows left out are not charged.
- Do not use it when you need item details such as shipping cost, stock, variants or seller data, because it reads search result pages only.
- It is callable through the Apify MCP server as the tool `sourcing-data-studio/aliexpress-search-api` and through the Apify API.

### Limits

- At most 20 search terms and 1,000 results per run. For more, run the Actor several times with different terms.
- Results are not the same from run to run. The language, the currency and the item ids follow the country AliExpress sees for the run, which the Actor does not choose, and prices change from visit to visit (see the FAQ). Use one run for one comparison.
- A sort order holds inside one result page only (see "Sort order, price range and minimums"). With most orders first, many results also come again on later pages and are skipped as duplicates: 87 of 420 in our test.
- The Actor reads at most 60 result pages per term, about 60 results each. While a minimum rating or sold count is set, it reads at most 20 pages per term, and a term stops earlier after 3 pages in a row that add no saved row.
- With a price range, AliExpress can return fewer results per page. In a test from Bahrain (prices in BHD) the first three pages of a narrow range (1 to 2) held 4, 9 and 8 results, and the first page of a wider range (1 to 10) held 25, instead of about 60; in platform tests (prices in USD) the first page of a range held 60. A high **Maximum results** can then take more pages, and more time at one page every 10 seconds.
- Rating, sold text, sold count, original price, discount and the new-user mark come only with full result cards, and AliExpress decides on every page load which form it serves. In eight earlier test loads of a first page, six brought full cards, one brought 30 full and 30 short cards, and one began with short cards, and both earlier test loads of a second page brought short cards only. In platform runs on 2026-10-09 the first three pages were all full cards. Expect some runs with short cards anyway; when later pages come as short cards, use more search terms with about 60 results each instead of one term with many pages.
- Results that AliExpress offers to new users as a free gift show "free with any purchase" in place of a price. They are skipped and not charged. For the search "phone case" this was 24 to 27 of the 60 results on the first page through the Apify Proxy (United States) and 5 of 60 from Bahrain; for other search terms it was 0 to 14 of 60. Expect fewer than 60 saved rows per page. With **Sort order** set to Most orders first it was 43 of 180 results for "usb c cable" and 0 of 659 for "yoga mat thick" in our platform tests, so part of the top sellers of a term can be missing from the rows. The run summary counts them under `invalidReasons`.
- The Actor loads one page at a time, about 10 seconds apart (at most 6 pages per minute), to stay polite to the source. A run of 10 results takes under two minutes.
- Items are de-duplicated within a run, not across runs.
- Search has no "no results" page: for a term that matches nothing, AliExpress still shows a few unrelated results, and these are saved like any other result. A first result page without any result card is therefore not read as "no match": the Actor loads it again (up to **Retries per page** times) and lists the term as `failed` in the run summary if it stays empty. A term is listed as `no-match` only when the page itself reports 0 results.
- Of the sorting and filters of the AliExpress site, only the three sort orders and the price range described above are supported, and AliExpress applies them. The shipping country (there is no way to choose the country the items ship to), free shipping and the other filters of the site are not supported. Without a **Sort order**, the results come in the default order of the site.
- AliExpress may show a block or a verification page instead of results. The Actor does not try to pass it. A blocked or verification page is not asked for again in the same run: it is listed as blocked in the run summary and nothing is charged. Run the search again later to try the term again.

### FAQ

#### Is this an official AliExpress search API?

No. It is an unofficial AliExpress search API: it reads public search result pages, does not use an AliExpress account and is not affiliated with or endorsed by AliExpress or Alibaba Group.

#### Which data does AliExpress Search API & Scraper collect?

Only public search result data that anyone can see without logging in: item id, title, prices, discount, rating, sold count, image and item link.

#### Which data is NOT collected?

- No seller data: no store names, store ids or store links.
- No personal data: no names, phone numbers, email addresses or reviewer details.
- No item pages, so no descriptions, variants, shipping costs, delivery times or stock.
- No review texts and no review counts.
- Nothing behind a login. The Actor does not sign in and does not use an account.

#### In which currency are the prices?

In the currency AliExpress showed for the address the request came from. The `currency` field of every row gives the ISO code. The Actor does not convert prices. A price range (**Minimum price**, **Maximum price**) is read in that currency too.

#### Can I sort the results or set a price range?

Yes. Set **Sort order** to get the results with the most orders first, the lowest price first or the highest price first, and **Minimum price** and **Maximum price** for a price range. AliExpress applies both: the Actor adds them to the address of the search page it reads, and the range is in the currency AliExpress shows for the request. AliExpress sorts inside each result page and starts again on the next, so sort the rows yourself when you read more than one page. Other sorting and filters of the site, such as the shipping country or free shipping, are not supported.

#### How do Minimum rating and Minimum sold count work?

The Actor checks the rows it has read: a row whose rating (or sold count) is missing or below the minimum is not saved and not charged. A missing value does not pass: a product without reviews shows no rating, and AliExpress also serves a shorter result card without a rating and a sold count. While a minimum is set, a search term stops after 3 result pages in a row that add no saved row, or after 20 pages, whichever comes first. The run summary shows for each term how many rows were read (`rowsRead`), how many a minimum left out (`leftOutByFilters`) and, where a minimum ended the term, why (`stoppedBy`).

#### Why did my run with a minimum save fewer rows than Maximum results?

Usually because rows were left out or a search term stopped early. Open the run summary (record `RUN_SUMMARY` in the **Storage** tab) and look under `listings`: `leftOutByFilters` is the number of rows a minimum left out, and `stoppedBy` is `no-saved-row-in-3-pages` or `page-limit-20` where the paging limit of the minimums ended a term. You can lower the minimum, add search terms, or set **Sort order** to Most orders first: in our platform test with that order, all 120 rows saved had a rating and a sold count.

#### Why are rating and sold count empty on some rows?

AliExpress serves two forms of the result card. The shorter form has no rating, no sold text, no original price and no discount, so these fields are null. AliExpress picks the form on every page load. In our earlier tests full cards came on the first result page only; in platform runs on 2026-10-09 the first three pages were all full cards. A row of a full card can still lack a rating when the product has no reviews. With a **Minimum rating** or **Minimum sold count**, rows without the value are left out and not charged.

#### Why does the same item have different prices in two runs?

The price is what AliExpress showed this run at that moment: a new-user deal, a sale price, or another price in a short result card, and it changes from visit to visit. In two runs of the same search four minutes apart on 2026-10-09, both in USD, all 60 products were the same and 48 of them showed a different price, nearly all with the same `priceType`. So do not compare the price of an item between two runs, and inside one run compare only rows with the same `priceType`. A `new_user_deal` row shows the one-time deal for new customers; `originalPrice` is the list price next to it where the result shows one. When the two runs see different countries, the same product also has a different item id (see "Which price do I get?").

#### Why did my run return 0 results?

There are three usual causes, and the run ends as failed in all of them. Either AliExpress blocked every page (a blocked page is asked for only once), or the first result page of every term came back without result cards even after the retries, or every result on the pages that were read was rejected, for example because all of them were free-gift offers without a price. The run summary in the **Storage** tab (record `RUN_SUMMARY`) lists each blocked or failed page under `failures`, gives the status of every term under `listings` and counts the rejected results by reason under `invalidReasons`. Nothing is charged for results in any of these cases. A run ends as succeeded with no rows when the result page itself reports 0 results for every term (those terms are listed as `no-match`), or when you set a minimum rating or sold count and every readable result was left out by it (`leftOutByFilters` under `listings`).

#### Is the price the final price I would pay?

No. It is a price shown in the search result to a visitor who is not logged in. Shipping, taxes, coupons and prices of other variants are not included, and a new-user deal price applies once and only to a first order.

#### Can I schedule AliExpress Search API & Scraper?

Yes. Save your input as a task and add a schedule in Apify Console, for example a weekly look at what sells for the same terms. The price of a single item is not comparable from one run to the next (see "Why does the same item have different prices in two runs?").

### Feedback

Tell us what to add next in the **Feedback for the developer** input field, or open an issue in the **Issues** tab. Feedback is saved with the run summary.

# Changelog

This Actor's version history is a separate document: https://apify.com/sourcing-data-studio/aliexpress-search-api/changelog.md

# Actor input Schema

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

Keywords to search on AliExpress, one term per line, exactly as you would type them in the AliExpress search box (for example: phone case, usb c cable, led strip lights). Each term is searched separately and its results are followed page by page (about 60 results per page). Up to 20 terms per run, each up to 200 characters. Repeated terms are searched once. For AI agents: pass an array of plain strings; do not pass URLs, item ids or category names.

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

Maximum number of search results to save and pay for in this run, counted across all search terms together (not per term). The run stops as soon as this many rows are saved. You pay only for saved rows. An item that appears under several terms is saved once. For AI agents: use 10 for a quick test and raise it when more rows are needed; with several terms, set it to roughly 60 times the number of terms to get the first page of each.

## `sort` (type: `string`):

Order of the results. relevance (default) is the default order of AliExpress. orders puts the results with the most orders first, priceAsc the lowest price first and priceDesc the highest price first. AliExpress applies the order inside each result page (about 60 results) and starts again on the next page, so sort the rows yourself when you read more than one page. The Actor adds the order to the address of the search page it reads; paging, Maximum results and the charges work as before. Compare prices only between rows with the same priceType. Example: priceAsc. For AI agents: pass one of relevance, orders, priceAsc, priceDesc; any other value is rejected with an error and the run does not start.

## `minPrice` (type: `number`):

Lowest price to show, a number of 0 or more, for example 2.5. AliExpress applies it, in the currency it shows for the request: the Actor cannot choose that currency, because it follows the address the request comes from. Check the currency field of the rows (a test from Bahrain returned BHD, the default Apify Proxy returned USD or EUR in tests). A price range can also bring fewer results per page. Leave empty or 0 for no lower limit. Up to three decimals are used.

## `maxPrice` (type: `number`):

Highest price to show, a number of 0 or more, for example 10. It must be at least Minimum price when both are set. AliExpress applies it, in the currency it shows for the request: the Actor cannot choose that currency, because it follows the address the request comes from. Check the currency field of the rows. Leave empty or 0 for no upper limit. Up to three decimals are used.

## `minRating` (type: `number`):

Minimum star rating from 0 to 5, for example 4.5. The Actor applies it to the results it has read: a result whose rating is lower, or that shows no rating, is not saved and not charged. Many results show no rating (a product without reviews has none, and AliExpress also serves a shorter result card without one), so a minimum rating can leave out many results. Leave empty or 0 for no minimum. When a minimum rating or a minimum sold count is set, a search term stops after 3 result pages in a row that add no saved result, or after 20 pages, whichever comes first; the run summary says which (stoppedBy).

## `minSoldCount` (type: `integer`):

Minimum number of items sold, a whole number of 0 or more, for example 100. The Actor applies it to the salesCount of the results it has read: a result whose sold count is lower, or that shows none, is not saved and not charged. Some results show no sold count (AliExpress also serves a shorter result card without one). Leave empty or 0 for no minimum. The same stop rule as for Minimum rating applies: a search term stops after 3 result pages in a row that add no saved result, or after 20 pages, whichever comes first.

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

Proxy servers used to load the search pages. Keep the default (Apify Proxy, automatic) unless you know you need something else. AliExpress picks the currency and the language from the address the request comes from, so the proxy decides both; every row states its currency in the currency field. In test runs the default proxy returned USD or EUR prices and English text.

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

How many times a failed search page (a server error, a timeout, a first result page without result cards) is loaded again, waiting longer each time. A page that AliExpress answers with a block or a verification page is not asked for again in the same run: it is listed as blocked in the run summary (key-value store record RUN_SUMMARY) and nothing is charged. Pages that still fail after the retries are listed there too and are never charged. The default of 3 fits almost every run.

## `debugLog` (type: `boolean`):

Print detailed debug messages to the run log. Leave off unless you are investigating a problem; it does not change the results.

## `feedback` (type: `string`):

Optional. Tell us which field, filter or country you need next, or what went wrong. It is saved with the run summary and does not change the results. Do not include personal data. AI agents may also use this field to report problems.

## Actor input object example

```json
{
  "searchQueries": [
    "phone case"
  ],
  "maxItems": 10,
  "sort": "relevance",
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxRequestRetries": 3,
  "debugLog": false
}
```

# Actor output Schema

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

No description

## `summary` (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": [
        "phone case"
    ],
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("sourcing-data-studio/aliexpress-search-api").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": 10,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("sourcing-data-studio/aliexpress-search-api").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": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call sourcing-data-studio/aliexpress-search-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sourcing-data-studio/aliexpress-search-api"
        }
    }
}
```

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/INbYmglrjsolDhCXA/builds/fyeRHInAwGvHeJxRs/openapi.json
