# Mercado Libre Deals & Best Sellers Scraper (`dami_studio/mercadolibre-scraper`) Actor

Mercado Libre's deals and best-seller lists as rows, in nine countries: price, previous price and discount, instalments, free shipping and Full, seller or brand, rating, sold count, link and photo. Filter deals by category, deal type, price, instalments and shipping. Not a keyword search.

- **URL**: https://apify.com/dami\_studio/mercadolibre-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** E-commerce, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.75 / 1,000 listing returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Mercado Libre Deals & Best Sellers Scraper

Mercado Libre's deals page and its best-seller lists, one row per listing. Pick a country and you get each deal's price, the price it had before, the discount, instalments, shipping, the seller or brand on the card, its rating and Mercado Libre's sold count, with the link and the photo.

**It is not a search scraper.** There's no keyword box. It reads two pages every Mercado Libre site has: Ofertas, the deals page, and Más vendidos, the best-seller lists. If you need the results of a search such as "iphone 15", this won't give you that.

Nine sites: Argentina, Brazil, Mexico, Chile, Colombia, Peru, Uruguay, Ecuador and Venezuela. Venezuela has no best-sellers page, so it's deals only there. Bolivia, Paraguay, the Dominican Republic and the Central American sites have no deals page at all.

### What it reads

**Deals (Ofertas).** 48 deals a page, in the order Mercado Libre shows them. You can narrow them with the filters the deals page itself has:

- a top-level category, like `MLA1051` for Celulares y Teléfonos in Argentina;
- the deal type: lightning deals (Ofertas relámpago) or the deal of the day;
- a price range;
- instalments: payable in instalments, interest-free, best price in instalments, or promoted instalments;
- free shipping;
- Full, Mercado Libre's own shipping service.

The deals page stops at about 1,048 deals for any one set of filters, even when it counts many more. Argentina's counted 11,285 on 13 September 2026. The run's status says when you reach that point, and a category or a price band gets you to the others.

**Best sellers (Más vendidos).** The lists on that page: up to 20 products for each category Mercado Libre puts there, usually six to ten categories. On 13 September 2026 Argentina's page had 103 products in six lists and Brazil's 154 in ten. The page takes no filters. A category ID keeps only that category's list, if the page has one.

### What it doesn't do

- No keyword search. No sorting either: the deals page has none, so rows come in Mercado Libre's order.
- No seller ID, seller reputation, item condition or location. These cards don't show them. `seller` is the name on the card, which is often a brand or its official store.
- The sold count is Mercado Libre's rounded label, like "+10mil vendidos". `soldAtLeast` turns it into 10000. It's a floor, not a count.
- Best-seller rows carry less than deals: price, previous price, discount, free shipping, Full and rank. No rating, sold count or seller, because that page doesn't show them.
- Prices are what the page showed when the run read it. Lightning deals often end within hours, and `dealEndsAt` says when.

### Input

```json
{
  "country": "AR",
  "sources": ["deals"],
  "category": "MLA1051",
  "maxPrice": 500000,
  "freeShipping": true,
  "maxItems": 200
}
```

- **Country.** Which site to read.
- **What to read.** `deals`, `bestSellers` or both. Empty means deals.
- **Category ID.** Open the deals page in your browser, pick a category on the left, and the address bar shows `category=MLA1051` or similar. It has to belong to the country you picked.
- **Deal type, Minimum price, Maximum price, Instalments, Free shipping only, Full only.** Deals only. Prices are in the site's own currency.
- **Maximum pages.** Deals pages, 48 deals each, 22 at most.
- **Maximum listings.** 1,000 unless you change it, and up to 2,000. Deals and best sellers count together.

If the deals page doesn't recognise a filter value, it quietly shows every deal instead. The actor checks that the page applied each filter you set. If it didn't, you get nothing, you're not charged, and the status names the filter.

### Output

One row per listing.

| Field | Example | Notes |
|---|---|---|
| `source` | `deals` | `deals` or `bestSellers` |
| `country`, `siteId` | `AR`, `MLA` | |
| `itemId` | `MLA1673496959` | the listing; on best sellers only when the page links a listing |
| `productId` | `MLA36781598` | Mercado Libre's catalog product, when there is one |
| `userProductId` | `MLAU370227959` | when the page gives one |
| `title` | `Hidrolavadora Electrica Alta Presion Profesional Trent 2000w…` | |
| `price`, `currency` | `170991`, `ARS` | |
| `originalPrice` | `344139.01` | the crossed-out price |
| `discountPercent` | `50` | as the card shows it |
| `installmentsCount`, `installmentAmount`, `installmentsInterestFree` | `6`, `38470`, `false` | deals only |
| `freeShipping` | `true` | |
| `fullFulfillment` | `true` | shipped by Full |
| `shippingText` | `Llega gratis mañana` | deals only |
| `seller`, `officialStore` | `TRENT`, `true` | deals only |
| `rating` | `4.8` | deals only |
| `soldText`, `soldAtLeast` | `+10mil vendidos`, `10000` | deals only |
| `promotion` | `deal_of_the_day` | `lightning`, `deal_of_the_day` or empty |
| `highlight` | `OFERTA DEL DÍA` | the label on the card |
| `dealEndsAt` | `2026-09-13T14:59:59Z` | lightning deals |
| `bestSellerRank` | `1` | best sellers only |
| `categoryId`, `categoryName` | `MLA1051`, `Celulares y Teléfonos` | the category you filtered on, or the best-seller list |
| `leafCategoryId` | `MLA3697` | best sellers only |
| `position`, `page` | `1`, `1` | place on the deals page, or the rank |
| `url` | `https://www.mercadolibre.com.ar/…/p/MLA36781598` | |
| `thumbnail` | `https://http2.mlstatic.com/D_Q_NP_2X_…-AB.webp` | |
| `scrapedAt` | `2026-09-13T14:44:33.000Z` | when the run started |

The run also leaves a report, `RUN_REPORT`, in its key-value store: the filters the page applied, the pages read, how many deals the page counted, rows skipped and why, and why the run stopped.

### What you pay

Each listing in your dataset is one charge. Nothing else costs anything: not the sample row you get with an empty input, not a deal that didn't match your filters, not a listing shown twice, and not a page that couldn't be read. If you set a maximum charge for the run, it stops when that's reached. The price is on the Pricing tab.

### Limits

- One country per run. Up to 2,000 listings and 22 deals pages.
- It reads about one page every two seconds, so a full deals run takes about a minute.
- When Mercado Libre doesn't serve a page, the status says so and nothing is charged for it.

### Where the data comes from

Public pages on Mercado Libre's own sites. Mercado Libre's terms of use restrict automated collection and reuse of its content, so check them against what you plan to do with the data.

### Questions

**How do I get only phones on sale in Brazil?** Country `BR`, category `MLB1051`.

**Why do I get fewer deals than the page counts?** The deals page stops at about 1,048 for one set of filters. Split the run by category or by price band.

**Can I get the lightning deals every morning?** Schedule the actor with Deal type set to lightning deals. Each run returns the ones on the page at that moment.

**Can I search for a product?** No. Mercado Libre's search results aren't part of this.

# Actor input Schema

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

Which Mercado Libre site to read. The other Latin American sites have no deals page.

## `sources` (type: `array`):

Deals are the site's Ofertas page, 48 a page. Best sellers are the lists on its Más vendidos page, up to 20 per category, picked by Mercado Libre. Leave it empty for deals only.

## `category` (type: `string`):

A top-level category, such as MLA1051 (Celulares y Teléfonos in Argentina) or MLB1051 in Brazil. Deals are then only that category's. For best sellers it keeps only that category's list, if the page shows one.

## `promotionType` (type: `string`):

Leave it empty for every kind of deal.

## `minPrice` (type: `integer`):

In the site's own currency, for example 10000 for 10,000 Argentine pesos. Deals only.

## `maxPrice` (type: `integer`):

In the site's own currency. Deals only.

## `installments` (type: `string`):

The instalment options the deals page offers. Leave it empty for any. Deals only.

## `freeShipping` (type: `boolean`):

Only deals that show free shipping. Deals only.

## `fullOnly` (type: `boolean`):

Only deals shipped by Mercado Libre's Full service. Deals only.

## `maxPages` (type: `integer`):

Deals pages to read, 48 deals each. The deals page goes no further than page 22, about 1,048 deals for one set of filters.

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

The most listings returned in one run, deals and best sellers together. Each listing returned is one charge.

## Actor input object example

```json
{
  "country": "AR",
  "sources": [
    "deals"
  ],
  "maxPages": 22,
  "maxItems": 48
}
```

# Actor output Schema

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

One row per listing found by your search.

## `report` (type: `string`):

What each search found and returned, and why the run stopped.

# 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 = {
    "country": "AR",
    "sources": [
        "deals"
    ],
    "maxItems": 48
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/mercadolibre-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 = {
    "country": "AR",
    "sources": ["deals"],
    "maxItems": 48,
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/mercadolibre-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 '{
  "country": "AR",
  "sources": [
    "deals"
  ],
  "maxItems": 48
}' |
apify call dami_studio/mercadolibre-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/mercadolibre-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/lBx88nN6y6Si2wbEV/builds/Dj9fPraZibHEL9fV5/openapi.json
