# MercadoLibre Products Scraper (`nice_dev/mercadolibre-products-scraper`) Actor

Scrape MercadoLibre and Mercado Livre products in 18 countries: price, discount, sold count, seller, shipping, ratings, full product sheet, reviews and Q\&A. Keywords or URLs, every site filter, new products and price changes only.

- **URL**: https://apify.com/nice_dev/mercadolibre-products-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** E-commerce, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.54 / 1,000 products

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

### 🛒 What is MercadoLibre Products Scraper?

**MercadoLibre Products Scraper** extracts **products from [MercadoLibre](https://www.mercadolibre.com) and [Mercado Livre](https://www.mercadolivre.com.br) in all 18 countries**: **price, discount, installments, units sold, rating, seller, shipping (free, FULL), and with one tick the full product sheet, buyer reviews and questions & answers**. It works as a **MercadoLibre API alternative**: no key, no quota to request — run it on a schedule, call it from your code, or plug it into Make, Zapier or n8n.

Type a **keyword** (`notebook`) and pick the countries, or paste any MercadoLibre URL (search, category, official store, seller, deals, best sellers, product), click **Start**, and download the products in JSON, CSV or Excel. No login, nothing to set up.&#x20;

### 📋 What data can you extract from MercadoLibre?

One item per product, 69 fields:

| Category | What you get |
| --- | --- |
| 🏷️ **Product** | title, link, offer id, catalog product id, category, product type — `Apple iPhone 15 (128 GB) - Azul` |
| 💰 **Price** | current price, crossed-out price, discount %, currency, monthly installments and whether they are interest-free — `16,096.73 MXN, -5 %, 15 × 1,073.12 interest-free` |
| 🔥 **Sales and ratings** | units sold, average rating, number of ratings, card label (best seller, deal of the day), sponsored or not — `+1000 sold, 4.9 ★ (27,032)` |
| 🚚 **Shipping** | free shipping, FULL (stored and shipped by Mercado Libre), delivery promise, international purchase, free pick-up |
| 🏪 **Seller** | name, official store or not; with the product page: MercadoLíder level, reputation, sales, followers, badges, store page |
| 📝 **Product sheet** | full description, every specification, brand, model, variations (color, size…) with price and stock, stock left, warranty, returns, payment methods, category path, other sellers of the same product and their lowest price, every photo |
| ⭐ **Reviews and Q\&A** | buyer reviews (rating, text, date, country, likes, photos), rating breakdown by star, buyers' questions with the seller's answer |
| 🔔 **Monitoring** | new product or price drop / rise, previous price, change in % |
| 🔎 **Search** | keyword, rank in the results, page, order, number of results the site announces, country site |

Every field, with an example, is listed in the **Output** section below.

The **product sheet** fields and the seller's profile are filled when **Full product details** is on; **reviews** and **questions** when their options are on. All three are off by default: a plain run returns what the search results show.

### ✅ Why use MercadoLibre Products Scraper?

- 🌎 **All 18 countries in one run**: Brazil, Mexico, Argentina, Colombia, Chile, Peru, Uruguay, Ecuador, Venezuela and the 9 others — the same keywords searched on each country site, each in its own currency.
- 🎯 **Every site filter, on keywords too**: price range, condition, discount, free shipping, FULL, official stores, interest-free installments, best sellers, order — and the filters you set on the site are kept when you paste a search URL.
- 📈 **Past the 2,000-result limit**: MercadoLibre shows at most about 2,000 products per search; the Actor splits a bigger search into price ranges and reads them all (a search with a condition filter stays at about 2,000: see Known limitations).
- 🧩 **Pay only for what you need**: product sheet, reviews, questions & answers and market statistics are separate options, all off by default.
- 🔔 **New products and price changes**: tick **Only new products**, schedule the Actor, and each run returns (and charges) only what it has never delivered — plus, if you want, the products whose price went down or up.
- 🔌 API, scheduling, integrations (Make, Zapier, n8n, Google Sheets…) and JSON / CSV / Excel export via the Apify platform.

### 🚀 How to scrape MercadoLibre

1. Create a free Apify account.
2. Open **MercadoLibre Products Scraper**, type a **Search keyword** (e.g. `notebook`) and choose the **Country site** (and **More country sites** if you want several).
3. Or paste your own MercadoLibre URLs into **Start URLs** (search results with their filters, categories, official stores, sellers, deals, best sellers, product pages), or product ids into **Product ids**.
4. Set **Max products** (100 by default, 0 = no limit) — and **Max products per search** when you run several searches — then click **Start**.
5. Download the dataset in JSON, CSV, Excel or via API.

### 💰 How much does it cost to scrape MercadoLibre?

This Actor uses **pay per event** pricing (the same amounts are in the **Pricing** tab). You pay for the products saved, and each option for what it adds:

Prices are per 1,000 events, by Apify plan (a higher plan pays less).

| What you pay for | Event | Free | Bronze | Silver | Gold |
| --- | --- | --- | --- | --- | --- |
| Product saved | `apify-default-dataset-item` | $0.89 | $0.72 | $0.63 | $0.54 |
| Product sheet added to a product, only with **Full product details** (once per product) | `product-details` | $1.79 | $0.89 | $0.88 | $0.87 |
| Buyer review delivered, only with **Buyer reviews** | `review` | $0.89 | $0.72 | $0.63 | $0.54 |
| Question (with its answer) delivered, only with **Questions and answers** | `question` | $0.54 | $0.53 | $0.45 | $0.36 |
| Product returned because its price changed, only with **Also products whose price changed** | `price-change` | $1.79 | $1.78 | $1.77 | $1.76 |
| Market statistics of one search, only with **Add market statistics per search** (once per search) | `market-stats` | $3.99 | $3.98 | $3.97 | $3.96 |
| Product dropped by a filter (a product you keep pays its normal price instead) | `filter-check` | $0.12 | $0.11 | $0.10 | $0.09 |
| Run start | `apify-actor-start` | $0.02 per GB of run memory | $0.02 per GB of run memory | $0.02 per GB of run memory | $0.02 per GB of run memory |

Examples (no option ticked, platform usage included):

- **1,000 products, one run**: Free plan 1,000 × $0.00089 + $0.04 run start (2 GB of memory by default) = $0.93. Gold plan 1,000 × $0.00054 + $0.04 = $0.58.
- **Daily monitor with `onlyNew`**, 1 run a day for 30 days, about 50 new products a day: 30 run starts × $0.04 = $1.20, plus 1,500 new products. Free plan 1,500 × $0.00089 + $1.20 = $2.54. Gold plan 1,500 × $0.00054 + $1.20 = $2.01. You pay only for the new products, never for the ones you already had.

The options (product sheet, reviews, questions & answers, price changes, market statistics) are all off by default: nothing is charged for them unless you tick them. Splitting a big search into price ranges costs nothing extra. Most site filters are applied by MercadoLibre itself; the Actor checks every product again (and applies the filters the site does not have: rating, units sold, excluded words): a product a filter drops costs only `filter-check`, a product you keep costs its normal price. Platform usage (compute, proxy) is included in the price.

### ⚙️ Input

One keyword on two country sites, with the product sheet:

```json
{
    "query": "notebook",
    "country": "br",
    "countries": ["mx"],
    "maxItems": 200,
    "extractDetails": true
}
```

Several keywords, a cap per search, site filters, then only what is new or cheaper on the next runs:

```json
{
    "searchQueries": ["iphone 15", "samsung galaxy s24"],
    "country": "mx",
    "maxItemsPerQuery": 100,
    "condition": "new",
    "officialStoresOnly": true,
    "onlyNew": true,
    "includePriceChanges": true,
    "stateKey": "phones-mx"
}
```

Or with your own URLs and product ids:

```json
{
    "startUrls": [
        { "url": "https://listado.mercadolibre.com.mx/laptop" },
        { "url": "https://www.mercadolivre.com.br/loja/apple" }
    ],
    "productIds": ["MLM1027172667"],
    "maxItems": 500,
    "includeReviews": true
}
```

| Field | Notes |
| --- | --- |
| `query`, `searchQueries` | Free-text search, exactly as typed on the site; `searchQueries` adds more keywords (one search each). Ignored when `startUrls` is set. |
| `country`, `countries` | Country site, by its 2-letter code (`br`, `mx`, `ar`, `co`, `cl`…); `countries` adds more. Every keyword is searched on every country site (max 500 searches per run). |
| `startUrls` | Any MercadoLibre / Mercado Livre URL of the 18 countries: search results (filters kept), categories, official stores, sellers, deals, best sellers, product pages. The country is read from each URL. Max 1,000 URLs. |
| `productIds` | Single products by id (catalog product, seller product or listing); the 3 letters give the country. |
| `maxItems` | Stop after this many products for the whole run (`0` = unlimited). |
| `maxItemsPerQuery` | Cap for EACH search (keyword × country, or search URL). `0` = no per-search cap. |
| `splitByPrice` | Go past the site's ~2,000 results per search by splitting it into price ranges (on by default, no extra charge). Not done for a search with a `condition` (see Known limitations). |
| `sortBy` | Order of the results: `relevance`, `price_asc` or `price_desc`. |
| `condition` | `any`, `new`, `used` or `refurbished`. |
| `minPrice`, `maxPrice` | Price range, in the currency of the country site. |
| `minDiscountPercent`, `freeShippingOnly`, `fullShippingOnly`, `officialStoresOnly`, `interestFreeOnly`, `bestSellersOnly` | The site's own filters: minimum discount, free shipping, FULL, official stores, interest-free installments, best sellers. In Brazil, free shipping is checked by the Actor on each product (the site has no reliable filter for it): a product that does not show free shipping is left out. |
| `includeSponsored` | Keep the products shown as ads (on by default). |
| `extractDetails` | Read each product's page: full sheet and seller's profile (paid option). |
| `includeReviews`, `maxReviewsPerProduct`, `reviewSort`, `reviewMinRating`, `reviewMaxRating` | Buyer reviews (paid option): how many per product, order, star range. |
| `includeQuestions`, `maxQuestionsPerProduct` | Questions and answers (paid option): how many per product. |
| `includeMarketStats` | One sheet of market statistics per search in the MARKET_STATS record of the run (paid option). |
| `minRating`, `minSoldCount`, `excludeKeywords` | The Actor's own filters: minimum rating, minimum units sold, words that drop a product when its title contains them. |
| `onlyNew`, `includePriceChanges`, `minPriceChangePercent`, `stateKey`, `resetState` | Monitoring: only the products never delivered under this memory key, plus (option) those whose price moved by at least the given %; `resetState` forgets the memory. |
| Advanced | `proxyConfiguration` (the Actor's own residential proxy of each country, included in the price), `maxConcurrency`, `maxRequestsPerMinute`, `minRequestIntervalMs`, `maxRequestRetries`, `debugLog`. |

### 📦 Output

A real product (Mexico, with **Full product details**), shortened: long lists cut to their first values, a few columns left out.

```json
{
    "id": "MLM3571336480",
    "productId": "MLM1027172667",
    "userProductId": "MLMU399506630",
    "url": "https://www.mercadolibre.com.mx/apple-iphone-15-128-gb-azul-distribuidor-autorizado/p/MLM1027172667",
    "title": "Apple iPhone 15 (128 GB) - Azul - Distribuidor Autorizado",
    "price": 16096.73,
    "originalPrice": 16999,
    "discountPercent": 5,
    "currency": "MXN",
    "installmentsCount": 15,
    "installmentAmount": 1073.12,
    "installmentsInterestFree": true,
    "soldCount": 1000,
    "soldText": "+1000 vendidos",
    "rating": 4.9,
    "reviewCount": 27032,
    "condition": "new",
    "sellerName": "Apple",
    "isOfficialStore": true,
    "freeShipping": true,
    "fullShipping": true,
    "highlight": "APPLE TIENDA OFICIAL",
    "tags": ["Ahorra con Plan Canje"],
    "isSponsored": false,
    "imageUrl": "https://http2.mlstatic.com/D_NQ_NP_952616-MLA95935522561_102025-O.webp",
    "images": ["https://http2.mlstatic.com/D_NQ_NP_952616-MLA95935522561_102025-O.webp"],
    "categoryId": "MLM1055",
    "domainId": "MLM-CELLPHONES",
    "description": "Este IPhone es compatible con eSIM. Contacta a tu operador móvil para conocer cómo activarla.",
    "specifications": [{ "group": "Características generales", "name": "Marca", "value": "Apple" }],
    "brand": "Apple",
    "model": "iPhone 15",
    "variations": [{ "label": "Color", "value": "Azul", "productId": "MLM1027172667" }],
    "availableQuantity": 50,
    "warranty": "12 meses de garantía de fábrica",
    "paymentMethods": ["Mercado Crédito", "Mastercard", "American Express", "Visa"],
    "categoryPath": ["Celulares y Telefonía", "Celulares y Smartphones", "Apple"],
    "sellerLevel": "MercadoLíder Platinum",
    "sellerReputation": "5_green",
    "sellerBadges": ["Buena atención", "Entrega a tiempo"],
    "reviewStats": { "average": 4.9, "count": 27032, "byStar": { "1": 229, "2": 44, "3": 139, "4": 729, "5": 25891 } },
    "reviews": [],
    "questions": [],
    "changeType": null,
    "searchTotal": 969,
    "searchQuery": "iphone 15",
    "position": 1,
    "page": 1,
    "sortBy": "relevance",
    "country": "mx",
    "siteId": "MLM",
    "searchUrl": "https://listado.mercadolibre.com.mx/iphone-15",
    "scrapedAt": "2026-10-15T12:00:00.000Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel.

#### All 69 fields

| Fields | What you get |
| --- | --- |
| `id`, `productId`, `userProductId`, `url`, `title` | **Product**: offer id `MLM3571336480`, catalog product `MLM1027172667`, seller product `MLMU399506630`, public page, title |
| `price`, `originalPrice`, `discountPercent`, `currency` | **Price**: `16096.73`, crossed-out `16999`, `5` %, `MXN` |
| `installmentsCount`, `installmentAmount`, `installmentsInterestFree`, `installmentsText` | `15` installments of `1073.12`, interest-free, as printed |
| `soldCount`, `soldText`, `rating`, `reviewCount` | **Sales and ratings**: `1000` (a lower bound, from `+1000 vendidos`), `4.9`, `27032` ratings |
| `condition` | `new`, `used`, `refurbished` or `open_box` |
| `sellerName`, `isOfficialStore` | **Seller** as the results show it |
| `freeShipping`, `fullShipping`, `shippingText`, `isInternational` | **Shipping**: free, FULL, delivery promise as printed, shipped from abroad |
| `highlight`, `tags`, `isSponsored` | Card label (`MÁS VENDIDO`), other labels, shown as an ad |
| `imageUrl`, `images` | Main photo; every photo with details |
| `categoryId`, `domainId`, `otherOffersCount`, `otherOffersMinPrice` | Category `MLM1055`, product type `MLM-CELLPHONES`, other offers of the same product and their lowest price |
| `description`, `specifications`, `brand`, `model`, `variations` | **Product sheet** (details): full text, every specification, variations with price and stock |
| `availableQuantity`, `stockText`, `pickupText`, `warranty`, `returnPolicy`, `paymentMethods`, `categoryPath` | Stock, free pick-up, warranty, returns, payment methods, categories from the top (details) |
| `sellerId`, `sellerUrl`, `sellerLevel`, `sellerReputation`, `sellerSalesText`, `sellerFollowers`, `sellerType`, `officialStoreId`, `sellerBadges` | **Seller's profile** (details): `MercadoLíder Platinum`, reputation `5_green`, sales `+1 M`, followers, badges |
| `reviewStats`, `reviews` | **Reviews**: average, count and ratings per star; the reviews themselves (option) |
| `questions` | **Q\&A**: questions with the seller's answer and its date (option) |
| `changeType`, `previousPrice`, `priceChangePercent` | **Monitoring**: `new`, `price_drop` or `price_rise`, previous price, change in % |
| `searchTotal`, `searchQuery`, `position`, `page`, `sortBy` | **Search**: results announced, keyword, rank, page, order |
| `country`, `siteId`, `searchUrl`, `scrapedAt` | Country site `mx`, site code `MLM`, results page, ISO timestamp |

### 💡 Tips

#### How to get more results

Set `maxItems` to `0` and keep **Go past 2,000 results per search** on: a broad keyword then returns every product the site has for it, not just the first 2,000. Add country sites with `countries` to cover more markets in the same run.

#### How to reduce costs

The levers are `maxItems`, `maxItemsPerQuery`, the filters (a product a filter drops costs only the filter fee, lower than a product) and `onlyNew` for recurring runs (you never pay twice for the same product). Tick only the options you use: the product sheet, reviews and questions are charged on top of each product.

#### Several searches in one run

Fill `searchQueries` and / or `countries`: the Actor runs one search per keyword × country site (3 keywords × 4 countries = 12 searches, up to 500 per run). A product found by several searches is saved — and charged — once. Set `maxItemsPerQuery` to give every search its own cap: without it the first searches can use up the whole `maxItems` budget. Several search URLs in `startUrls` work the same way.

#### Monitoring: new products and price changes

Tick **Only new products** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the products already delivered: they are not saved, not charged, and their page is not even opened. Tick **Also products whose price changed** too, and a product already delivered comes back when its price moved by at least **Min price change (%)** (3 % by default), with `changeType` = `price_drop` or `price_rise`, `previousPrice` and `priceChangePercent`. The memory lives in a named key-value store of your account (`mercadolibre-products-scraper-seen`, up to 150,000 products per key) and is only updated with products that really reached the dataset, so a failed run never hides anything. The price memory keeps the last 50,000 products per key (25,000 under 512 MB of run memory). Give each schedule its own `stateKey` (two schedules sharing a key would hide each other's products), and tick `resetState` once to start over. MercadoLibre has no "newest first" order: each run reads the whole search and keeps what is new.

#### Market statistics per search

Tick **Add market statistics per search**: the `MARKET_STATS` record of the run's key-value store gets one sheet per search — results announced, price minimum, median and quartiles, average discount, shares with free shipping, FULL, official store and interest-free installments, top sellers and brands, units sold — worked out from the products of the run (at least 10 per search). Brands come from the product page: tick **Full product details** too, or the brand list stays empty. Prices are in the currency of the search (the site's own; should a search carry two, the figures use the most frequent one and the others are counted apart).

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per MercadoLibre product. Actor id: `nice_dev/mercadolibre-products-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/mercadolibre-products-scraper`.

Smallest input, for a cheap first call:

```json
{
    "query": "notebook",
    "country": "mx",
    "maxItems": 10
}
```

Key output fields: `url`, `title`, `price`, `originalPrice`, `currency`, `soldCount`, `rating`, `sellerName`, `freeShipping`.

Cost: pay per event, each product at its price and each option on top, see the pricing section above; the options are all off by default. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

#### Is it legal to scrape MercadoLibre?

The Actor only reads what MercadoLibre shows publicly to any anonymous visitor. It logs in to nothing. Results can contain personal data (seller names, buyer reviews), which is protected by data protection laws such as the LGPD in Brazil or the GDPR: do not store it without a legitimate reason. You are responsible for using the data in compliance with MercadoLibre's Terms of Use and applicable law. This Actor is not affiliated with MercadoLibre.

#### Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting. A page the site turns away is retried at once in a new browser session with a new IP, up to 10 times on top of the retries; a page the site refuses on its own while the same session reads the others is given up after 3 sessions (without a proxy, after a pause of 5 seconds, doubled at each retry up to 150 seconds).

#### Which countries are covered?

The 18 MercadoLibre / Mercado Livre sites: Argentina (`ar`), Bolivia (`bo`), Brazil (`br`), Chile (`cl`), Colombia (`co`), Costa Rica (`cr`), Dominican Republic (`do`), Ecuador (`ec`), Guatemala (`gt`), Honduras (`hn`), Mexico (`mx`), Nicaragua (`ni`), Panama (`pa`), Peru (`pe`), Paraguay (`py`), El Salvador (`sv`), Uruguay (`uy`) and Venezuela (`ve`). Prices are in each country's currency, as a visitor of that country sees them.

#### Is the data safe to open in Excel or to show on a web page?

Titles, descriptions, reviews and answers are the sellers' and buyers' own words, copied as they are. A text can begin with `-`, `+`, `=` or `@` (a title such as `-20% hoy`): Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. On a web page, escape every field like any text written by a stranger.

#### Known limitations

- MercadoLibre prints no publication date for a product: there is no date filter and no "newest first" order. Use **Only new products** to get the products no earlier run delivered (with **Max products**, the next ones of the search, which may be older than the last run).
- A search with a **condition** (`new`, `used`, `refurbished`) gives about 2,000 results at most, with or without a price range: the site forgets the condition as soon as a price range is added, so the Actor does not split such a search by price and checks your `minPrice` / `maxPrice` on each product itself. To get more, paste a category page URL.
- `soldCount` and `availableQuantity` are the site's rounded labels (`+5 mil vendidos` = 5000): lower bounds, not exact counts.
- The product sheet, the seller's profile, reviews and questions come from the product page: they are empty unless their option is on.
- Two runs sharing the same `stateKey` at the same time may both return the same new product.

**A run that reaches its timeout** stops itself about 45 seconds before it: no new page is asked, what it read is saved and, with `onlyNew`, remembered, and the run ends *Succeeded* with "Stopped before the run's timeout". Resurrect it to go on from there, or give the next run a longer timeout (Run options).

**A run the platform stops without warning** (out of memory)

- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the products already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `onlyNew`, the memory is saved after each write (at most once every 2 seconds): resurrect the stopped run and the products it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the products of its last 2 seconds once more.

#### Something doesn't work?

The last line of the log counts the products saved, filtered out and no longer on MercadoLibre (removed while the run was reading them), and the requests that failed after every retry. Those requests and the removed products are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause (a search URL that does not exist says so, instead of "run it again").

If MercadoLibre changes its pages, you are told instead of paying for blank rows. A results page that counts products but gives none the Actor can read is an error (listed in `FAILED_REQUESTS`), never a quiet "No products found". If the first 20 products read all lack the same field among title, price, currency and photo (and, with **Full product details**, specifications, category path, seller name, seller link, payment methods and a second photo of the product page), the run saves nothing more, stops and fails, and its last message names the missing field: at most those first products are charged. A run of fewer products (a scheduled `onlyNew` run that finds a few new ones, a small **Max products**) is checked at its end, from 5 products: its products are already saved, and the run fails with the missing field instead of ending green.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which URLs failed and why.

# Actor input Schema

## `startUrls` (type: `array`):

MercadoLibre / Mercado Livre URLs of any of the 18 countries: search results (`https://listado.mercadolibre.com.mx/laptop`, every filter set on the site is kept), category pages, product pages (`/p/MLM…`, `/up/MLMU…`, `articulo.mercadolibre…/MLM-…-_JM`), official stores (`/tienda/<name>`, Brazil `/loja/<name>`), seller listings (`_CustId_<id>`), deals (`/ofertas`) and best sellers (`/mas-vendidos`, Brazil `/mais-vendidos`). The country is read from each URL. When this list is not empty, the keyword fields below are ignored; filters, caps and monitoring still apply. Max 1 000 URLs.

## `query` (type: `string`):

Free-text search, exactly as typed on the site (e.g. `notebook`, `iphone 15`).

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

Several keywords in one run: one search per keyword (times each country below). Added to **Search keyword**; products found by several searches are saved once.

## `productIds` (type: `array`):

Single products to read, by id: catalog product `MLB12345678`, seller product `MLMU1234567890` or listing `MLA1234567890` (also written `MLA-1234567890`). The 3 letters give the country (MLA Argentina, MLB Brazil, MLM Mexico, MLC Chile, MCO Colombia, MPE Peru, MLU Uruguay, MEC Ecuador, MLV Venezuela, MBO Bolivia, MPY Paraguay, MRD Dominican Republic, MCR Costa Rica, MPA Panama, MGT Guatemala, MHN Honduras, MSV El Salvador, MNI Nicaragua). Max 1 000.

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

MercadoLibre site the keywords are searched on. Prices come in its currency. URLs and ids keep their own country.

## `countries` (type: `array`):

Several country sites in one run, as the 2-letter codes of **Country site** (`mx`, `ar`, `co`…): every keyword is searched on every site (3 keywords × 4 countries = 12 searches, max 500). Added to **Country site**.

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

Maximum number of products to save for the whole run (after deduplication and filters). 0 = no limit.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH search (keyword × country, or search URL), so that the first search cannot use up the whole **Max products** budget. 0 = no per-search cap.

## `splitByPrice` (type: `boolean`):

MercadoLibre shows at most about 2,000 products per search. When a search has more, the Actor splits it into price ranges (each one under the limit) and reads them all, so a broad search returns everything. Off = the first 2,000 only. No extra charge. Not with **Condition**: the site drops the condition when a price range is added, so a search with a condition stays at about 2,000 results (paste a category URL to get more).

## `sortBy` (type: `string`):

Order of the search results, as on the site. The site has no 'newest' order: use **Only new products** below.

## `condition` (type: `string`):

Only new, used or refurbished products.

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

Only products from this price, in the currency of the country site (R$, MXN, ARS…).

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

Only products up to this price, in the currency of the country site. 0 = no maximum.

## `minDiscountPercent` (type: `integer`):

Only products whose price is reduced by at least this share (5 to 90 %), as the site filters it.

## `freeShippingOnly` (type: `boolean`):

Only products with free shipping. The site's own filter (Envío gratis); on Mercado Livre Brazil, where the site has no reliable one, the Actor checks each product instead (a product that does not show free shipping is left out).

## `fullShippingOnly` (type: `boolean`):

Site filter 'FULL': products stored and shipped by Mercado Libre's own warehouses (faster delivery).

## `officialStoresOnly` (type: `boolean`):

Site filter 'Official stores' (Tiendas oficiales / Lojas oficiais): brands and authorised resellers.

## `interestFreeOnly` (type: `boolean`):

Site filter 'Interest-free installments' (Meses sin intereses / Parcelamento sem juros).

## `bestSellersOnly` (type: `boolean`):

Site filter 'Best sellers' (MercadoLíder sellers: Mejores vendedores / Melhores vendedores).

## `includeSponsored` (type: `boolean`):

Keep the products the site shows as ads in the search results (`isSponsored` = true). Off = drop them.

## `extractDetails` (type: `boolean`):

Read each product's page: full description, all specifications, every photo, variations (color, size…) with price and stock, stock left, warranty, returns, payment methods, category path, other sellers of the same product (count and lowest price), and the seller's profile (MercadoLíder level, reputation, sales, followers, official store).

## `includeReviews` (type: `boolean`):

Add each product's buyer reviews (rating, text, date, buyer country, likes, photos) and the rating breakdown by star. Charged per review delivered.

## `maxReviewsPerProduct` (type: `integer`):

Reviews kept per product, in the order chosen in Reviews order.

## `reviewSort` (type: `string`):

Order the reviews are read in, as on the site: most helpful first, or newest first.

## `reviewMinRating` (type: `integer`):

Keep only the reviews with at least this many stars (1-5). Empty = all.

## `reviewMaxRating` (type: `integer`):

Keep only the reviews with at most this many stars, e.g. 2 for the complaints. Empty = all.

## `includeQuestions` (type: `boolean`):

Add the buyers' questions on each product with the seller's answer and its date. Charged per question delivered.

## `maxQuestionsPerProduct` (type: `integer`):

Questions kept per product, newest first. Read 40 at a time.

## `includeMarketStats` (type: `boolean`):

Adds one record, `MARKET_STATS`, to the run's key-value store (Output tab): one sheet per search, worked out from the products of this run — number of results the site announces, price minimum, median and quartiles, average discount, shares with free shipping / FULL / official store / interest-free installments, top sellers and brands, units sold. Brands are given by the product page only: without Full product details the brand list stays empty. A search needs at least 10 products delivered; products pasted by URL or id belong to no search. Charged per search delivered (event `market-stats`); unticked (default) = nothing.

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

Only products rated at least this (out of 5). Products without a rating are dropped.

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

Only products with at least this many units sold, as the site shows it ('+5 mil vendidos' counts as 5000).

## `excludeKeywords` (type: `array`):

Drop the products whose title contains one of these words (case and accents ignored).

## `onlyNew` (type: `boolean`):

Skip the products that a previous run (same **Memory key**) already delivered: they are not saved and not charged, and their page is not even opened. First run = everything is new.

## `includePriceChanges` (type: `boolean`):

With **Only new products**: also return the products already delivered whose price went up or down since the last row delivered (`changeType` = `price_drop` / `price_rise`, with `previousPrice` and `priceChangePercent`). Charged per price change delivered (event `price-change`).

## `minPriceChangePercent` (type: `number`):

With **Also products whose price changed**: a product comes back only if its price moved by at least this many percent.

## `stateKey` (type: `string`):

Name of the memory used by **Only new products**. Give each schedule / task its own key (e.g. `notebooks-br`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every product again. Untick it afterwards.

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

Keep the default: the Actor uses its own residential proxy of each country, included in the price (MercadoLibre turns away data-center IPs). Your own proxies: they must be residential and in the country of the site. The residential Apify proxy is not available in this Actor.

## `maxConcurrency` (type: `integer`):

Maximum number of pages read in parallel.

## `maxRequestsPerMinute` (type: `integer`):

Most pages read from the site in any 60 seconds, all of them counted: search pages, product pages, review and question pages. Lower it if the log shows the site turning requests away.

## `minRequestIntervalMs` (type: `integer`):

Smallest gap between two requests, in milliseconds. 0 = no gap.

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

Retries per request before it is marked as failed. A page the site turns away is also retried in a new browser session with a new IP, up to 10 times, without using up these retries; a page refused on its own while the session reads the others is given up after 3 sessions.

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

Include debug messages in the run log.

## Actor input object example

```json
{
  "startUrls": [],
  "query": "notebook",
  "searchQueries": [],
  "productIds": [],
  "country": "br",
  "countries": [],
  "maxItems": 100,
  "maxItemsPerQuery": 0,
  "splitByPrice": true,
  "sortBy": "relevance",
  "condition": "any",
  "freeShippingOnly": false,
  "fullShippingOnly": false,
  "officialStoresOnly": false,
  "interestFreeOnly": false,
  "bestSellersOnly": false,
  "includeSponsored": true,
  "extractDetails": false,
  "includeReviews": false,
  "maxReviewsPerProduct": 20,
  "reviewSort": "relevance",
  "includeQuestions": false,
  "maxQuestionsPerProduct": 40,
  "includeMarketStats": false,
  "excludeKeywords": [],
  "onlyNew": false,
  "includePriceChanges": false,
  "minPriceChangePercent": 3,
  "stateKey": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 4,
  "maxRequestsPerMinute": 60,
  "minRequestIntervalMs": 0,
  "maxRequestRetries": 5,
  "debugLog": false
}
```

# Actor output Schema

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

No description

## `marketStats` (type: `string`):

The MARKET_STATS record: one sheet per search. Written only with the option Add market statistics.

# 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 = {
    "query": "notebook",
    "country": "br",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/mercadolibre-products-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "query": "notebook",
    "country": "br",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/mercadolibre-products-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "query": "notebook",
  "country": "br",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/mercadolibre-products-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/mercadolibre-products-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/o6DVs4bmREGCjCRCU/builds/ffxwEvr6Y9tEjmo3g/openapi.json
