MercadoLibre Fast Scraper avatar

MercadoLibre Fast Scraper

Pricing

from $5.00 / 1,000 results

Go to Apify Store
MercadoLibre Fast Scraper

MercadoLibre Fast Scraper

search results — and, optionally, every product page they list — on all 18 Latin American country sites: Argentina, Brazil, Mexico, Chile, Colombia, Uruguay, Peru and the rest. Search by keyword or paste any search, category or product URL (filters and sorting included)

Pricing

from $5.00 / 1,000 results

Rating

0.0

(0)

Developer

Tin

Tin

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

15 days ago

Last modified

Categories

Share

MercadoLibre Scraper — Node.js / Apify

Apify Actor that scrapes MercadoLibre / Mercado Livre search results — and, optionally, every product page they list — on all 18 Latin American country sites: Argentina, Brazil, Mexico, Chile, Colombia, Uruguay, Peru and the rest. Search by keyword or paste any search, category or product URL (filters and sorting included).

Search results alone give title, price, discount, installments, shipping, seller, rating and units sold for 48 products per page, fast and cheap. Turn on product details to also get stock, condition, brand, attributes, description, all images, categories, review count and seller reputation.

Setup

Requires Node.js 20.18.1+ (the Actor image uses Node 24 with Google Chrome and Playwright 1.63.0).

npm install
npm test # parser + crawler tests (offline, against saved pages)

Run locally with the Apify CLI (or write the same JSON to storage/key_value_stores/default/INPUT.json and run npm start):

apify run --input='{
"searchQueries": ["zapatillas running"],
"country": "AR",
"maxItems": 20
}'

MercadoLibre blocks IPs outside Latin America, so a local run needs a Latin American residential proxy. Apify Proxy only works outside the platform if the account has Proxy external access; without it the log says "No proxy configured" and requests go out directly (and get MeLi's login wall). Locally Chrome opens a visible window — it has to run headful (see below).

Input

fieldtypedescription
searchQueriesarrayKeywords, searched on the site of country.
countrystringAR (default), BR, MX, CL, CO, UY, PE, EC, VE, BO, CR, DO, GT, HN, NI, PA, PY, SV.
startUrlsarraySearch / category result pages (listado.mercadolibre.com.ar/..., lista.mercadolivre.com.br/...) and product pages (/p/MLA..., articulo.../MLA-..., /up/MLBU...) on any country site.
maxItemsintegerLimit of products across all inputs, at most 10,000 per run. Empty = 10,000.
includeProductDetailsbooleanOpen every product page too. Default false.
includeAdsbooleanAlso output sponsored results (isAd: true). Default false.
proxyConfigobjectDefault: Apify RESIDENTIAL. With no country set, each site gets proxies from its own country (mercadolibre.com.ar → AR, …); a country set here is used for every site.

At least one search query or start URL is required. Search pages are followed through MeLi's own "next" link until maxItems is reached or the results run out. Products repeated across pages (MeLi reshuffles) are output once.

Speed and cost

Measured on Apify with 4 GB memory (6 workers), residential proxies, 2026-10-03:

mode1,000 productsproxy trafficplatform cost*
search results only~3 min (6 items/s)~7 MB~$0.09
with product details~25 min (0.6–0.7 items/s)~225 MB~$2.40

*Residential proxy at $8/GB plus compute; proxy traffic is most of it. A product page is ~200 KB over the wire, a search page (48 products) about the same, plus ~250 KB once per browser session for MeLi's bot challenge.

Memory is limited to 2–8 GB (default 4 GB) in .actor/actor.json. The worker count follows memory, ~1.5 per GB (2 GB → 3, 4 GB → 6, 8 GB → 12): each worker drives a browser tab, and at 4 GB with 5 workers the run peaked at 1.8 GB and used 65 % of its CPU core — pages mostly wait on the proxy.

Output

One dataset record per product, always the same 43 fields in the same order. Example with product details (Argentina):

{
"url": "https://www.mercadolibre.com.ar/samsung-galaxy-a17-a175f-negro-67-4gwi-finfc-android-1-negro/p/MLA65114795",
"itemId": "MLA4022163150",
"productId": "MLA65114795",
"title": "Samsung Galaxy A17 A175f negro 6.7 4G+Wi-Fi+NFC - Android 1 negro",
"price": 353990,
"originalPrice": 389000,
"discountPercent": 9,
"currency": "ARS",
"installmentsCount": 6,
"installmentAmount": 79641.85,
"installmentsInterestFree": false,
"shipping": "Llega gratis el martes",
"freeShipping": true,
"fullFulfillment": true,
"internationalFrom": null,
"seller": "ORBEXTECHSTORE",
"sellerId": 3333630569,
"officialStore": false,
"sellerReputation": "5_green",
"sellerPowerSellerStatus": "silver",
"rating": 4.9,
"reviewsCount": 14573,
"soldQuantity": 1000,
"availableQuantity": 6,
"inStock": true,
"condition": "new",
"brand": "Samsung",
"image": "https://http2.mlstatic.com/D_NQ_NP_751119-MLA105637632754_012026-O.webp",
"images": [
"https://http2.mlstatic.com/D_NQ_NP_751119-MLA105637632754_012026-O.webp",
"https://http2.mlstatic.com/D_NQ_NP_819311-MLA105637692854_012026-O.webp"
],
"categories": ["Celulares y Teléfonos", "Celulares y Smartphones", "Samsung"],
"categoryId": "MLA1055",
"domainId": "MLA-CELLPHONES",
"attributes": [
{ "name": "Marca", "value": "Samsung" },
{ "name": "Modelo", "value": "A17" }
],
"description": "Mayor rendimiento\nSu memoria RAM de 4 GB permite que tu smartphone funcione…",
"listingType": "gold_special",
"isAd": false,
"position": 5,
"country": "AR",
"siteId": "MLA",
"searchQuery": "celular samsung",
"sourceUrl": "https://listado.mercadolibre.com.ar/celular-samsung",
"detailsScraped": true,
"scrapedAt": "2026-10-03T09:22:32.617Z"
}

Field notes:

  • Without product details, these fields are null / empty: sellerId, sellerReputation, sellerPowerSellerStatus, reviewsCount, availableQuantity, inStock, brand, categories, attributes, description, listingType; images holds just the main image and condition is only set for used / refurbished items (search results don't label new ones).
  • itemId is the seller's listing; productId the MercadoLibre catalog product it belongs to (many listings can share one). url is the page the search linked to — a catalog page (/p/), a listing (articulo.) or a user product (/up/).
  • Prices are numbers in the site's currency (currency). originalPrice / discountPercent are only set when MeLi shows a discount.
  • soldQuantity and availableQuantity are what MeLi shows, which is rounded (+500 vendidos → 500; large stocks are capped).
  • shipping is the delivery promise as shown, in the site's language. It, freeShipping and prices can depend on where the proxy IP is.
  • position is the rank among organic results (1 = first, continuing across pages); sponsored results have position: null. Sponsored results are taken from their product ids — the Actor never follows MeLi's ad-click links, so advertisers aren't billed for its visits.
  • If a product page keeps failing, the product is still output with its search-result fields and detailsScraped: false. A product that no longer exists is skipped and its slot goes to the next result.

The run's outcome counters and proxy traffic are stored in the key-value store as summary. Pages that load but can't be parsed (layout change, soft block) are saved there as debug-list-<n> / debug-item-<n> (first 10 per run).

Migrations. The crawl state (queue, seen pages, maxItems budget, counters) is saved to the key-value store as CRAWLER_STATE every minute and when Apify moves the run to another server. On a move the crawler first stops taking pages and waits for dataset pushes under way, so the resumed run continues exactly where it stopped: no product is scraped — or charged — twice.

Monetization

Works with pay-per-result as is. For pay-per-event, define the synthetic apify-default-dataset-item event (every product) and optionally a product-details event: the Actor charges it once per product whose page was opened, so the much costlier details mode can be priced separately. A run's spending limit is respected (ACTOR_MAX_PAID_DATASET_ITEMS caps maxItems; under pay-per-event the crawl stops when the limit is reached).

How it gets past MercadoLibre's bot protection

MeLi's search and product pages sit behind a bot challenge: a fresh visitor first gets an interstitial whose script solves a proof-of-work and runs MeLi's browser fingerprinting before reloading the page. Clients that don't run it end on /captcha/wall; IPs outside Latin America get a login wall (/gz/account-verification). MeLi's public API needs OAuth for everything.

So the Actor drives a real Google Chrome (Playwright), headful on the image's X server — headless Chrome is refused outright — with residential proxies from each site's own country. Each worker keeps one browser context (one sticky proxy IP, one cookie jar) per country and reuses it for up to 80 pages, so the challenge runs once per session. Only the challenge page may load scripts; real pages load just their HTML document (images, CSS and JS blocked), which is what keeps traffic at ~200 KB per page instead of ~2 MB. A blocked page (captcha, login wall) is retried up to 4 times (search pages 8) on a fresh session. In the test runs above, sessions were almost never blocked.

Everything is parsed from the JSON state MeLi embeds in every page (_n.ctx.r=…), which is the same on all country sites, with the page's JSON-LD as a fallback — no CSS selectors.

Codebase

  • src/main.js — Actor entry: input, proxies per country, dataset output, charging, summary.
  • src/meli/crawler.js — task queue, workers, session rotation, retries, pagination, maxItems budget, migration state.
  • src/meli/session.js — shared Chrome, one context per proxy session, challenge handling, resource blocking, page classification.
  • src/meli/parse.js — search page and product page parsers, output record.
  • src/meli/sites.js — country sites, URL helpers.
  • src/meli/*.test.js — tests against real pages in src/meli/fixtures/ (gzipped, captured 2026-10-03 through Apify residential proxies in AR/BR/CL/CO/MX).
  • .actor/ — Actor manifest, Dockerfile and schemas: input, output (links to the products, the Overview table and the summary record) and dataset (type/description of every field plus the Overview and Product details views). Apify validates each pushed item against the dataset fields, so keep .actor/dataset_schema.json in step with RECORD_FIELDS in parse.js when adding or changing a field.
  • legacy/akamai-debug/ — the earlier HTTP-only proof-of-work experiment this Actor replaced (not deployed).

Log lines look like:

[w3] sess=7129eglh4d6a item item_ok status=200 chall=0 dur=3.3s kb=222 try=1 mercadolivre.com.br/headphone-bluetooth-max5c-ugreen-75h-anc-43db-cor- | BRL 162.96 Headphone Bluetooth Max5c Ugreen 75h Anc

chall=1 means the page went through the bot challenge, kb is proxy traffic. Outcomes: list_ok, list_empty (no results), item_ok, captcha, blocked (login wall / access error), challenge (interstitial never cleared), ratelimit, not_found, http_error, transport_error, unparsable; *_failed counts pages that ran out of retries and item_card_only the products output from their search result instead.