DEV Community

Cover image for How to Scrape AliExpress Search Results with Python
ReventaData
ReventaData

Posted on Originally published at apify.com

How to Scrape AliExpress Search Results with Python

By the end of this tutorial, you will have a short Python script that turns AliExpress search results into structured JSON: one row per product with its id, title, canonical product URL, price, currency, star rating, units sold, image links and the shipping tag the card shows.

We use the Apify Actor AliExpress Scraper (reventadata/aliexpress-scraper). It is for anyone who tracks prices on AliExpress, sizes up a product niche by units sold, or compares listings by rating, and would rather read rows than scroll result cards.

⏱️ Time: setting this up takes a few minutes: an account, a token and one script.

You will learn how to configure the input, run the Actor from Python, read every field it returns, and avoid the filter traps that make a run come back empty.


Prerequisites

Install the client:

pip install "apify-client~=3.0"
Enter fullscreen mode Exit fullscreen mode

No scraping code is needed: the Actor fetches the search pages, reads the cards and saves the rows. You send an input and read the results.


What you'll achieve

You will send one or more search queries (for example phone case or mechanical keyboard) and receive one clean row per product card on the AliExpress search results. The Actor reads the search result cards only; it does not open product pages one by one.

That keeps each row to what a card shows: title, price, rating, the sold count, images and a shipping tag. There is no seller profile, description or variant table.

Example use case: you want the best-rated phone cases with real sales behind them. Set minRating to 4.5 and minSold to 100, and the Actor keeps only cards that clear both bars.


Step 1: Access AliExpress Scraper

Open the AliExpress Scraper page on Apify Store. In Apify Console, an Actor opens on its Input tab, where you can fill the same fields this tutorial sets from code.

We will run it from Python, so keep your API token at hand and export it:

export APIFY_API_TOKEN="<your token>"
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure your queries and the caps

The one required field is searchQueries: a list of search terms. For each query the Actor builds an AliExpress search URL and walks its pages. For the prefill query phone case, page 1 is:

https://www.aliexpress.com/w/wholesale-phone-case.html?page=1&SearchText=phone+case&shipTo=US&currency=USD

Here is the script. Its input is the Actor's own prefill: one query, 5 rows, one page.

import os

from apify_client import ApifyClient

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

run_input = {
    "searchQueries": ["phone case"],
    "maxItems": 5,
    "maxPages": 1,
    "country": "US",
    "currency": "USD",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["UNBLOCKER"],
    },
}

run = client.actor("reventadata/aliexpress-scraper").call(run_input=run_input)
if run is None or run.status != "SUCCEEDED":
    raise SystemExit(f"Run did not succeed (status: {run.status if run else 'unknown'})")

for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item["id"], "|", item["title"][:60], "|", item["price"], item["currency"], "|", item["rating"], "|", item["soldCount"])
Enter fullscreen mode Exit fullscreen mode

maxItems is the total number of rows to save across all queries. maxPages caps the pages walked per query. Without them, the defaults are 60 and 5.


Step 3: Add filters

Parameter Type Default What it does
country string US Sent to AliExpress as shipTo.
currency string USD Sent to AliExpress as currency.
minPrice, maxPrice number none Price band. A card with no readable price is dropped when either is set.
minRating number none Minimum star rating, 0 to 5. Unrated cards are dropped when set.
minSold integer none Minimum units sold. Cards without a sold count are dropped when set.
proxyConfiguration object Unblocker Apify Unblocker proxy by default.

Three details worth knowing:

  • The filters run on the cards the Actor reads, after each page is fetched. A tight minSold can leave a page with few kept rows, so raise maxPages when you filter hard.
  • Every word of a query must appear in the title, ignoring case and accents. That is how the Actor drops the unrelated recommendation cards AliExpress shows when nothing matches a query.
  • Accessory and damaged listings are dropped. Titles with words like case, cover, cable, strap or holder are treated as accessories, unless your query itself contains case, cover, protector, cable, strap or tip. Titles admitting damage (broken, faulty, cracked, for parts, not working) are dropped too, but a negation such as "anti scratch" keeps the row.

Step 4: Run the Actor

Run the script with python aliexpress.py. .call() starts the Actor on Apify and waits until it finishes. Behind the scenes the Actor requests each search page (through Apify's Unblocker proxy, unless you change proxyConfiguration), reads the result cards, applies your filters and saves the rows. A product that shows up under two of your queries is saved once.

A query stops at the first page with no cards, or when you reach maxPages. Rows stop being saved at maxItems: the current query may still read its remaining pages, and later queries are skipped.

⚠️ Tip: .call() blocks until the run ends. To fire and forget, use a webhook instead (see the pro tips below).


Step 5: View and download results

The script prints one line per row. In Apify Console, results appear in the run's Output tab, and Export downloads them. Datasets export as JSON, CSV, XML, Excel, HTML table, RSS or JSONL.

Here is a sample row, a sample from a capture dated 2026-10-16: one search card saved from the Spanish storefront in a browser and parsed with the Actor's own row builder. It is not output of the prefill input above, which is why the price is in euros. matchedKeyword and scrapedAt are left out:

{
  "id": "1005010497678198",
  "title": "Auriculares Inalámbricos Bluetooth 5.3 HiFi Estéreo Resistente al Sudor Cascos Calgante Deportivo TEISCHE SW-08",
  "url": "https://www.aliexpress.com/item/1005010497678198.html",
  "price": 7.71,
  "originalPrice": null,
  "discountPercent": null,
  "currency": "EUR",
  "rating": 4.9,
  "soldCount": 38,
  "soldText": "38 vendidos",
  "thumbnailUrl": "https://ae-pic-a1.aliexpress-media.com/kf/E8a248d80dbf340dfa7bb04ad6b8d07a0h.jpg_480x480q75.jpg_.avif",
  "galleryImages": [
    "https://ae-pic-a1.aliexpress-media.com/kf/E8a248d80dbf340dfa7bb04ad6b8d07a0h.jpg_480x480q75.jpg_.avif",
    "https://ae-pic-a1.aliexpress-media.com/kf/Eb36c445f517d42efa7b4f1b916048f2ef.jpg_480x480q75.jpg_.avif",
    "https://ae-pic-a1.aliexpress-media.com/kf/E95a75f15f62543ccbbd8d0aba4ee4293s.jpg_480x480q75.jpg_.avif",
    "https://ae-pic-a1.aliexpress-media.com/kf/E34099cc5d0ee42f59a3a636328810addc.jpg_480x480q75.jpg_.avif",
    "https://ae-pic-a1.aliexpress-media.com/kf/E8c10f199c77049a0a5cb4fa099b304efF.jpg_480x480q75.jpg_.avif"
  ],
  "shippingDisplay": "Envío gratis a partir de 10,9€",
  "isFreeShipping": false
}
Enter fullscreen mode Exit fullscreen mode

Understanding your results

  • id is the AliExpress product id, and url is rebuilt from it as https://www.aliexpress.com/item/<id>.html, with the long query string of the card link dropped.
  • price is the price shown on the card, as a number. currency is read from the card when it shows a euro, pound or dollar sign or code, else it is the currency you asked for.
  • originalPrice and discountPercent are null in every row of the current version, so do not build a discount report on them yet.
  • soldCount is the digits of soldText: "38 vendidos" becomes 38, and a text like "1,000+ sold" becomes 1000, a floor rather than an exact count.
  • isFreeShipping is true only when the tag says plain "Free shipping" (or "Envío gratis"). A conditional tag, like the "free shipping from 10,9€" one above, stays in shippingDisplay and leaves the flag false.
  • galleryImages holds up to 5 image links from the card.
  • matchedKeyword is the query that kept the row; scrapedAt is when it was saved.

Pro tips and advanced usage

  1. Write queries in the words of the titles. The sample card's title is Spanish, so wireless earbuds would not keep it, while auriculares inalambricos would: every query word must be in the title.
  2. Use minSold to skip untested listings. Cards without a sold count are dropped when it is set, so you only get products with sales on display.
  3. Put several queries in one run. searchQueries takes a list, and a product found by two of them is saved once.
  4. Hook it to your pipeline. An Apify webhook fires when a run finishes; its resource is "the response of the Get Actor run API endpoint" (docs.apify.com/integrations/webhooks/actions), which carries defaultDatasetId.
  5. Check currency in your own rows. The Actor sends country and currency to AliExpress, and it takes the row's currency from the card when the card shows one, so read it from the rows rather than assuming it.

For current pricing and details, see the Store page.


Troubleshooting common issues

  • "0 results for queries ...". A blocked page or a page without cards ends the run FAILED; when pages loaded but nothing passed, it ends SUCCEEDED with an empty dataset. Usually a query word is missing from the titles, or minRating, minSold or the price band dropped every card. Loosen one at a time.
  • Fewer rows than maxItems. The filters dropped cards and maxPages ran out first. Raise maxPages.
  • Nothing happens and the log says "No searchQueries provided in input." The query list is empty; add at least one query.
  • An input rejected at start. maxItems and maxPages must be at least 1, the price and sold filters 0 or more, and minRating between 0 and 5; an input outside the schema is refused before the run starts.

The run's log shows each page fetched and how many cards were parsed and kept on it.


Next steps

Save your input as an Apify task and add a schedule: schedules use cron expressions, so a daily price check is one line (docs.apify.com/actors/running/schedules). The Apify Python client docs cover the rest of the API. Start with the prefill input above and grow from there.

What are you planning to scrape on AliExpress? Drop a comment! 💬

Top comments (0)