Purpose
Retrieve the visible Yandex Market search results for a product name, model, SKU, or other query and return structured product listings suitable for a competitor or pricing report.
When to Use
Use when the caller provides a Yandex Market search query and needs the matching products and competing offers. The query may be a model number, product title, category phrase, or SKU.
Workflow
- Construct the direct search URL:
https://market.yandex.ru/search?text={url-encoded-query}. - Navigate directly to that URL with
domcontentloaded. - If the consent overlay is present, click
div#gdpr-popup-v3-button-mandatory; then run the extractor below on the same loaded search page. Do not visit the homepage or type into the search box. - Extract the visible result cards with this evaluator:
(()=>{
const clean=s=>(s||'').replace(/\\s+/g,' ').trim();
const abs=u=>{try{return new URL(u,location.origin).href}catch{return null}};
const query=new URLSearchParams(location.search).get('text')||'';
const money=s=>{
const m=clean(s).match(/(?:от\\s*)?([0-9][0-9\\s]*(?:[.,][0-9]{1,2})?)\\s*(?:₽|руб\\.?)/i);
return m?clean(m[1]).replace(/\\s/g,'')+' ₽':null;
};
const value=(root,selectors)=>{
for(const sel of selectors){const el=root.querySelector(sel);if(el){const t=clean(el.textContent);if(t)return t;}}
return null;
};
const results=[];
const seen=new Set();
const cards=[...document.querySelectorAll('[data-auto="snippet-product"], article, [data-zone-name="snippet"]')];
for(const card of cards){
const link=[...card.querySelectorAll('a[href]')].find(a=>/\\/product(?:--|\\/)/.test(a.getAttribute('href')||''));
if(!link)continue;
const url=abs(link.getAttribute('href')); if(!url||seen.has(url))continue;
const text=clean(card.textContent);
const name=value(card,['[data-auto="snippet-title"]','[data-auto="snippet-product-name"]','h3','h2'])||clean(link.textContent)||null;
const price=value(card,['[data-auto="snippet-price"]','[data-auto*="price"]'])||money(text);
const seller=value(card,['[data-auto="snippet-shop"]','[data-auto*="shop"]','[data-auto="offer-shop-name"]']);
seen.add(url); results.push({name,price,seller,url});
}
if(!results.length){
for(const link of [...document.querySelectorAll('a[href]')].filter(a=>/\\/product(?:--|\\/)/.test(a.getAttribute('href')||''))){
const url=abs(link.getAttribute('href')); if(!url||seen.has(url))continue;
const card=link.closest('article,li,[data-auto="snippet-product"],div')||link;
const text=clean(card.textContent);
seen.add(url); results.push({name:clean(link.textContent)||null,price:money(text),seller:null,url});
}
}
return {query,products:results};
})()Site-Specific Gotchas
- The useful state is available directly at
/search?text={query}; a homepage visit and search-box interaction are unnecessary. - Yandex Market may show a mandatory GDPR/consent overlay. The observed dismiss control is
div#gdpr-popup-v3-button-mandatory; dismiss it before extracting results. - Search results can contain several offer or card variants. Prefer the product-card selectors and deduplicate by canonical product URL; the fallback anchor pass handles pages where the card data attributes differ.
- The evaluator returns currently rendered/visible results only. If the page uses lazy loading or pagination, additional pages must be loaded and passed through the same extractor, then concatenated and deduplicated by URL.
- CSS/data-auto attributes may change with a frontend redesign; retain the product URL pattern and validate selectors if the result array is unexpectedly empty.
Expected Output
Return an object of the form {query, products}, where each product contains name, price, seller, and canonical url. The array represents the products and competing listings visible for the requested search query.