# Mercado Livre Offers Scraper · Price & store filters · $2.5/1K (`mlg14/mercado-scraper`) Actor

Get Mercado Livre Brazil offers and search results for price monitoring, deal tracking and competitor research. Price, official-store, condition and sort filters applied by the site. Returns price, discount, seller, rating and shipping. Keyword or offers URL. $2.5/1K offers.

- **URL**: https://apify.com/mlg14/mercado-scraper.md
- **Developed by:** [MLG Data](https://apify.com/mlg14) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.50 / 1,000 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

## Mercado Livre Offers Scraper

Scrape Mercado Livre Brazil offer listings and export prices, discounts, product links, seller labels, ratings, and shipping signals to JSON or CSV. This scraper is an API alternative for the public offers catalog: it reads what the offer cards display and gives each visible product a structured row.

The scope is precise. Individual product pages present verification challenges, while public offers pages and marketplace search pages (lista.mercadolivre.com.br) return product cards. Enter keywords for a marketplace search, or an offers URL, and narrow the results by price, official store, condition and sort order. These filters are applied by Mercado Livre itself, so each page already contains matching products and the actor keeps reading pages until Maximum offers is reached.

### What data can you extract from Mercado Livre?

Each result is one offer card from the Brazilian offers section. Prices use Brazilian reais and are not converted. Values such as seller, installments, and discounts are present only when the card displays them.

| Field | Description | Example |
| --- | --- | --- |
| id | Stable row key: seller offer ID when visible, otherwise catalog product ID. | MLB6647645240 |
| itemId | Seller-specific offer identifier from the card link, when present. | MLB6647645240 |
| catalogProductId | Catalog product identifier from the card link, when present. | MLB23873195 |
| siteId | Marketplace identifier for Brazil. | MLB |
| title | Product title displayed on the card. | Travesseiro Viscoelástico Borboleta Cervical Sono Profundo Cinza |
| permalink | Original card link, including offer selection information when supplied. | Product URL |
| canonicalUrl | Product page URL with query and fragment removed. | Product URL |
| price | Current displayed offer price. | 135.2 |
| currency | Price currency. | BRL |
| originalPrice | Previous price, if the card strikes one through. | 299 |
| discountPercent | Percentage discount printed on the card. | 54 |
| installments | Visible installment count, per-payment amount, and interest-free flag. | {"quantity":10,"amount":114.9,"interestFree":true} |
| thumbnailUrl | Main card image URL. | Image URL |
| officialStore | True when the card shows the Loja oficial badge (flat copy of seller.isOfficialStore). | true |
| seller | Visible seller name and official-store badge. | {"name":"Example seller","isOfficialStore":false} |
| freeShipping | Whether the card advertises free shipping. | true |
| fullShipping | Whether the card visibly advertises Full shipping. | false |
| ratingAverage | Star rating printed on the card. | 4.7 |
| soldQuantity | Displayed sold count, often a rounded lower bound such as “+1000 vendidos.” | 1000 |
| dealLabel | Promotion badge from the card. | OFERTA DO DIA |
| sourceUrl | Offers page where the card was collected. | https://www.mercadolivre.com.br/ofertas |
| scrapedAt | UTC time the row was extracted. | ISO 8601 timestamp |

The seller and installments values are small objects so their related values stay together. A missing badge or label is returned as null, rather than guessed from another page. The shipping fields record what the card advertises, not a final delivery quote for a specific postal code. A catalog product can have multiple seller offers; itemId and catalogProductId remain separate for that reason. The original permalink can carry an offer ID and tracking information. Use canonicalUrl when you need a clean product URL, and keep itemId for matching a seller-specific offer.

### How to scrape Mercado Livre offers

1. Open the public Brazil offers section and copy its URL. A category filtered offers URL also works. Paste one or more URLs into Offers URLs.
2. Optionally enter Keywords. Each keyword runs a marketplace search. Pages are read until Maximum offers is reached, within the page cap (default 10 per URL or keyword).
3. Set Maximum offers to cap the number of dataset rows. Add a minimum or maximum price, an official-store requirement, a condition (new or used) or a sort order; Mercado Livre applies them before the results are returned.
4. Run the scraper. It opens the filtered search or offers pages, removes duplicate offer IDs, and writes rows to the dataset until the cap is reached.
5. Download the dataset as JSON or CSV, or read it through the platform API. Schedule another run when you need a fresh price snapshot.

A category filter belongs in the URL, for example https://www.mercadolivre.com.br/ofertas?category=MLB1055. The category identifier is supplied by Mercado Livre's own offers navigation. The actor accepts public www.mercadolivre.com.br/ofertas URLs and lista.mercadolivre.com.br search or category URLs. Product, account, and checkout URLs are outside the supported input scope.

### Input

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| startUrls | URL list | General offers page | Public Brazil offers URLs (category filtered ones work) or lista.mercadolivre.com.br search/category URLs. Offers URLs are skipped when Keywords are set. |
| searchQueries | String list | Empty | Search terms. Each runs a real marketplace search on Mercado Livre with the filters below applied by the site. |
| priceMin | Number | Unset | Minimum price in BRL, applied by Mercado Livre. |
| priceMax | Number | Unset | Maximum price in BRL, applied by Mercado Livre. |
| officialStoresOnly | Boolean | false | Only official-store (Loja oficial) products, applied by Mercado Livre. |
| condition | String | any | any, new or used (keyword and search URLs). |
| sort | String | relevance | relevance, price_asc or price_desc. Keyword and search URLs are sorted by the site across all results; offers pages are sorted among the crawled pages. |
| maxItems | Integer | 40 | Maximum rows emitted. Pages are read until this many rows are collected. Zero means no row cap within the page limit. |
| maxPagesPerQuery | Integer | 10 | Safety cap on pages per URL or keyword (offers max 21, search max 42). Reading stops once maxItems is reached. |
| proxyConfiguration | Object | Automatic | Mercado Livre only opens for a Brazilian residential IP, so the actor uses Apify Residential proxies (country BR) unless you provide your own. |

For a compact category sample, use:

```json
{
  "startUrls": [
    {"url": "https://www.mercadolivre.com.br/ofertas?category=MLB1055"}
  ],
  "maxPagesPerQuery": 1,
  "maxItems": 30,
  "priceMin": 100,
  "sort": "price_asc"
}
```

For a broad snapshot, leave searchQueries empty and start at the general offers page. If you add a phrase such as "travesseiro cervical", the actor runs a marketplace search for it and the site applies the price, official-store, condition and sort filters before returning each page.

On keyword and search URLs the site sorts across all results. On offers pages sorting is local to the crawled pages, which is not a site-wide price sort. For example, “lowest price first” on three offers pages orders only the products found on those three pages. Increase maxPagesPerQuery to widen the comparison set, subject to the offers section's limit. Combining many URLs can increase the number of unique offers, and duplicate id values are emitted once.

### Output example

The following selected fields come from a successful run on the general offers page. The run returned 40 rows from one page. Longer URLs and optional fields are omitted here for readability; the dataset contains the complete row.

```json
{
  "id": "MLB6647645240",
  "itemId": "MLB6647645240",
  "catalogProductId": null,
  "siteId": "MLB",
  "title": "Travesseiro Viscoelástico Borboleta Cervical Sono Profundo Cinza",
  "price": 135.2,
  "currency": "BRL",
  "originalPrice": 299,
  "discountPercent": 54,
  "installments": null,
  "seller": null,
  "freeShipping": false,
  "fullShipping": false,
  "ratingAverage": 4.7,
  "soldQuantity": 1000,
  "dealLabel": "OFERTA DO DIA",
  "sourceUrl": "https://www.mercadolivre.com.br/ofertas"
}
```

This example also shows why an empty field is meaningful. The card supplied a product ID, a discount, a rating, and a sales label, but did not show a seller name or installment terms. The actor leaves those values empty instead of opening a protected detail page and risking an unrelated seller result. Sold counts are approximate when the page displays a plus sign; 1000 represents the displayed “more than 1000” threshold, not an exact total.

### Use cases

- Retail price checks: collect an offers snapshot each morning, compare current and previous prices, and flag large changes. Keep currency with the numeric price so downstream comparisons remain in BRL.
- Promotion analysis: use originalPrice, discountPercent, and dealLabel to compare advertised discounts. A missing former price means the card did not show a comparable strikethrough value.
- Category monitoring: run a category filtered offers URL on a schedule and record which products enter or leave the visible offer set. Store itemId alongside the title because titles can change.
- Seller visibility: compare products with a visible official-store badge against other cards. This is a card-level signal and does not replace a seller profile lookup.
- Shipping coverage: measure how many visible offers advertise free or Full shipping in a category. The actual checkout offer may depend on location and account context.
- Catalog matching: use catalogProductId to group cards that link to the same catalog page, while retaining itemId to distinguish seller offers where the card exposes it.

### How much does it cost to scrape Mercado Livre?

The configured result price is **$0.0016 per dataset row**, or **$1.60 per 1,000 rows**. The row cap controls the maximum number of result events; pages that contain no matching offers do not add result events. Platform processing and proxy usage are handled by the actor. The number of available cards, filters, and page limits determine how many rows a run can actually return.

| Rows delivered | Result charge |
| ---: | ---: |
| 40 | $0.064 |
| 250 | $0.40 |
| 500 | $0.80 |
| 1,000 | $1.60 |

These are arithmetic examples, not promises that a particular category contains that many distinct visible offers. A small category can end after one page. A narrow keyword may return only a handful of cards even when the actor scans the full selected page range. Set maxItems to your intended upper bound, then inspect the row count and field coverage from a small sample before scheduling larger runs.

### Tips for best results

Start with one offers URL and one page. Confirm that the category is the one you intended and that the visible card fields fit your analysis. The public general offers page returned 48 product cards in probing; a category filtered page returned 32 cards, so page size depends on the route and available inventory. The golden run capped the general page at 40 rows and filled id, title, permalink, price, currency, and thumbnailUrl on every row. A seller name appeared on 85% of those rows. Field coverage can change as the site changes its cards.

For a keyword study, increase the page limit before concluding that a product is absent. Keywords are searched by Mercado Livre itself, so relevance, synonyms and stemming follow the site's own search. Pasting a category search URL narrows the source further.

For price comparisons, keep the exact run date and sourceUrl. Offers change rapidly, so a later run can show a different price or a missing card. The scrapedAt field records extraction time in UTC. OriginalPrice is the displayed former price, and discountPercent is the displayed label. Small differences between a calculated percentage and the displayed label may come from site rounding or offer presentation.

If several category URLs overlap, the actor deduplicates by id. A seller offer identifier is preferred; where it is not visible, the catalog product ID becomes the row key. That fallback may combine cards that point to one catalog product but represent different sellers. When seller-level precision matters, require itemId in your downstream checks.

### Limits

This actor currently covers **Brazil only (offers pages and marketplace search)**. It does not cover all 18 country sites, seller storefronts, direct product details, reviews, specifications, stock, location, or full image galleries. Those fields are absent because they were not reliably visible on the accessible offer cards.

Plain HTTP requests get a proof-of-work bot challenge and the public search API returns 403, so the actor loads the offers pages in a real browser on a Brazilian residential IP, which passes the automatic check. Product pages and other countries (for example Mexico) redirect to account verification or a CAPTCHA that the actor does not solve, so the offers route, including category filters and pagination, is the source used here. If a verification page appears, the actor retries on a new IP and fails with a clear message if it keeps appearing.

The offers navigation exposed pages through page 20; the input allows up to 21 pages per URL. Some categories end much sooner. Repeated pages and empty pages stop pagination. The site can change page size, cards, or navigation at any time. Each page holds 48 offers. There is no login support and no scraping of account or checkout data.

Some fields reflect marketing copy rather than exact inventory facts. SoldQuantity can be rounded. FreeShipping refers to a label on the card, not a postal-code-specific quote. FullShipping is true only when the card visibly says so. Seller names and official-store labels may be missing even when a product has a seller on its detail page. If a field is critical, check its fill rate in your own category and time period.

### Automation prompts

A structured workflow can use an input request such as: “Collect the first two pages of Brazil electronics offers, keep cards priced between 100 and 1,000 reais, and return the product ID, title, current price, previous price, and product URL.” Supply the actual offers category URL to make that request specific.

Another request might be: “Snapshot the general offers page daily, keep only titles containing ‘travesseiro’, and compare each product's price with yesterday's result.” Store id, itemId, sourceUrl, and scrapedAt with every snapshot so the comparison can distinguish a changed price from a different seller offer.

### Use with AI agents (MCP)

Add this actor to any MCP client (Claude, Cursor, VS Code, n8n and others) with one URL:

`https://mcp.apify.com?tools=mlg14/mercado-scraper`

The actor returns one dataset item per offer (title, price, original price, discount, seller, rating, shipping labels, product link). Keep `maxItems` small so the agent gets a bounded result; filters are applied by Mercado Livre itself.

**Prompt 1:** "Find the cheapest new phones on Mercado Livre Brazil under 2,000 reais."

```json
{
  "searchQueries": [
    "celular samsung"
  ],
  "priceMax": 2000,
  "condition": "new",
  "sort": "price_asc",
  "maxItems": 40
}
```

**Prompt 2:** "Get today's Mercado Livre offers in this category with prices and discounts."

```json
{
  "startUrls": [
    {
      "url": "https://www.mercadolivre.com.br/ofertas?category=MLB1055"
    }
  ],
  "maxPagesPerQuery": 1,
  "maxItems": 30,
  "priceMin": 100,
  "sort": "price_asc"
}
```

**Prompt 3:** "List official-store Mercado Livre listings for headphones (fone de ouvido)."

```json
{
  "searchQueries": [
    "fone de ouvido"
  ],
  "officialStoresOnly": true,
  "maxItems": 40
}
```

### FAQ

#### Is this data public?

The actor reads public product cards on the offers section. Review the site's terms and applicable law for your use case. Avoid using scraped data in ways that misuse personal information.

#### Do I need to configure a proxy?

No. The actor uses Apify Residential proxies in Brazil automatically; Mercado Livre rejects datacenter addresses. Residential traffic is included in the result price. You can provide your own proxy settings if you prefer.

#### How fast is a run?

A 40-offer run takes about 40 to 70 seconds, most of it browser start and the security check; each further page adds roughly 15 to 25 seconds. Use a one-page sample to estimate your own category before scheduling a larger crawl.

#### Can I use a normal keyword search URL?

Yes. Use Keywords, or paste a lista.mercadolivre.com.br search or category URL into Offers URLs; price, official-store, condition and sort filters are added to the URL for you.

#### Can I scrape a product's full description or stock?

No. The actor emits fields visible on the offer card. Detail pages were challenged in probing, so descriptions, stock, specifications, and gallery images are outside the supported output. The result includes a product link for workflows that have another permitted source for those details.

#### Why is a field empty?

The card may not display that value. For example, some cards omit seller names or installments. The actor returns null for absent optional details and does not invent a value from neighboring cards. Check the dataset's fill rate when deciding whether a field is suitable for your analysis.

#### Can I schedule runs and export the results?

Yes. Use the platform's scheduling and dataset export features to create repeated snapshots and download JSON or CSV. You can also read the dataset through the API or send completion events to another workflow.

### Integrations

The default dataset is available through export and API access. Use scheduled runs for recurring snapshots, webhooks for completion notifications, and your preferred spreadsheet or database workflow for analysis. Keep the original product identifiers and extraction timestamps when joining records across runs; title and price alone are not reliable keys.

### Support

Open an issue on the Issues tab; we reply within 24h and add fields on request. Include the offers URL, a small input example, the affected row ID, and the date of the run so the card can be checked against the current page.

# Actor input Schema

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

Public Brazil offers pages or search/category pages to scrape. Example: https://www.mercadolivre.com.br/ofertas?category=MLB1055 or a lista.mercadolivre.com.br URL. Use this for category deals; ignored for offers URLs when searchQueries is set.

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

Search terms, each run as a real Mercado Livre marketplace search with all filters applied by the site. Example: \["samsung", "fone de ouvido"]. Use this to find products by keyword; leave empty to scrape startUrls.

## `priceMin` (type: `number`):

Only products priced at or above this amount in Brazilian reais (BRL), applied by Mercado Livre. Example: 100. Use together with priceMax for a price band; leave empty for no minimum.

## `priceMax` (type: `number`):

Only products priced at or below this amount in Brazilian reais (BRL), applied by Mercado Livre. Example: 1000. Use together with priceMin for a price band; leave empty for no maximum.

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

If true, only products sold by official stores (Mercado Livre Loja oficial filter) are returned. Allowed values: true or false. Example: true for brand-authorised sellers. Leave false for all sellers.

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

Product condition filter for searchQueries and search URLs, applied by Mercado Livre. Allowed values: any, new, used. Example: new. Use new to exclude second-hand items; leave any for all conditions.

## `sort` (type: `string`):

Order of results. Allowed values: relevance, price_asc, price_desc. Example: price_asc for cheapest first. Keyword and search URLs are sorted site-wide; offers pages are sorted only among the crawled pages. Use relevance for the default order.

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

Maximum number of offers (dataset rows) to return; pages are read until this many are collected. Example: 40. Keep it small for quick tests; set 0 to collect everything up to maxPagesPerQuery.

## `maxPagesPerQuery` (type: `integer`):

Safety cap on pages read per URL or keyword, with 48-60 offers per page (offers pages max 21, search max 42). Example: 2. Reading stops once maxItems is reached; use a higher value for large category exports.

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

Proxy settings. Mercado Livre only opens for a Brazilian residential IP, so the actor uses Apify Residential proxies (country BR) unless you provide your own proxy.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.mercadolivre.com.br/ofertas"
    }
  ],
  "officialStoresOnly": false,
  "condition": "any",
  "sort": "relevance",
  "maxItems": 40,
  "maxPagesPerQuery": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `offers` (type: `string`):

All extracted public offers in the default dataset.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.mercadolivre.com.br/ofertas"
        }
    ],
    "maxItems": 40,
    "maxPagesPerQuery": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("mlg14/mercado-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 = {
    "startUrls": [{ "url": "https://www.mercadolivre.com.br/ofertas" }],
    "maxItems": 40,
    "maxPagesPerQuery": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("mlg14/mercado-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 '{
  "startUrls": [
    {
      "url": "https://www.mercadolivre.com.br/ofertas"
    }
  ],
  "maxItems": 40,
  "maxPagesPerQuery": 10
}' |
apify call mlg14/mercado-scraper --silent --output-dataset

```

## MCP server setup

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