kestrel actors › Ecommerce
AliExpress Reviews Scraper — Product Feedback & Ratings
This AliExpress reviews scraper turns any product page into a clean table of AliExpress product reviews: the 1-5 star rating, the buyer's own words plus a machine translation into the language you pick, the buyer's country, the exact SKU variant the review is about, the photos they uploaded, the shipping method the order used, the follow-up review they came back and wrote weeks later, and the helpful votes other shoppers gave it. Give it product URLs or item ids and it reads the same public AliExpress feedback endpoint the product page's own review widget calls — no API key, no login, no cookies, no headless browser. It is built as an AliExpress product research tool for dropshipping product validation: buyer reviews and buyer photos are how you tell a product worth listing from one that will drown you in refunds, and this is the cheapest way to pull them in bulk.
Run AliExpress Reviews Scraper on Apify →
AliExpress reviews scraper pricing: what one row costs
| Event | What it is | Price | Charged for |
|---|---|---|---|
review | Review row | $0.002 | One AliExpress buyer review: the 1-5 star rating, the buyer's text and AliExpress's translation of it, buyer name and country, the SKU variant bought, the buyer's photos, the shipping method, the follow-up review, helpful votes and the structured product attributes rated. Products with no reviews, unknown item ids, product rows, duplicate targets and filtered reviews are free. |
AliExpress reviews scraper input reference
Every field of AliExpress Reviews, straight from the actor's input schema.
| Field | Type | Default | What it does |
|---|---|---|---|
productUrls | array | [] | AliExpress product pages, e.g. https://www.aliexpress.com/item/1005006255429323.html — aliexpress.us, aliexpress.ru, the /i/<id>.html short form and any share link with tracking junk after the ? all work, because every AliExpress item URL carries the numeric item id in its path. No page has to be loaded to resolve them. |
productIds | array | [] | AliExpress numeric item ids, e.g. 1005006255429323 — the number in /item/<id>.html, and what an earlier run's product_id gives you. All three AliExpress id namespaces work (1005…, 3256… on aliexpress.us, and the legacy 2255…/4000… ids), and they resolve to the same reviews. |
maxReviewsPerProduct | integer | 100 | 0 = every review the product has (AliExpress pages them in blocks of up to 500; a best-seller runs to a few thousand). N = the first N AliExpress serves. This is the main cost control: it caps how many reviews are read, and the filters below then decide which of them are worth paying for. Range 0-50000. |
reviewsFilter | string (enum) | "all" | The only three filters AliExpress itself applies, so the pages you do not want are never even fetched. All reviews = no filter. Only reviews with photos = AliExpress's own photo filter (buyer photos are the fastest way to judge whether a product is worth listing). Only reviews with a follow-up = buyers who came back weeks later to update their review, the best durability signal on the site. Only buyers from the chosen country = AliExpress's one country filter; it needs exactly one entry in Buyer countries. One of: all, with_photos, with_follow_up, same_country. |
minRating | integer | 0 | AliExpress reviews are whole stars, 1 to 5. 0 = no floor; 5 keeps only the perfect scores. AliExpress has no server-side star filter, so this one runs in the actor — the pages are still read, the filtered reviews are simply never charged. Range 0-5. |
maxRating | integer | 0 | The other end of the same 1-5 scale: 0 = no ceiling, 3 gives a complaints feed of everything a buyer was unhappy about. Combine with Sort = lowest rated first and the Complaints view in the dataset tab. Filtered reviews are never charged. Range 0-5. |
requireText | boolean | false | Drop star-only reviews (an empty feedback field) before billing. On AliExpress roughly one review in five is a bare star rating, so this is a real saving when you are after review text for product research. |
countries | array | [] | Keep only reviews from buyers in these ISO-2 countries, e.g. US, BR, ES, PL. Empty = every country. The first entry also tells AliExpress which market to answer as, which decides the ordering it serves and which reviews the "Only buyers from the chosen country" filter keeps. Filtered reviews are never charged. |
sort | string (enum) | "default" | The order the reviews are delivered in. AliExpress ignores every sort parameter its own endpoint accepts (verified 2026-08-29: complex_default, dateDescending and positive_first all return the identical page), so this actor orders the reviews it collected instead of pretending the site does. Newest/oldest use the review date; lowest rated first is the complaints feed. One of: default, newest, oldest, lowest_rating, highest_rating. |
language | string (enum) | "en_US" | AliExpress machine-translates every review into one language of your choice: text_translated comes back in this language whatever the buyer wrote in, and text keeps the original. It also decides the language the review date is written in, which the actor parses back to an ISO date for you. One of: en_US, es_ES, pt_BR, fr_FR, de_DE, it_IT, nl_NL, pl_PL, tr_TR, ru_RU, ja_JP, ko_KR. |
includeProductRow | boolean | true | Also emit one free row per product with its title, image, average rating, the full 1-5 star histogram, the positive/neutral/negative split, how many of its reviews carry photos or a follow-up, and the structured attributes buyers rated it on. It is what a product-research run actually wants, it costs one extra request per product, and it is never charged. |
sessions | integer | 2 | How many proxy sessions (egress IPs) run in parallel. More is faster; each is paced separately. Range 1-16. |
perIp | number | 1 | Pace for each session. AliExpress's feedback endpoint answered 150 back-to-back requests from a single datacenter IP with no throttling at all, and 10 of 10 at 1 req/s; 1-2 is comfortable. Range 0.1-5. |
proxyConfiguration | object | {"useApifyProxy": true} | Apify Proxy with the datacenter group is enough: the feedback endpoint answers plain HTTP requests from datacenter ranges with no key, no cookies and no bot gate. Residential works too and costs more. Keep the default. |
Example input
{
"productUrls": ["https://www.aliexpress.com/item/1005006255429323.html"],
"productIds": ["1005008342451530"],
"maxReviewsPerProduct": 200,
"reviewsFilter": "all",
"minRating": 0,
"maxRating": 3,
"requireText": true,
"countries": ["US"],
"sort": "lowest_rating",
"language": "en_US",
"includeProductRow": true,
"sessions": 2,
"perIp": 1,
"proxyConfiguration": {"useApifyProxy": true}
}
AliExpress reviews scraper output fields
One row per AliExpress buyer review (charged), plus a free product context row and a free status row per target.
Dataset views in the Apify Console: Overview, Reviews, Complaints, Photo reviews, Products, Status.
| Field | Type | What it holds |
|---|---|---|
type | string | review | product | status |
target | string | The input value (product URL or item id) this row came from |
product_id | string | AliExpress's numeric item id (the number in /item/<id>.html) |
product_title | string | Product title as AliExpress lists it |
product_url | string | The product's page on aliexpress.com |
product_image | string | Main product image URL (product rows) |
review_id | string | AliExpress's numeric evaluation id, unique per review |
review_date | string | Publication date, YYYY-MM-DD, parsed back from the language the review was requested in |
review_date_raw | string | The date exactly as AliExpress wrote it, e.g. "02 Mar 2026" or "02 мар 2026" |
rating | number | Star rating, 1-5 (on product rows, the product's average as a decimal such as 4.2) |
rating_100 | integer | AliExpress's own 0-100 score behind the stars: 100 = 5 stars, 80 = 4 stars, and so on |
text | string | The review exactly as the buyer wrote it; null when they left stars only |
text_translated | string | AliExpress's machine translation of the review into the language the run asked for |
language | string | Language code of the served text, e.g. en, ru, es |
buyer_name | string | Buyer display name, masked by AliExpress ("S***l") or "AliExpress Shopper" when they stayed anonymous |
buyer_country | string | Buyer country as an ISO-2 code, e.g. US, BR, PL |
buyer_gender | string | Buyer gender when AliExpress publishes it |
buyer_anonymous | boolean | true when the buyer hid their identity |
buyer_avatar | string | Buyer avatar image URL, when there is one |
sku_id | string | AliExpress's numeric id of the exact variant the buyer bought |
sku_info | string | The variant in words, e.g. "Color:LP40 white" — which colour or size the review is actually about |
images | array | Full-size URLs of the photos the buyer attached to the review |
image_count | integer | How many photos the review carries |
logistics | string | The shipping method the order used, e.g. "AliExpress Selection Standard Shipping" |
helpful_votes | integer | How many shoppers marked the review helpful |
unhelpful_votes | integer | How many shoppers marked the review unhelpful |
attributes | object | The structured attributes AliExpress asked this buyer to rate, e.g. {"Quality of sound": "Good", "Durability": "Fits ok"} |
follow_up_text | string | The follow-up review the buyer added later, in their own words |
follow_up_translated | string | Machine translation of the follow-up review |
follow_up_date | string | Date of the follow-up review, YYYY-MM-DD |
follow_up_days | integer | How many days after the first review the follow-up was written — the durability signal |
follow_up_images | array | Photos attached to the follow-up review |
featured | boolean | true when AliExpress promotes this review to the top of the product page |
ai_generated | boolean | AliExpress's own flag for a review it believes was written by AI |
rating_percent | number | The product's average rating as a percentage, AliExpress's own number (product rows) |
reviews_total | integer | How many reviews AliExpress says the product has (product rows) |
reviews_fetched | integer | Reviews read in this run for the product, before filters (product rows) |
five_star | integer | Number of 5-star reviews (product rows) |
four_star | integer | Number of 4-star reviews (product rows) |
three_star | integer | Number of 3-star reviews (product rows) |
two_star | integer | Number of 2-star reviews (product rows) |
one_star | integer | Number of 1-star reviews (product rows) |
positive_count | integer | Reviews AliExpress counts as positive, 4-5 stars (product rows) |
neutral_count | integer | Reviews AliExpress counts as neutral, 3 stars (product rows) |
negative_count | integer | Reviews AliExpress counts as negative, 1-2 stars (product rows) |
positive_rate | number | Share of positive reviews as a percentage (product rows) |
negative_rate | number | Share of negative reviews as a percentage (product rows) |
with_photos_count | integer | How many of the product's reviews carry buyer photos (product rows) |
with_follow_up_count | integer | How many carry a follow-up review written later (product rows) |
same_country_count | integer | How many were written by buyers in the country the run asked as (product rows) |
product_type | string | AliExpress's own product classification, e.g. ORDINARY (product rows) |
review_attributes | array | The structured attributes buyers rated the product on, with how many said each thing — the fastest read on what people love and hate (product rows) |
status | string | ok | no_reviews | not_found | duplicate | error (status rows) |
reviews | integer | Reviews delivered and charged for this target (status rows) |
filtered | integer | Reviews dropped by the filters, never charged (status rows) |
pages | integer | Requests made for this target (status rows) |
total | integer | Reviews AliExpress lists for the product (status rows) |
repeats | integer | Reviews AliExpress served twice across its shuffled result shards and this run dropped (status rows) |
duplicates | integer | 1 when this target resolved to a product another target already covers (status rows) |
error | string | Why a target failed (status rows) |
fetched_at | string | UTC timestamp of the request |
Example row from a real run
Taken from the actor's README — this is the shape your dataset holds.
{
"type": "review",
"review_id": "60094105248269979",
"product_id": "1005006255429323",
"product_title": "Original Lenovo LP40 wireless headphones TWS Bluetooth Earphones",
"product_url": "https://www.aliexpress.com/item/1005006255429323.html",
"rating": 5,
"rating_100": 100,
"review_date": "2025-11-29",
"review_date_raw": "29 Nov 2025",
"text": "Fast delivery! Package came within estimate delivery. The headphones came in perfect condition, and the sound and connection is very nice.",
"text_translated": "Fast delivery! Package came within estimate delivery.",
"language": "en",
"buyer_name": "AliExpress Shopper",
"buyer_country": "US",
"buyer_anonymous": true,
"sku_id": "12000036486711239",
"sku_info": "Color:LP40 white",
"images": ["https://ae-pic-a1.aliexpress-media.com/kf/Ab1b4386f35a14c28b499f08897b6fea0y.jpg"],
"image_count": 1,
"logistics": "AliExpress Selection Standard",
"helpful_votes": 0,
"unhelpful_votes": 0,
"attributes": {"Quality of sound": "Fast", "Durability": "Fast", "User Friendly": "Good"},
"follow_up_text": null,
"follow_up_days": null,
"featured": true,
"ai_generated": false
}
{
"type": "product",
"product_id": "1005006255429323",
"product_title": "Original Lenovo LP40 wireless headphones",
"product_image": "https://ae-pic-a1.aliexpress-media.com/kf/Haa1bfb60935a4a3ca5e24c9ef3bcd163R.jpg",
"product_url": "https://www.aliexpress.com/item/1005006255429323.html",
"rating": 4.2,
"rating_percent": 84.9,
"reviews_total": 2836,
"reviews_fetched": 100,
"five_star": 1888, "four_star": 380, "three_star": 207, "two_star": 106, "one_star": 266,
"positive_count": 2268, "neutral_count": 207, "negative_count": 372,
"positive_rate": 79.7, "negative_rate": 13.0,
"with_photos_count": 313,
"with_follow_up_count": 82,
"same_country_count": 257,
"product_type": "ORDINARY",
"review_attributes": [{"attribute": "Durability : Fits ok", "reviews": 1493, "value_id": 1500325947}]
}
AliExpress reviews scraper in Python, JavaScript and curl
Python
from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("kestrel/aliexpress-reviews-scraper").call(run_input={
"productUrls": ["https://www.aliexpress.com/item/1005006255429323.html"],
"maxReviewsPerProduct": 500,
"reviewsFilter": "with_photos",
"requireText": True,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
if row["type"] == "review":
print(row["rating"], row["buyer_country"], row["sku_info"], row["text"])
JavaScript (Node)
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('kestrel/aliexpress-reviews-scraper').call({
productIds: ['1005006255429323'],
maxReviewsPerProduct: 0,
maxRating: 3,
sort: 'lowest_rating',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((i) => i.type === 'review').length, 'complaints');
curl
curl -X POST "https://api.apify.com/v2/acts/kestrel~aliexpress-reviews-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"productUrls":["https://www.aliexpress.com/item/1005006255429323.html"],"maxReviewsPerProduct":100}'
The same three calls are runnable files in the examples repository: examples/aliexpress-reviews-scraper.py|.js|.sh.
What are the limits of the AliExpress feedback endpoint?
Worth knowing before you plan a job, all measured on 2026-08-29:
- AliExpress does not sort. Every sort value its own endpoint accepts returns the identical page. That is why
sorthere orders the reviews the run collected rather than pretending the site does it. - Page 1 always returns 20 rows, whatever page size is requested, while later pages honour up to 500 at a plain offset. A naive scraper asking for 100 per page silently loses reviews 21-100 of every product. This one only ever asks for a page size that divides the offset and counts the rows it actually received, so nothing is skipped.
- The backend shuffles. Two result orderings are served at random, so a deep walk sees a small share of reviews twice. They are deduped by
review_id, and the count that was dropped is reported inrepeats. - An empty answer is ambiguous. A product with no reviews and an item id that does not exist return byte-identical responses. This actor never guesses: an empty list is re-asked on a fresh IP and then settled against the product page, so you get
no_reviewsornot_found, never a false "no reviews" because of a throttle. A genuine refusal is reported asstatus: "error"with the reason. - Price, stock and seller data are not in this dataset. The product page renders them in the browser, so a reviews scraper cannot read them without one. Use a product scraper for those.
FAQ
Do I need an AliExpress API key or account?
No. This reads the same public feedback endpoint the product page itself calls. No key, no cookies, no login, no browser.
How do I get AliExpress reviews by product id?
Put the numeric id straight into productIds. It is the number in /item/<id>.html, and it is what the product_id column of an earlier run gives you, so a two-stage pipeline (find products, then pull reviews) needs no URL building at all.
Can I download AliExpress reviews as a CSV?
Yes — every run's dataset exports to CSV, JSON, Excel, XML or RSS from the run page, or through the Apify API. Use the Reviews or Complaints view first if you want a tidy column set.
How do I get AliExpress negative reviews only?
Set maxRating: 3 and sort: "lowest_rating". The Complaints view then puts the text, the photos, the variant, the shipping method and any follow-up side by side. Filtered-out reviews are never charged.
Can I get only AliExpress review photos?
Yes. Set reviewsFilter: "with_photos" — that is the site's own filter, so the pages without photos are never fetched. The images and image_count columns carry the full-size URLs of the AliExpress buyer photos.
Is there an AliExpress reviews API?
There is no public AliExpress reviews API you can sign up for. This actor is the practical substitute: a REST endpoint you call with a token, returning AliExpress reviews without an api key of your own, in JSON or CSV.
How many reviews can I get per product?
Every review the site will page through. maxReviewsPerProduct: 0 takes them all; the ceiling in practice is what a product actually has. Very large products run to a few thousand and take a couple of minutes.
Does it translate reviews?
Yes. text keeps the buyer's original words and text_translated carries the site's machine translation into whichever of the twelve language options you choose, so a Polish buyer's complaint arrives readable in English.
Can I schedule it to monitor new reviews?
Yes — schedule the actor daily or weekly, sort newest, cap maxReviewsPerProduct at a hundred or so, and dedupe on review_id downstream. That is the cheapest form of review monitoring for a catalogue you resell.
What happens if a product id is wrong?
You get a free status row with status: "not_found" and a reason, and the run carries on with the other targets. Nothing is charged.
How to use AliExpress Reviews Scraper
Related scrapers
Run AliExpress Reviews Scraper
The actor lives on the Apify Store, where the pricing tab carries the live per-row price and the input form has every field above: apify.com/kestrel/aliexpress-reviews-scraper