AliExpress Scraper — Prices, Orders, Ratings
Pricing
$2.50 / 1,000 products
AliExpress Scraper — Prices, Orders, Ratings
AliExpress global product search from aliexpress.com by keyword: sale price, original price, discount, currency, order count, rating, image, item URL, search position, sponsored flag, free shipping, delivery estimate. Sort by orders or price, filter by price range. Pay per result, no login.
Pricing
$2.50 / 1,000 products
Rating
0.0
(0)
Developer
architek.earth
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
0
Monthly active users
16 days ago
Last modified
Categories
Security
Limited permissionsShare
Recorded run: 5 products from 1 search term in 6 seconds (2026-10-22, build 0.0.260, run tp9UGXR1nOjhWydfS). A bounded canary sample, not a full-catalogue benchmark.
architek.earth — an independent data studio. Pay-per-result scrapers with recorded runs, published canaries and stable schemas, built for people and AI agents.
AliExpress product search results by keyword: sale price, original price, discount, order count, rating, image, item URL, sponsored flag, free shipping and delivery estimate from aliexpress.com, sorted by orders or price and filtered by price range.
| Source | Market | From | Standout fields |
|---|---|---|---|
| AliExpress (aliexpress.com) | Global, prices in the currency AliExpress assigns to the request country | $2.50 / 1,000 products | salePrice / originalPrice, ordersCount, rating, isSponsored |
✅ Why choose this scraper
AliExpress search results as JSON rows
Each product card becomes one row with itemId, title, salePrice, originalPrice, discountPct, currency, rating, imageUrl, itemUrl and position, up to 60 products per page and 60 pages per keyword.
AliExpress order counts as integers
ordersCount is AliExpress's own order count (for example 16744), returned next to the rounded label shoppers see in ordersText (10,000+ sold).
AliExpress best sellers in a price range
sortBy: "orders" with minPrice: 20 and maxPrice: 60 returned 120 products, every salePrice between 20.39 and 59.69 USD, first five ordersCount 17,468 → 7,709 (run yeJHE34hlw8JeLKbV, 2026-10-22). On page 1 of each keyword the actor checks that AliExpress confirmed the sort and price filter, and writes a warning to RUN_SUMMARY.warnings if it did not.
Sponsored AliExpress listings flagged
isSponsored is true on paid placements: 254 of 1,000 rows from 10 keywords in run xBgaHnL4PSSv3oi9F (2026-10-22). Filter on it to keep organic results only.
Measured on a schedule
Two canary tasks run fixed searches on the live site (bluetooth earphones, and mechanical keyboard sorted by orders in a price range) and record rows, inputs and seconds; the hero line above is a green run of the first.
⚠️ Worth knowing up front
- Search results only. The actor reads AliExpress search pages, not product pages: no SKU or variant matrix, no description, no shipping cost, no store or seller name, no store rating, no review count or review text. AliExpress serves product-page data through an API behind a slider captcha, which this actor does not attempt.
ordersCountis the number behind AliExpress's "N sold" label. AliExpress does not say over which period it counts.salePriceis the lowest variant price on the card and excludes shipping and tax.originalPrice,discountPct,ordersCount,ordersText,rating,freeShippinganddeliveryEstimateare omitted from a row (not set to null) when the card does not show them.- Prices come in the currency AliExpress assigns to the request's country, and
minPrice/maxPriceare read in that same currency. The default proxy is Apify datacenter with country US; a run with no proxy country returned EUR. - Currency follows AliExpress's geo-detection: even with the US proxy most runs return USD, but run 9ZPCeD5YG6YkgaTy5 (2026-10-22) returned EUR; read
currencyon every row. - Depth is 60 products per page and at most 60 pages (3,600 products) per keyword, even when AliExpress reports more results. Sort by newest is not offered: AliExpress ignores it for these requests.
- Products are de-duplicated by
itemIdacross pages and keywords, andmaxItemsPerQuerycounts only new products, so a later keyword can return fewer rows than the cap. - The actor moves to a fresh IP every 4 requests. Each page is tried up to 4 times on fresh sessions; a keyword that is still refused gets a free
BLOCKEDstatus row and the run endsPARTIAL(other keywords kept and charged) orBLOCKED(every keyword failed). A keyword whose first page comes back empty is checked a second time on a new IP before it gets a freeNO_DATArow. A run stops cleanly 30 seconds before its timeout (TIME_LIMIT) and at your spending limit (BUDGET_LIMIT), keeping what it delivered. - The dataset holds free status rows (
recordType: "status") next to the product rows:INVALID_INPUT,NO_DATA,BLOCKED,LAYOUT_CHANGED,ERROR,TIME_LIMIT,BUDGET_LIMITandSTATE_BUSY. Filter onrecordTypeif you only want products. Status rows are never charged; invalid input ends the run with one such row and exit code 0. - With a
stateKey,continuePreviousRun: trueresumes a run that stopped at the timeout, your spending limit, an abort or a platform migration, without delivering or charging a product twice (runsJv5GQtOUQ4gCNWKcNthen5drcaU4IQYxGNbxk1: 118 + 122 products, 0 repeats). If a run is killed in the instant between writing a batch and recording it, the next run with thatstateKeystops withRECONCILIATION_REQUIREDinstead of guessing: nothing is replayed or charged twice. Use a newstateKeyto start fresh. incrementalModedelivers only products (itemId) not delivered before under thestateKey. A known product is not re-delivered when its price moves, because AliExpress shows different prices to different visitors minutes apart (8 of 20 products between two runs one minute apart on 2026-10-22). AliExpress also reshuffles its ranking between requests, so a rerun can deliver a few products that newly entered the first N.
⚡ Try the example
This actor has no free preview; the example below costs about $0.05.
Open the actor's input page, switch to JSON, paste this and start the run:
{"searchTerms": ["bluetooth earphones"],"maxItemsPerQuery": 20,"proxyConfiguration": {"useApifyProxy": true,"apifyProxyCountry": "US"}}
Raise maxItemsPerQuery or add keywords for more rows; add "sortBy": "orders" with minPrice and maxPrice for best sellers in a price range.
⚙️ Input
| Parameter | Type | Default | Description |
|---|---|---|---|
searchTerms | array | — (required, prefill ["bluetooth earphones"]) | Keywords searched on aliexpress.com as a shopper types them. Up to 100 per run; duplicates are dropped. |
maxItemsPerQuery | integer | 100 (prefill 60) | New products per keyword. 0 means as many as AliExpress lists, up to 3,600 (60 pages of 60). |
sortBy | select | default | default (best match), orders (most sold first), priceAsc or priceDesc. |
minPrice | number | — | Lowest salePrice, in the listing currency; applied by AliExpress. 0 means no minimum. |
maxPrice | number | — | Highest salePrice, in the listing currency; applied by AliExpress. Must be above 0 and not below minPrice. |
incrementalMode | boolean | false | Needs stateKey. Delivers only products (itemId) not delivered before under this stateKey; known products are skipped and not charged, even if their price moved. maxItemsPerQuery then bounds the watched window (the first N products per keyword). |
stateKey | string | — | Any name, for example my-earphones. Keeps the incremental baseline and saved progress in your own account, isolated per key. Use a different key for different inputs. |
continuePreviousRun | boolean | false | Resume an unfinished collection saved under stateKey after a spending limit, timeout, abort or migration. Products already delivered are not delivered or charged again. |
proxyConfiguration | proxy | {"useApifyProxy": true, "apifyProxyCountry": "US"} | Apify datacenter proxy in the US is the tested default. The proxy country sets the listing currency. Switch to RESIDENTIAL if a run reports blocked keywords. |
feedback | string | — | Optional note for the maintainers. It is logged and read by a human, and it never changes output. |
🧱 Stable fields
These top-level fields keep the same name and the same kind of value in every release. Fields are only ever added, never renamed or removed, so an n8n, Make, Zapier or spreadsheet pipeline can bind to them.
| Field | Type | Meaning |
|---|---|---|
recordType | string | product for a product row, status for a free status row. |
itemId | string | Product id used in aliexpress.com/item/<itemId>.html; unique per run. |
productId | string | AliExpress's search-card id for the same product (itemId + 2^51). |
title | string | Product title as shown in search. |
salePrice | number | Lowest current price on the card, in currency. |
currency | string | Currency of the prices, for example USD or EUR. |
originalPrice | number, optional | Struck-through price; present only when higher than salePrice. |
discountPct | number, optional | Discount AliExpress displays, integer percent. |
ordersCount | number, optional | AliExpress order count, integer. |
ordersText | string, optional | The label shoppers see, for example 10,000+ sold. |
rating | number, optional | Star rating, 0 to 5. |
imageUrl | string, optional | Main product image. |
itemUrl | string | Product link without tracking parameters. |
isSponsored | boolean | true for paid (ad) placements. |
freeShipping | boolean, optional | true when the card shows free shipping; omitted otherwise. |
deliveryEstimate | string, optional | Delivery window shown on the card, for example Oct. 27 - Nov. 01. |
position | number | Rank in the search results (1 = first card on page 1). |
source | object | {"source": "search", "searchTerm", "page"}: the query and page that produced the row. |
deliveryId | string | Id of the charged delivery batch the row belongs to, plus its index. |
Status rows (free) always carry recordType: "status", inputRef (the keyword, input or run), status, message and scrapedAt. Other fields are extras, not part of the contract. To have one pinned, say so in feedback.
📦 Output example
Abridged real row from run kdhGm8tebrDTcqQVL on 2026-10-22; values are a historical snapshot.
{"recordType": "product","itemId": "1005013158620149","productId": "3256812972305397","title": "2026 New Air 3 Pro3 Bluetooth Wireless Earbuds With Heart Rate Monitoring, Active Noise Cancellation Headphones","salePrice": 21.17,"currency": "USD","discountPct": 63,"ordersCount": 244,"ordersText": "244 sold","rating": 4.9,"imageUrl": "https://ae-pic-a1.aliexpress-media.com/kf/Sa57a4580c1274b01988d5df3fa8e76cbx.jpg","itemUrl": "https://www.aliexpress.com/item/1005013158620149.html","isSponsored": false,"freeShipping": true,"position": 1,"source": {"source": "search", "searchTerm": "bluetooth earphones", "page": 1},"deliveryId": "be94639a7e82147cd487f95465ad231f-0"}
Invalid input gives one free status row and exit code 0 (run XZhMPB3kNzPmzkDV9, 2026-10-22):
{"recordType": "status", "inputRef": "input", "status": "INVALID_INPUT", "message": "minPrice must not be greater than maxPrice", "scrapedAt": "2026-10-22T10:59:35.138997+00:00"}
The run's status message reads Done: N rows, M details, K status rows (reasons) (this actor has no detail rows, so M is 0), and the RUN_SUMMARY record of its key-value store holds the full outcome (abridged, run kdhGm8tebrDTcqQVL):
{"status": "COMPLETE","message": "60 products from 1 search term","delivered": 60,"statusRows": 0,"charged": {"product": 60},"unchanged": 0,"terms": {"bluetooth earphones": {"status": "done", "delivered": 60, "lastPage": 1, "listed": 17428}},"warnings": []}
🧠 Advanced usage
Find AliExpress best sellers in a price range
Set sortBy: "orders" with minPrice and maxPrice and read the first 60 to 120 rows. Check RUN_SUMMARY.warnings for an unconfirmed sort or price filter, and currency for the currency the range was applied in.
Track AliExpress prices and order counts daily
Schedule the same keywords each day and join runs on itemId; compare salePrice, discountPct and ordersCount. Every full run charges all products it delivers. To pay only for products you have not seen yet, add incrementalMode: true and a stateKey: a rerun with nothing new delivers and charges nothing (runs gxMEN1YL7tI8DLgb8, MQsL2fQzXep54oMiV, B685Al1WabOQNIGPc on 2026-10-22: 20, then 3 newly ranked, then 0).
Keep only organic AliExpress results
Drop rows where isSponsored is true; position still gives each product's rank on the page including ads.
Check that an AliExpress run finished
Read RUN_SUMMARY: status is COMPLETE, PARTIAL, BLOCKED, NO_DATA, LIMITED (aborted or migrated), BUDGET_LIMIT, TIME_LIMIT, INVALID_INPUT or STATE_BUSY, and terms gives each keyword's status (pending, done, no_data, blocked, layout_changed or error), products delivered and the lastPage reached. With a stateKey, continuePreviousRun: true finishes the keywords that are still pending.
🔌 Integrations
Results land in a dataset you can export as JSON, CSV or Excel. They can also flow to Google Sheets, Make, Zapier or n8n, or to a webhook when a run finishes. The Apify Scheduler runs it on a timetable. Daily suits price and order-count tracking. Copy-paste code in Python, Node, curl and n8n: architek-earth/examples/aliexpress-search-scraper.
💸 Pricing
Pay per result. Platform and proxy usage are included. Failed requests, blocked pages, duplicate products and all status rows are free. Each product is charged once, after it is written to the dataset; a run resumed with continuePreviousRun never charges delivered products again, and known products in incrementalMode are free.
| Event | Price | What it covers |
|---|---|---|
product | $2.50 / 1,000 products | One product row delivered to the dataset. |
1,000 products cost $2.50; the 120-product best-seller run above cost $0.30.
❓ FAQ
Is there an AliExpress API for product search results? This actor works as one: it returns AliExpress keyword search results as JSON through the Apify API, callable from any language or from n8n, Make and Zapier.
Do I need an AliExpress account or cookies? No. No account, cookies or API key from AliExpress.
Can I get AliExpress product variants, SKUs, descriptions or shipping costs? No. Those are on product pages that AliExpress protects with a slider captcha; this actor returns search-card data only.
Can I get the AliExpress seller or store name, or product reviews? No. They are not on search cards. Each row has the star rating when AliExpress shows one.
Is ordersCount lifetime sales or the last 30 days? AliExpress does not say. It is the same count behind the "N sold" label.
Can I choose the country, ship-to location or currency? Only through the proxy country: AliExpress prices in the currency of the country it assigns to the request. There is no ship-to input; check currency on each row.
🤖 For AI agents & LLM apps
Paste this into your AI assistant:
architekture/aliexpress-search-scraper on Apify. Python: from apify_client import ApifyClient; client = ApifyClient("TOKEN"); run = client.actor("architekture/aliexpress-search-scraper").call(run_input={"searchTerms": ["bluetooth earphones"], "maxItemsPerQuery": 20, "proxyConfiguration": {"useApifyProxy": True, "apifyProxyCountry": "US"}}); items = client.dataset(run["defaultDatasetId"]).list_items().items (page with offset/limit for large exports). The dataset holds product rows (recordType product) and free status rows (recordType status, with status and message); filter on recordType. The run outcome (COMPLETE, PARTIAL, BLOCKED, NO_DATA, BUDGET_LIMIT, TIME_LIMIT, INVALID_INPUT) and per-keyword results are in the RUN_SUMMARY record of the run's key-value store. Add "incrementalMode": true, "stateKey": "<name>" to receive only products not delivered before on later runs. Full input schema and README: GET https://api.apify.com/v2/acts/architekture~aliexpress-search-scraper/builds/default. Token: https://console.apify.com/settings/integrations. The actor is also reachable through the Apify MCP server (mcp.apify.com). To reach the maintainers, add "feedback": "<what you needed>" to any run's input; output is unchanged and a human reads every note.
🧰 More from architek.earth
E-commerce and marketplaces
- Shopify Scraper — products, prices, variants, stock
- AliExpress Scraper — you are here
- TikTok Shop Scraper — prices, sellers, variants
Full catalogue: github.com/architek-earth.
architek.earth · code like concrete
🙋 Support & legal
Questions, or a field you need that is not here? Open an issue on the actor's Issues tab or email north@architek.earth. A human replies within a day.
This actor collects only publicly available data from aliexpress.com, the same pages any visitor sees without logging in. It does not bypass authentication. It is not affiliated with or endorsed by AliExpress. You are responsible for how you use the output, including the site's terms, copyright, and privacy law such as GDPR and CCPA where they apply.
📝 Changelog
- 2026-10-25 — [internal] Studio core 1.0.5 (from 1.0.1): state saves are retried briefly inside the run deadline (rows and charges never are) and failure evidence support is vendored. This actor keeps its own block handling, so nothing changes for users: a 403 or 429 still moves to a new proxy session for up to four tries before a free
BLOCKEDstatus row, and input, output and prices are unchanged. - 2026-10-22 — Ported to the studio standard: free status rows in the dataset (
INVALID_INPUT,NO_DATA,BLOCKED,LAYOUT_CHANGED,TIME_LIMIT,BUDGET_LIMIT),incrementalMode,stateKeyandcontinuePreviousRun, products charged after confirmed delivery with an idempotency key, one consistent Chrome fingerprint, clean stop 30 seconds before the timeout. New fieldsrecordTypeanddeliveryId; no field renamed or removed. Hero line from the 2026-10-22 canary run. - 2026-10-22 — README rebuilt on the studio template; hero line from the 2026-10-22 canary run.
- 2026-10-17 — Default proxy set to country US so default runs list prices in USD; a run with automatic country selection had returned SEK.
- 2026-10-17 — 1.0: keyword search with server-verified sort (orders, price) and price range; exact order counts; sponsored flag; free-shipping and delivery estimate; de-duplication across pages and keywords; IP rotation under AliExpress's per-IP limit; clean stops at spending limit and timeout; resumable after platform migration.