Scrape Mercado Livre Search Results

Site lista.mercadolivre.com.brTask scrape-search-resultsVersion v3Updated Aug 20, 2026Category shopping

Navigate directly to Mercado Livre Brasil keyword-results URLs and extract deduplicated product cards, including pricing, seller, official-store status, shipping, media, promotion, rating, and availability fields. This skill was captured from a live agent session on lista.mercadolivre.com.br and publishes here verbatim, exactly as an agent receives it.

NoteSelectors and URL schemes drift as sites change. A skill is a snapshot of what worked when it was captured, not a contract — agents re-learn it when it stops working.

Purpose

Collect structured product listings from Mercado Livre Brasil search-result pages using the site's slug-based search URL and resilient selectors covering current Poly cards and legacy UI Search layouts. The extractor captures title, URL, image, prices, installments, discount labels, seller, official-store status, shipping, badges, rating, review count, condition, and sold-count text.

When to Use

Use when the input is a product keyword or phrase and the required output is the set of product cards currently displayed on the corresponding Mercado Livre Brasil results page. Apply the optional officialStoreOnly post-filter when the caller wants only listings marked as an official store, such as an official brand shop. The workflow is page-local and does not resolve product IDs or open individual product pages.

Workflow

  1. Build the direct results URL by normalizing {query} to lowercase, replacing runs of whitespace with hyphens, and URL-encoding the resulting path segment: https://lista.mercadolivre.com.br/{normalized-query} Optional observed marketplace-scope parameter: append ?sb=all_mercadolibre when the caller requests the all-Mercado-Libre scope.
  2. In one browser call, navigate to that URL with waitUntil: "domcontentloaded", allow roughly 2 seconds for cards to render, and run this evaluator. Set officialStoreOnly to true only when requested; it defaults to false and therefore does not narrow ordinary searches.
(()=>{
const officialStoreOnly=false;
const clean=s=>(s||'').replace(/\s+/g,' ').trim();
const abs=u=>{try{return new URL(u,location.href).href}catch{return u||''}};
const firstText=(el,selectors)=>{for(const s of selectors){const n=el.querySelector(s),v=clean(n?.textContent);if(v)return v}return ''};
const firstAttr=(el,selectors,attrs)=>{for(const s of selectors){const n=el.querySelector(s);if(!n)continue;for(const a of attrs){const v=n.getAttribute(a);if(v){if(a==='srcset')return abs(v.split(',')[0].trim().split(/\s+/)[0]);return abs(v)}}}return ''};
const money=(card,selector)=>{const el=card.querySelector(selector);if(!el)return null;const f=clean(el.querySelector('.andes-money-amount__fraction')?.textContent),c=clean(el.querySelector('.andes-money-amount__cents')?.textContent||'00');if(!f)return null;const n=parseFloat(f.replace(/\./g,'').replace(',','.')+'.'+c.replace(/\D/g,''));return Number.isFinite(n)?n:null};
const cardSelectors=['li.ui-search-layout__item','.ui-search-result__wrapper','.poly-card','.andes-card'];
const cards=[...new Set(cardSelectors.flatMap(s=>[...document.querySelectorAll(s)]))];
const products=cards.map(card=>{const titleEl=card.querySelector('a.poly-component__title,h2.ui-search-item__title,.ui-search-item__title,[class*="title"] a,a[href*="/MLB-"]');const link=titleEl?.closest('a')||card.querySelector('a[href*="mercadolivre.com.br/MLB"],a[href*="/MLB-"]');const title=clean(titleEl?.textContent||card.querySelector('h2,h3')?.textContent);if(!title||!link)return null;const seller=firstText(card,['.poly-component__seller','.ui-search-item__group__element [class*="seller"]','[class*="seller"]']);const official=!!card.querySelector('.poly-component__seller svg[aria-label="Loja oficial"],[aria-label*="Loja oficial" i]')||/loja oficial/i.test(seller)||/loja oficial/i.test(clean(card.textContent));return {title,url:abs(link.href),image:firstAttr(card,['.poly-component__picture','img','picture source'],['src','data-src','data-lazy-src','srcset']),priceCurrent:money(card,'.poly-price__current')??firstText(card,['.poly-price__current','.ui-search-price__part']),priceCurrentFull:firstText(card,['.poly-price__current','.ui-search-price__part']),priceOriginal:money(card,'.poly-price__previous,.poly-price__labels')??firstText(card,['.poly-price__previous','.poly-price__current s','.andes-money-amount--previous','s']),installments:firstText(card,['.poly-price__installments','.ui-search-installments']),discount:firstText(card,['.poly-price__discount-polylabel','.poly-price__label','.ui-search-price__second-line']),seller,isOfficialStore:official,shipping:firstText(card,['.poly-component__shipping-v2','.poly-component__shipping','.ui-search-item__shipping','[class*="shipping"]']),rating:firstText(card,['.poly-reviews__rating','.ui-search-reviews__rating','[class*="rating"]']),reviews:firstText(card,['.poly-reviews__total','.ui-search-reviews__amount','[class*="reviews"]']),badges:[...card.querySelectorAll('.polylabel-pill,.polylabel-label,.ui-search-item__highlight-label,[class*="badge"]')].map(e=>clean(e.textContent)).filter(Boolean),condition:firstText(card,['.poly-component__condition','[class*="condition"]']),sold:firstText(card,['.poly-component__sold-quantity','[class*="sold"]','[class*="quantity"]'])}}).filter(Boolean);
const unique=[],seen=new Set();for(const p of products)if(!seen.has(p.url)){seen.add(p.url);unique.push(p)}
const result=officialStoreOnly?unique.filter(p=>p.isOfficialStore):unique;
return {url:location.href,title:document.title,bodyLength:document.body.innerHTML.length,cardCount:cards.length,officialStoreOnly,products:result};
})()

Site-Specific Gotchas

  • The search endpoint is directly reachable at /{hyphenated-query} on lista.mercadolivre.com.br; do not visit the homepage or type into the search box first.
  • ?sb=all_mercadolibre is an observed optional scope parameter for the all-Mercado-Libre search view; it is not the official-store filter itself.
  • Official-store status is exposed on current Poly cards by an SVG with aria-label="Loja oficial"; the evaluator also checks the seller/card text for localized official-store labeling. Treat this as a page marker, not proof of seller identity when the markup is absent.
  • Mercado Livre may render different card structures, so retain both poly-* and ui-search-* selectors and deduplicate by canonical product URL.
  • Current Poly cards expose useful fields through .poly-component__seller, .poly-component__shipping-v2, .poly-price__installments, .poly-price__discount-polylabel, .polylabel-pill, and .poly-component__picture; these are more precise than relying only on card text.
  • Image URLs may be lazy-loaded in src, data-src, data-lazy-src, or srcset; the evaluator checks all of these and converts them to absolute URLs.
  • Broad fallback selectors containing title, rating, reviews, shipping, or seller can match localized layout variants and are less stable than specific Poly/UI Search selectors.
  • A domcontentloaded navigation followed by a short render wait helps cards appear. If cardCount and products are zero, inspect the loaded page for an anti-bot or consent interstitial and preserve the same browser session while waiting or retrying; no separate bypass endpoint is established.
  • Prices, ratings, review counts, seller text, shipping text, and other labels remain localized text. priceCurrent and priceOriginal are numeric when the amount markup is parseable; otherwise they retain the displayed text.
  • The evaluator only extracts cards present in the loaded result page; it does not infer products hidden behind pagination or infinite scrolling.

Expected Output

An object with url, title, bodyLength, cardCount, officialStoreOnly, and products. Each product contains title, absolute url, image, priceCurrent, priceCurrentFull, priceOriginal, installments, discount, seller, isOfficialStore, shipping, rating, reviews, badges, condition, and sold. Optional fields are empty strings, null, or empty arrays when absent, and duplicate product URLs are removed.

Call it

GET https://production-sfo.browserless.io/skills?token=TOKEN-HERE&domain=lista.mercadolivre.com.br&task=scrape-search-results