# MercadoLibre Seller Price Monitor – Competitor & Buy Box (`pricelatam/mercadolibre-seller-price-monitor`) Actor

Monitor MercadoLibre sellers, official stores and competitors: per catalog product, the seller's price, rank, gap to the cheapest competitor, MAP violations and price history. Official API, no proxies. Pay per row.

- **URL**: https://apify.com/pricelatam/mercadolibre-seller-price-monitor.md
- **Developed by:** [Miguel Pinzon](https://apify.com/pricelatam) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 seller offer results

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?

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

## MercadoLibre Seller Price Monitor

**MercadoLibre seller price monitor for brands, official stores, sellers and agencies.** Give it one or more sellers (your own store, your distributors or up to 10 competitors) and, for every MercadoLibre catalog product where they sell, it returns the seller's current price, who is cheapest right now (the price side of the **buy box**), how far the seller is above or below the best competitor, its rank among all offers, and whether anybody sells below your minimum advertised price (**MAP compliance**). It is **competitor price monitoring** without scraping or proxies: data comes from the official MercadoLibre API and from a shared **price history** database that grows with every run, so each row also tells you how the seller's price moved in the last 24 hours and 7 days. Works for any seller, including **official store** accounts, in Colombia, Mexico, Argentina, Brazil, Chile, Peru, Uruguay and Ecuador. You pay per row.

> Independent tool, not affiliated with MercadoLibre.

> Also by pricelatam: [MercadoLibre Price Tracker](https://apify.com/pricelatam/mercadolibre-price-tracker) (every product with its best price and full price history) and [MercadoLibre Price Drop Alerts & Watchlist](https://apify.com/pricelatam/mercadolibre-price-drop-alerts) (only the products whose price dropped).

### Who is it for?

- **An official store watching its distributors.** List the distributors as sellers, add your minimum prices in `mapPrices`, schedule it: every row where a distributor (or anybody else) sells below MAP is flagged with the offending listing.
- **A seller watching 3 competitors.** List yourself and them; filter rows with `status: "above"` to see where you are losing on price and by how much (`priceGapPct`).
- **An agency reporting to several brands.** One run per brand with its stores and price lists, exported to Google Sheets or Excel from the dataset.

### What does it return?

One row per **seller × catalog product**:

| Field | Meaning |
|---|---|
| `sellerId`, `sellerNickname`, `sellerPermalink` | The monitored seller. |
| `productId`, `name`, `domainId`, `siteId`, `url`, `thumbnail` | The catalog product (/p/ page). |
| `currency` | Currency of every price in the row. |
| `sellerPrice`, `sellerItemId`, `sellerCondition`, `sellerListingType`, `sellerFreeShipping` | The seller's cheapest offer in the chosen `condition`. |
| `bestCompetitorPrice`, `bestCompetitorSellerId`, `bestCompetitorNickname`, `bestCompetitorItemId` | The cheapest offer of any other seller. |
| `priceGapPct` | (seller − best competitor) / best competitor × 100. **Positive = the seller is more expensive.** |
| `rank` | 1 = cheapest. Competitor offers strictly cheaper than the seller + 1; ties share the rank. |
| `offersCount` | Offers of all sellers in the chosen condition. |
| `status` | `cheapest`, `tied`, `above`, `only_seller`, `no_offer` (the product is in our history for this seller, or in your list, but the seller has no active offer now), `seller_not_found`. |
| `mapPrice`, `sellerBelowMap`, `competitorsBelowMap[]` | MAP checks, when you pass `mapPrices`: each violation with `sellerId`, `nickname`, `itemId`, `price`. |
| `sellerPriceChange24h`, `sellerPriceChange7d` | Change of the seller's listing price vs 24 h / 7 days earlier. `null` (never 0) when that listing has no recorded price that old. |
| `sellerLowestSeen`, `sellerLowestSeenAt`, `sellerObservations`, `firstSeenAt`, `lastSeenAt` | History of the seller's listing in the shared database. |
| `offers[]` | Only with `includeCompetitorOffers`: every offer of the product, cheapest first, flagged `isMonitoredSeller`. |
| `message` | Only on `seller_not_found` rows: what went wrong and what to provide. |
| `scrapedAt` | When the offers were read (UTC). |

**About the buy box:** MercadoLibre does not expose its buy box winner to API applications (`buy_box_winner` comes back empty), and the winner also depends on reputation and shipping. This Actor reports the price position, which is what you can act on: `cheapest` means no other seller is cheaper in that condition.

### Which products are monitored?

For each seller, up to `maxProductsPerSeller` catalog products, in this order:

1. your `discoveryProducts` and the products of `mapPrices` (a MAP is always checked);
2. results of your `queries` where the seller has an offer;
3. products where our shared history has an active offer of the seller, most recently seen first.

With `refreshLive` on (default), every product is read live and the observation is added to the shared history, so the next run (yours or anybody's) has more history. With it off, the answer comes only from the stored history: faster and with fewer API calls, but prices are as of the last time somebody checked the product (`scrapedAt`).

### How do I get a seller ID?

1. Open any listing (publication) of the seller on MercadoLibre.
2. In the seller box on the right, under the seller's name and reputation, click **"Ver más productos del vendedor"** (Mercado Livre: *"Ver mais produtos do vendedor"*).
3. The page that opens lists the seller's products, and its address contains `_CustId_` followed by digits, for example `https://listado.mercadolibre.com.co/_CustId_2923575120`. Those digits are the seller ID. You can paste the whole link: the Actor extracts the ID.

A profile link (`https://www.mercadolibre.com.co/perfil/NICKNAME`) or the bare nickname also works when the seller is already in our database or sells on one of your `discoveryProducts` / `queries` products. If a seller cannot be found, the run does not fail: you get a `seller_not_found` row saying what to add, and it is not charged.

### Input examples

**One seller**, the products we already know for it:

```json
{
  "country": "MCO",
  "sellers": ["2923575120"],
  "maxProductsPerSeller": 20
}
```

**A seller and 3 competitors** on the products you compete on:

```json
{
  "country": "MCO",
  "sellers": [
    "https://listado.mercadolibre.com.co/_CustId_2923575120",
    "SQUAREDEALSCOF",
    "https://www.mercadolibre.com.co/perfil/REDPHONEMOBILE",
    "3834040324"
  ],
  "queries": ["ipad 11 256gb"],
  "discoveryProducts": ["MCO50912377", "https://www.mercadolibre.com.co/apple-ipad-11/p/MCO52110181"],
  "condition": "new",
  "maxProductsPerSeller": 30
}
```

**An official store with minimum advertised prices** (MAP compliance across all sellers):

```json
{
  "country": "MCO",
  "sellers": ["2923575120", "3246949102"],
  "discoveryProducts": ["MCO50912377", "MCO52110181", "MCO48936856"],
  "mapPrices": { "MCO50912377": 2030000, "MCO52110181": 1550000, "MCO48936856": 1550000 },
  "includeCompetitorOffers": true
}
```

#### Input fields

| Field | Default | Description |
|---|---|---|
| `sellers` | – (required) | 1–10 sellers: numeric ID, link with `_CustId_<id>`, `/perfil/<nickname>` link or nickname. |
| `country` | `MCO` | MCO, MLM, MLA, MLB, MLC, MPE, MLU or MEC. |
| `discoveryProducts` | – | Product IDs or `/p/` URLs, monitored for every seller and used to find sellers by nickname. |
| `queries` | – | Search keywords; the category is detected automatically. |
| `maxProductsPerSeller` | 50 | 1–500. |
| `refreshLive` | `true` | Read live prices (and record them) or answer from the stored history only. |
| `condition` | `new` | `new`, `used` or `any`: used for rank, best competitor and MAP. |
| `mapPrices` | – | `{ "MCO12345": 199900 }`, local currency. These products are always monitored for every seller. |
| `includeCompetitorOffers` | `false` | Attach every offer to each row. |

### Output example

A real row (13 Nov 2026, run with `mapPrices: {"MCO50912377": 2030000}`):

```json
{
  "sellerId": "2923575120",
  "sellerNickname": "UNIVERSOELECTRONICOCOF",
  "sellerPermalink": "http://perfil.mercadolibre.com.co/UNIVERSOELECTRONICOCOF",
  "productId": "MCO50912377",
  "name": "Apple iPad 11 con chip A16, WiFi de 256 GB",
  "domainId": "MCO-TABLETS",
  "siteId": "MCO",
  "url": "https://www.mercadolibre.com.co/p/MCO50912377",
  "thumbnail": "https://http2.mlstatic.com/D_NQ_NP_780662-MLA96101840367_102025-F.jpg",
  "currency": "COP",
  "sellerPrice": 2036978,
  "sellerItemId": "MCO4125062572",
  "sellerCondition": "new",
  "sellerListingType": "gold_pro",
  "sellerFreeShipping": true,
  "bestCompetitorPrice": 2027248,
  "bestCompetitorSellerId": "3246949102",
  "bestCompetitorNickname": "SQUAREDEALSCOF",
  "bestCompetitorItemId": "MCO4059748102",
  "priceGapPct": 0.48,
  "rank": 2,
  "offersCount": 4,
  "status": "above",
  "mapPrice": 2030000,
  "sellerBelowMap": false,
  "competitorsBelowMap": [
    { "sellerId": "3246949102", "nickname": "SQUAREDEALSCOF", "itemId": "MCO4059748102", "price": 2027248 }
  ],
  "sellerPriceChange24h": 12897,
  "sellerPriceChange7d": null,
  "sellerLowestSeen": 2024081,
  "sellerLowestSeenAt": "2026-11-12T03:58:07.483398Z",
  "sellerObservations": 5,
  "firstSeenAt": "2026-11-12T03:58:07.483398Z",
  "lastSeenAt": "2026-11-13T20:27:07.486158Z",
  "scrapedAt": "2026-11-13T20:27:07.486158Z"
}
```

The seller is 0.48 % above SQUAREDEALSCOF, which sells below the 2,030,000 MAP; the seller raised its price by 12,897 in the last 24 hours. `sellerPriceChange7d` is null because the listing was first recorded the day before.

### Schedule it every 6 hours with email or Slack alerts

1. Save your input as a **task** in Apify Console.
2. *Schedules* → *Create new* → pick the task, cron `0 */6 * * *` ([docs](https://docs.apify.com/platform/schedules)).
3. On the task, *Integrations*: **email** on run succeeded with a link to the dataset, **Slack** to post to a channel ([docs](https://docs.apify.com/platform/integrations/slack)), or a **webhook** to Zapier, Make, n8n or your backend; the payload carries `defaultDatasetId` ([docs](https://docs.apify.com/platform/integrations/webhooks)).
4. Filter the dataset by `status = above` (losing on price) or `sellerBelowMap = true` / non-empty `competitorsBelowMap` (MAP violations).

Each scheduled run also feeds the shared history, so the 24 h / 7 d changes become available after the first day.

### How much does it cost?

Pay per event, no subscription. Platform usage is included.

| Event | Price |
|---|---|
| `seller-offer-result`: every seller × product row (`no_offer` rows included) | $0.003 |
| `map-violation`: extra per row where the seller or a competitor is below your MAP (only when you pass `mapPrices`) | $0.002 |
| Actor start (charged by Apify on every run) | $0.00005 |

Example: 50 products checked 4 times a day for 30 days = 6,000 rows = **$18 per month**, a fraction of a SaaS price monitor. `seller_not_found` rows are free. Set a maximum cost per run in the run options; the Actor stops cleanly when it is reached.

### Use it from AI agents (Apify MCP server)

The Actor is available as a tool through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp), so Claude, Cursor, VS Code or any MCP client can query it:

```json
{
  "mcpServers": {
    "mercadolibre-seller-price-monitor": {
      "url": "https://mcp.apify.com?tools=pricelatam/mercadolibre-seller-price-monitor"
    }
  }
}
```

If your client does not support OAuth, send your token instead with `"headers": { "Authorization": "Bearer <YOUR_APIFY_TOKEN>" }`.

Then ask, for example: *"¿Quién está vendiendo por debajo de mi precio mínimo el producto MCO50912377 en Colombia? Mi precio mínimo es 2.030.000 COP y mi tienda es 2923575120."* ("Who is selling product X below my minimum price in Colombia?")

From code: `pip install apify-client`, then `client.actor("pricelatam/mercadolibre-seller-price-monitor").call(run_input={...})` and iterate the default dataset.

### Limits

- **Catalog products only.** The API with an application token lists offers per catalog product (`/p/` pages). Listings outside the catalog (plain publications without a /p/ page) do not appear, and the seller's full listing search is not available to applications.
- A nickname is found only if the seller is already in our database or sells on one of your `discoveryProducts` / `queries` products; a numeric ID always works.
- Prices are item prices without shipping; `sellerFreeShipping` and the offers list tell you whether shipping is free.
- The 24 h / 7 d changes need history of that same listing; a new listing starts with `null`.
- Up to 10 sellers and 500 products per seller per run.

### FAQ

**Is the "buy box" the real one?**
It is the price position. MercadoLibre's buy box winner is not available to API applications and also weighs reputation and shipping; `cheapest` means nobody else is cheaper in the chosen condition.

**Why does a seller show `no_offer`?**
The product is in your `discoveryProducts`, or our history had an active offer of the seller there, but the seller has no active offer now. `sellerItemId` and `lastSeenAt` show its last listing and when it was last seen.

**Are other users' runs mixed with mine?**
Only the price history is shared (that is what makes the 24 h / 7 d changes and the lowest prices available from the first run). Your input, your MAP list and your dataset are private to your account.

**Something does not work. Where do I report it?**
Open an issue in the Actor's **Issues** tab with the run ID and the input you used.

### Independence notice

This Actor is an independent tool. It is not affiliated with, endorsed by or sponsored by MercadoLibre. "MercadoLibre" and "Mercado Livre" are trademarks of their owners and are used only to describe the data source. Prices are the ones published through the official MercadoLibre API at the time of each run.

***

### En español

**MercadoLibre Seller Price Monitor** vigila uno o varios vendedores de MercadoLibre (tu tienda oficial, tus distribuidores o hasta 10 competidores) en 8 países y, por cada ficha de catálogo donde venden, devuelve el precio del vendedor, quién es el más barato (el lado de precio del *buy box*), la diferencia porcentual con el mejor competidor, su posición entre todas las ofertas y quién vende por debajo de tu precio mínimo autorizado (MAP). Usa la API oficial y la historia de precios compartida, así que cada fila trae también el cambio del precio del vendedor en 24 h y 7 días. El id del vendedor está en el enlace "Ver más productos del vendedor" de cualquier publicación (`_CustId_<id>`). Se cobra $0.003 por fila y $0.002 adicionales por fila con violación de MAP. Herramienta independiente, sin relación con MercadoLibre.

# Actor input Schema

## `sellers` (type: `array`):

1 to 10 sellers, one per line. Each line can be: the numeric seller ID (e.g. 2923575120); any link containing *CustId*<id> (open one of the seller's listings and click 'Ver más productos del vendedor' / 'Ver mais produtos do vendedor': that link contains *CustId* followed by the ID); a profile link such as https://www.mercadolibre.com.co/perfil/NICKNAME; or the bare nickname. A numeric ID always works; a nickname is found among the sellers we already know or in the offers of 'Products where the seller appears'. The prefilled example, 2923575120 (UNIVERSOELECTRONICOCOF), was the Colombian seller with the most active catalog offers in our shared history on 13 Nov 2026.

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

MercadoLibre site of the sellers, the search keywords and the products found in our history. Brazil is Mercado Livre.

## `maxProductsPerSeller` (type: `integer`):

Upper limit of catalog products reported per seller: your 'Products where the seller appears' and the products of mapPrices first, then keyword results where the seller sells, then the products where our shared history has an active offer of the seller (most recently seen first).

## `discoveryProducts` (type: `array`):

Catalog product IDs (MCO12345) or product URLs (…/p/MCO12345) to monitor for every seller. They are also used to find sellers given by nickname: every seller with an offer on these products is checked. A seller without an offer on one of them gets a 'no_offer' row for it.

## `queries` (type: `array`):

Searches such as 'ipad 11 256gb'. The category is detected automatically; the catalog products found are added for each seller that has an offer on them, and their sellers are checked when resolving nicknames.

## `refreshLive` (type: `boolean`):

On: every product's offers are read from MercadoLibre now and recorded in the shared price history. Off: the answer comes only from our stored history (faster, but prices are as of the last time anybody checked the product; see scrapedAt).

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

Condition used for the rank, the best competitor and MAP checks. The shared price history always stores every offer.

## `mapPrices` (type: `object`):

Minimum authorized price per catalog product, in its local currency, e.g. {"MCO50912377": 2000000}. Every offer of the chosen condition below it is flagged, the monitored seller's own (sellerBelowMap) and competitors' (competitorsBelowMap). These products are always monitored for every seller, like 'Products where the seller appears'.

## `includeCompetitorOffers` (type: `boolean`):

Attach all offers of the product (seller, nickname when known, price, condition, shipping) to each row.

## Actor input object example

```json
{
  "sellers": [
    "2923575120"
  ],
  "country": "MCO",
  "maxProductsPerSeller": 20,
  "refreshLive": true,
  "condition": "new",
  "includeCompetitorOffers": false
}
```

# Actor output Schema

## `sellerOffers` (type: `string`):

All items of the run's default dataset: the seller's price, rank and gap to the cheapest competitor, MAP checks and price history per product.

# 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 = {
    "sellers": [
        "2923575120"
    ],
    "maxProductsPerSeller": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("pricelatam/mercadolibre-seller-price-monitor").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 = {
    "sellers": ["2923575120"],
    "maxProductsPerSeller": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("pricelatam/mercadolibre-seller-price-monitor").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 '{
  "sellers": [
    "2923575120"
  ],
  "maxProductsPerSeller": 20
}' |
apify call pricelatam/mercadolibre-seller-price-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pricelatam/mercadolibre-seller-price-monitor"
        }
    }
}
```

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/aCzTgwUpR0hN0rby1/builds/DRwhMssOD96asHvs0/openapi.json
