MercadoLibre Fast Scraper
Pricing
from $5.00 / 1,000 results
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
Maintained by CommunityActor 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 installnpm 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
| field | type | description |
|---|---|---|
searchQueries | array | Keywords, searched on the site of country. |
country | string | AR (default), BR, MX, CL, CO, UY, PE, EC, VE, BO, CR, DO, GT, HN, NI, PA, PY, SV. |
startUrls | array | Search / category result pages (listado.mercadolibre.com.ar/..., lista.mercadolivre.com.br/...) and product pages (/p/MLA..., articulo.../MLA-..., /up/MLBU...) on any country site. |
maxItems | integer | Limit of products across all inputs, at most 10,000 per run. Empty = 10,000. |
includeProductDetails | boolean | Open every product page too. Default false. |
includeAds | boolean | Also output sponsored results (isAd: true). Default false. |
proxyConfig | object | Default: 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:
| mode | 1,000 products | proxy traffic | platform 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;imagesholds just the main image andconditionis only set for used / refurbished items (search results don't label new ones). itemIdis the seller's listing;productIdthe MercadoLibre catalog product it belongs to (many listings can share one).urlis 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/discountPercentare only set when MeLi shows a discount. soldQuantityandavailableQuantityare what MeLi shows, which is rounded (+500 vendidos→ 500; large stocks are capped).shippingis the delivery promise as shown, in the site's language. It,freeShippingand prices can depend on where the proxy IP is.positionis the rank among organic results (1 = first, continuing across pages); sponsored results haveposition: 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,
maxItemsbudget, 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
summaryrecord) and dataset (type/description of every field plus the Overview and Product details views). Apify validates each pushed item against the datasetfields, so keep .actor/dataset_schema.json in step withRECORD_FIELDSin 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.