# Yandex Market Search & Price Scraper (`apt_marble/yandex-market-search-price-scraper`) Actor

Track prices on Russia's biggest marketplace. Turn search terms, categories and brand pages into one clean table of products with prices, sellers, ratings, delivery promises and stock counts. Watch competitors daily, audit your own listings, export to a spreadsheet.

- **URL**: https://apify.com/apt\_marble/yandex-market-search-price-scraper.md
- **Developed by:** [Hamza](https://apify.com/apt_marble) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 product founds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Yandex Market Search Scraper

Turn any Yandex Market search — or any category, brand or filtered listing page
you can see on the site — into a clean, flat table of products with prices,
sellers, ratings, delivery promises and stock counts. Built for e-commerce teams
who need to watch what competitors charge on Russia's largest marketplace, for
brands checking how their products are being listed and priced by resellers, and
for analysts who want marketplace price data in a spreadsheet instead of in a
browser tab. No account and no login are needed — just run it.

### What you can do with it

- **Watch competitor prices daily.** Run the same searches on a schedule and
  build a price history for every product that shows up on them.
- **Check who is undercutting you.** Every row names the seller behind the
  price, so you can see exactly which shops are selling below your line.
- **Audit your own listings.** Search your brand and confirm the headline price,
  delivery promise and stock count buyers actually see for each of your
  products.
- **Size up a category before you enter it.** Pull a whole category or brand
  listing and look at the real price spread, the ratings and who is selling.
- **Find products worth stocking.** Sort by rating or by price and pull the top
  of the list for any keyword you care about.
- **Track the price a shopper is actually quoted.** `advertisedPrice` is the
  headline figure on the card, checked product page by product page against the
  marketplace's own price for the same seller's listing.

### What you get

One row per product, exactly as the marketplace published it at the moment of
collection.

```json
{
  "query": "iphone",
  "queryType": "searchTerm",
  "position": 12,
  "page": 2,
  "productId": 5952767671,
  "skuId": "103765464591",
  "offerId": "lj_LfmpbXb27zUgbgatKCg",
  "title": "Смартфон Apple iPhone 16 256ГБ Dual: nanoSIM Black (Черный)",
  "brand": "Apple",
  "price": 111462,
  "advertisedPrice": 81999,
  "currency": "RUB",
  "rating": 4.9,
  "ratingCount": 410,
  "sellerName": "iGlobalShop",
  "sellerId": 216526610,
  "deliveryText": "Сегодня",
  "inStockCount": 10,
  "isSponsored": false,
  "isCrossBorder": true,
  "specs": [
    "Диагональ экрана: 6.1\"",
    "Встроенная память : 256 ГБ",
    "Оперативная память: 8 ГБ"
  ],
  "imageUrl": "https://avatars.mds.yandex.net/get-mpic/1733932/2a0000019aa0800e088f675a8cdfa41c7406/600x600",
  "productUrl": "https://market.yandex.ru/product/5952767671",
  "sortApplied": "popularity",
  "regionId": 213,
  "regionName": "Moscow",
  "collectedAt": "2026-08-17T09:14:52.318Z"
}
```

### Input reference

| Setting | Type | Default | Description |
| --- | --- | --- | --- |
| Search terms | list of text | — | Product searches to run, one per line. Each is collected separately and every row says which term it came from. |
| Category or brand addresses | list of text | — | Optional. Paste the address of any category, brand or filtered listing from the marketplace and it is collected exactly as you see it, filters included. Anything that is not a listing — a single product, a seller's page, the marketplace home page — is refused before the run starts, with a message saying what to paste instead. |
| Maximum products per search | integer | `100` | Stop after this many products for each search term or address. |
| Order results by | select | `Popularity` | Popularity, price low to high, price high to low, or highest rated. Popularity is the marketplace's own default order. Whatever you choose here wins, including over an ordering already built into an address you pasted. |
| Minimum price | integer | — | Optional. Only products at or above this price come back. |
| Maximum price | integer | — | Optional. Only products at or below this price come back. |
| Currency | select | `RUB` | The marketplace publishes every price in Russian roubles and they are returned exactly as published, never converted. Nothing to change — it is shown so you know what the numbers mean. |
| How many searches to run at once | integer | `3` | Work on several search terms side by side to finish sooner. Lower it if you would rather be gentle on the source. |

At least one search term or one address must be filled in. If neither is, the
run stops immediately and says so.

### Output fields

| Field | Type | Description |
| --- | --- | --- |
| `query` | text | The search term or address this product came from. |
| `queryType` | text | `searchTerm` or `listingUrl`. |
| `position` | number | Where the product sat in the marketplace's own ordering, counted across the whole run for that search. |
| `page` | number | Which listing page it appeared on, as the marketplace reported it. |
| `productId` | number | The marketplace's own product identifier. Several sellers can list the same product, so this repeats across rows while `offerId` does not. |
| `skuId` | text | The identifier of the exact variant being sold. |
| `offerId` | text | The identifier of the specific seller's listing. |
| `title` | text | The product name as shown. |
| `brand` | text | Brand name, where the marketplace publishes one. |
| `price` | number | The listing's own reference figure for the offer — the higher "before" number the card carries next to its headline price. It is **not** the amount a shopper is charged, and on a measured sample of ten listings checked against their own product pages it matched neither of the two prices those pages publish for the same seller in eight cases, running from 1 % to 113 % above the amount charged. Use it as an anchor, not as a price. |
| `advertisedPrice` | number | The price the marketplace headlines on the card, which applies when its own payment method is used. **This is the number to compare against a shelf price.** Verified live: on ten listings re-read on their own product pages it equalled the marketplace's own headline price for the same seller's listing ten times out of ten. Empty when the marketplace publishes no such price. |
| `currency` | text | The currency the price is published in — always read from the response, never assumed. |
| `rating` | number | Star rating out of 5. Empty when the product has not been rated. |
| `ratingCount` | number | How many ratings that average is built from. Empty when there are none. |
| `sellerName` | text | The shop selling at that price. |
| `sellerId` | number | The marketplace's own identifier for that shop. |
| `deliveryText` | text | The delivery promise shown with the product, in the marketplace's own wording. |
| `inStockCount` | number | Units the seller says are available. |
| `isSponsored` | true/false | The marketplace's own promotion flag on the offer, passed through as it comes. Read the caveat below before using it: it was set on 44 of 48 offers measured live, so it does not single out paid placements. |
| `isCrossBorder` | true/false | Whether the item ships from outside the country. |
| `specs` | list of text | The short specification bullets shown under the product, where any are published. |
| `imageUrl` | text | Product photograph. |
| `productUrl` | text | Link to the product's own page. |
| `sortApplied` | text | The ordering the marketplace actually applied, read back from its answer. |
| `regionId` | number | The market the prices were served for, read back from the answer rather than assumed. |
| `regionName` | text | That market's name. |
| `collectedAt` | text | When the row was collected, in ISO 8601. |

### Pricing

You pay per product collected — nothing else, and nothing for a search that
comes back with nothing.

| What you pay for | Price |
| --- | --- |
| Each product collected | $0.002 (that is $2.00 per 1,000 products) |

**A worked example.** Ten search terms, up to 200 products each, run every
morning: about 2,000 products a day, or **$4.00 per run**. A single one-off
check of one category at the full 400-product depth costs **$0.80**.

Set a maximum on the run and it will stop once that limit is reached, so a run
can never cost more than you allowed.

### Limits & what this actor cannot do

- **A search has a ceiling on how deep it goes.** The marketplace publishes a
  few hundred products for any one search — measured between about 330 and 390 —
  no matter how many it claims to hold in total. Asking for more returns
  everything it makes available, not more than that. Split a broad search into
  narrower ones, or use category and brand addresses, to cover more ground.
- **Prices are the ones the source publishes for its default market.** The
  marketplace serves one market to everybody and does not accept a choice of
  another, so there is no city selector here and there never can be one that
  would tell the truth. Every row is stamped with the market it was actually
  served for, so you always know what you are looking at.
- **Compare on `advertisedPrice`, not on `price`.** A listing page carries two
  numbers per product and only one of them is a price anyone pays.
  `advertisedPrice` is the headline figure, and it was checked against the
  marketplace's own product page for the same seller's listing on ten products:
  it matched exactly ten times out of ten. `price` is the higher "before"
  figure the listing carries alongside it, and on those same ten products it
  matched neither the amount charged nor the crossed-out figure the product page
  shows, in eight of them — sitting anywhere from 1 % to 113 % above the amount
  charged. Both come back in their own columns and neither is merged into the
  other, but only `advertisedPrice` is safe to compare against a shelf price.
- **The exact amount charged without the marketplace's own payment method is
  not on the listing page.** The product page publishes it; a listing page does
  not, for any product. It is therefore not reported, and it is not
  approximated from `price` and presented as if the marketplace had published
  it. If you need it, that is a product-page job, not a search job.
- **No discount percentage.** Listings publish no percentage saved and no
  recommended retail figure, so none is reported and none is worked out by
  arithmetic and presented as the marketplace's own.
- **Ratings are not published for every product, and how many varies a lot.**
  Two live runs of the same two searches minutes apart returned a rating on 37
  of 50 products and then on 24 of 50 — roughly a half to three quarters, and
  not a figure to plan around. The rest come back empty rather than as a zero,
  because a zero would read as a terrible product rather than an unrated one.
- **The promotion flag is not a paid-placement detector, and is not sold as
  one.** The marketplace sets its promotion flag on most of the listing: 44 of 48
  offers in a live probe across three searches and one category, and 42 then 34
  of 50 on two ordinary runs. The separate
  flag that governs whether the marketplace itself labels a card as an ad was
  false on all 48. So `isSponsored` is passed through exactly as published and
  described as what it is — the marketplace's own flag — rather than presented
  as a way to tell paid results from ranked ones. Nothing is filtered out on
  the strength of it.
- **Positions are the marketplace's ranks, so they can have gaps.** `position`
  is stamped in the order the marketplace served each product, before anything
  is dropped. When the same offer is served twice across pages, or a price range
  excludes it, that rank simply does not appear in your table. A missing number
  means a product was ranked there and not kept, never that a row went astray.
- Results are a snapshot at the moment of collection, and the marketplace's own
  results change continuously. Ratings, stock counts and delivery promises are
  as published at collection time and can lag.
- The actor reports what the marketplace publishes to the public. It does not
  sign in, does not see anything behind a login, and cannot reveal a detail the
  marketplace keeps private.
- A search the marketplace refuses to complete is reported as a failed search,
  never as "no results found". The run summary counts searches that produced
  results, searches that genuinely had nothing, searches whose products all fell
  outside the price range that was set, and searches that could not be
  read, each as its own number.
- Speed depends on the size of the job and on the marketplace's own response
  times; no fixed throughput is promised.
- The marketplace's terms govern automated access. You are responsible for using
  the data lawfully and in line with those terms, including any applicable
  privacy law such as GDPR and Russian personal data law.

### FAQ

**Do I need an account on Yandex Market?**
No. Nothing is signed in to and nothing is bought.

**Does it need my login or password?**
No. There is nothing to configure — start it and it runs.

**Can I schedule it?**
Yes. Point a schedule at it and it will collect the same searches on whatever
rhythm you set, which is how you build a price history.

**Which city's prices am I getting?**
The ones the marketplace publishes for its default market. It serves the same
market to everyone and will not accept a different one, so rather than offer a
city selector that quietly returns the same prices under a different label, this
actor reports the market it was actually served and says so on every row.

**Why did I get fewer products than I asked for?**
Because the marketplace stopped publishing new ones. It makes a few hundred
available for any one search — measured between about 330 and 390 — and the
actor returns everything it publishes and then stops. It never invents a filler
row to reach your number.

**One product is listed by several shops. Do I get all of them?**
This actor returns the listing exactly as the marketplace ranks it, which means
the seller and price shown for each product in the results. It is a picture of
the listing, not a full seller-by-seller breakdown of one product.

**What happens if a search fails?**
It is counted as a failed search and named in the run summary, with the reason.
It is never quietly reported as a search that found nothing — those are two
different answers and this actor keeps them apart.

# Actor input Schema

## `queries` (type: `array`):

Product searches to run, one per line. Each one is collected on its own and every row tells you which term it came from.

## `categoryUrls` (type: `array`):

Optional. Paste the address of any category, brand or filtered listing straight from the marketplace and it is collected exactly as you see it, including the filters you set. Single product addresses are rejected with a message.

## `maxResultsPerQuery` (type: `integer`):

How many products to collect for each search term or address. The marketplace publishes roughly 390 products for any one search, so anything above that simply returns everything it publishes.

## `sortBy` (type: `string`):

The order the marketplace should return products in. 'Popularity' is the marketplace's own default order.

## `minPrice` (type: `integer`):

Optional. Only products at or above this price are returned. Leave blank for no lower bound.

## `maxPrice` (type: `integer`):

Optional. Only products at or below this price are returned. Leave blank for no upper bound.

## `currency` (type: `string`):

The marketplace publishes every price in Russian roubles and this actor returns them exactly as published, never converted. There is nothing to change here — it is shown so you know what the numbers mean. Every row is also stamped with the market the marketplace served it for: it serves one default market to everybody and will not accept a different one, so there is no city to choose either.

## `maxConcurrency` (type: `integer`):

Run several search terms side by side to finish sooner. Lower it if you would rather be gentle on the source.

## Actor input object example

```json
{
  "queries": [
    "iphone",
    "робот-пылесос"
  ],
  "categoryUrls": [
    "https://market.yandex.ru/catalog--smartfony/54726/list?hid=91491"
  ],
  "maxResultsPerQuery": 50,
  "sortBy": "popularity",
  "currency": "RUB",
  "maxConcurrency": 3
}
```

# Actor output Schema

## `products` (type: `string`):

Every product this run collected.

## `overview` (type: `string`):

The same products in the compact overview layout.

## `spreadsheet` (type: `string`):

Every product as a CSV file you can open in a spreadsheet.

## `runSummary` (type: `string`):

What this run collected, what came back with nothing, and anything it could not read.

# 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 = {
    "queries": [
        "iphone",
        "наушники"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("apt_marble/yandex-market-search-price-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 = { "queries": [
        "iphone",
        "наушники",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("apt_marble/yandex-market-search-price-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 '{
  "queries": [
    "iphone",
    "наушники"
  ]
}' |
apify call apt_marble/yandex-market-search-price-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,apt_marble/yandex-market-search-price-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/53oG4dh0fUNAddyfn/builds/6n7vUFnn66jepzI8k/openapi.json
