# Magnit Market (mm.ru) Scraper (`crawlerbros/magnit-market-scraper`) Actor

Scrape Magnit Market (mm.ru / Магнит Маркет) - Russia's marketplace by Magnit. Search products, browse by category, fetch full product details (prices, ratings, stock, images, seller info, characteristics and SKUs), or pull real customer reviews.

- **URL**: https://apify.com/crawlerbros/magnit-market-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, E-commerce, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## Magnit Market (mm.ru) Scraper

Scrape **mm.ru** — Magnit Market (Магнит Маркет), the marketplace launched in
May 2024 by Magnit, Russia's #2 grocery retailer, as the rebrand of
KazanExpress. Search products, browse any category, pull full product detail
pages (prices, ratings, stock, images, seller info, characteristics, SKU
variants), list the category tree, or fetch real customer reviews — all
without logging in or paying for a proxy.

### What this actor does

- **Five modes:** `search`, `byCategory`, `productDetails`, `categoryTree`, `reviews`
- **Search & browse:** free-text search or full category listings, sortable by popularity/price/rating, with server-side price/rating/stock/adult filters
- **Full product detail:** description, characteristics, SKU variants with their own price/stock, seller info, delivery estimate, every photo, and up to 10 similar products
- **Category discovery:** the full mm.ru category hierarchy (or one branch) with per-category product counts, so you can find category IDs without guessing
- **Customer reviews:** star rating, review text, pros/cons, purchased variant, reviewer name, like/dislike counts, photos, seller replies, plus a full rating breakdown for the whole product
- **Empty fields are omitted** from every record — only fields mm.ru actually returned are included

### Output per product (mode = `search`, `byCategory`)

- `productId` — mm.ru product ID
- `title`
- `priceRub`, `oldPriceRub`, `isPromotion`, `discountPercent`
- `rating`, `reviewsCount`, `ratingsCount`, `ordersCount`
- `quantityAvailable`, `inStock`, `isLowStock`
- `isForAdults`
- `catalogType`, `storeCode` — mm.ru's internal listing classification and store/warehouse code
- `mainImageUrl`, `imageUrls[]` — up to 10 photos
- `skuGroupId`, `skuIds[]` — up to 30 variant SKU IDs
- `nearestDeliveryDate`
- `productUrl`, `sourceUrl`
- `recordType: "product"`, `scrapedAt`

### Output per product detail (mode = `productDetails`)

- `productId`, `title`, `description`, `shortDescription`
- `categoryId`, `categoryTitle`, `categoryPath[]` — full breadcrumb from root to this product's category
- `priceRub`, `fullPriceRub`, `discountPercent`
- `rating`, `externalRating` — mm.ru's own rating plus any imported (e.g. legacy KazanExpress) rating
- `ordersCount`, `reviewsCount`, `reviewsPhotoCount`
- `mainImageUrl`, `imageUrls[]` — up to 20 photos
- `shopId`, `shopTitle`, `shopUrl`, `shopRating`, `shopOfficial`, `shopOrdersCount`, `shopReviewsCount`
- `characteristics[]` — full spec table (`name`/`value` pairs), grouped across SKU variants
- `quickSpecs[]` — the short bullet-point highlights shown at the top of the product page (`name`/`value` pairs)
- `skus[]` — every SKU variant: `skuId`, `title`, `priceRub`, `fullPriceRub`, `availableAmount`, `characteristics[]`
- `nearestDeliveryDate`
- `similarProducts[]` — up to 10 related items (unless `includeSimilarProducts: false`), each with `productId`, `title`, `priceRub`, `fullPriceRub`, `rating`, `reviewsCount`, `ordersCount`, `imageUrl`, `deliveryDate`, `categoryId`, `isAdultCategory`, `productUrl`
- `productUrl`, `sourceUrl`
- `recordType: "productDetail"`, `scrapedAt`

### Output per review (mode = `reviews`)

- `reviewId`, `productId`
- `rating`
- `reviewText` — full review text; `pros`/`cons` appear only on the (uncommon) reviews where the reviewer filled in those separate fields
- `reviewDate`
- `reviewerName` — shows `***` if the reviewer posted anonymously (mm.ru's own masking, not this actor's), `isAnonymous`, `isEdited`
- `likesCount`, `dislikesCount`
- `variantCharacteristics[]` — the purchased variant (e.g. color/size/model), `name`/`value` pairs
- `photoUrls[]` — review photos
- `sellerReply` — `content`, `shopName`, `date`, present only if the seller replied
- `productRatingBreakdown` — 1-5 star histogram for the whole product (not just the returned subset)
- `productReviewsTotal`, `productAvgRating` — always reflect mm.ru's full review set for that product, regardless of `reviewsLimit`
- `productUrl`
- `recordType: "review"`, `scrapedAt`

### Output per category (mode = `categoryTree`)

- `categoryId`, `title`
- `depth` — 0 for a top-level category
- `parentPath[]` — titles of every ancestor category
- `productAmount`
- `isLeaf` — true if the category has no subcategories (directly usable as a `byCategory` seed)
- `isAdult`, `isEco`
- `categoryUrl`, `sourceUrl`
- `recordType: "category"`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `byCategory` / `productDetails` / `categoryTree` / `reviews` |
| `searchQuery` | string | – | Free-text query, e.g. `iphone`, `ноутбук` (mode=search) |
| `categoryId` | string | – | Numeric category ID or category URL. Overrides `rootCategory` if both are set (mode=byCategory, categoryTree) |
| `rootCategory` | string | – | Pick one of 20 built-in top-level categories (mode=byCategory, categoryTree) |
| `productIds` | array | – | Product IDs or full product URLs (mode=productDetails, reviews) |
| `includeSimilarProducts` | boolean | `true` | Add a `similarProducts` array (up to 10 related items) to each record (mode=productDetails) |
| `reviewsLimit` | integer | `20` | Max reviews emitted per product ID, newest first (mode=reviews) |
| `sortBy` | string | `popularityDesc` | Popularity / price / rating / newest / discount, asc or desc (mode=search, byCategory) |
| `cityId` | integer | `1` | Delivery-city ID (affects delivery-date estimates only; mode=search, byCategory, productDetails) |
| `minPrice` | integer | – | Minimum price in RUB (mode=search, byCategory) |
| `maxPrice` | integer | – | Maximum price in RUB (mode=search, byCategory) |
| `minRating` | number | – | Minimum rating, 0-5 (mode=search, byCategory) |
| `inStockOnly` | boolean | `false` | Only emit in-stock products (mode=search, byCategory) |
| `excludeAdultItems` | boolean | `false` | Skip 18+ flagged products (mode=search, byCategory) |
| `leafCategoriesOnly` | boolean | `false` | Only emit categories with no subcategories (mode=categoryTree) |
| `maxItems` | integer | `10` | Hard cap on emitted records (all modes) |
| `proxyConfiguration` | object | AUTO group | Apify proxy configuration (all modes) |

Notes on filtering: `minPrice`/`maxPrice`/`minRating`/`inStockOnly` only exclude
products that actually carry the relevant field in mm.ru's response —
products missing price, rating, or stock-quantity data on the listing pass
the filter through unfiltered rather than being dropped, since they can't be
classified either way.

Sort note: `sortBy` is always sent to mm.ru's API as requested. Popularity,
price, and rating sorting are confirmed to reorder results server-side
(sponsored/promoted listings can still appear out of strict order — mm.ru's
own placement, not something this actor re-sorts). Newest and discount
sorting are accepted without an error but confirmed to have no effect —
mm.ru silently falls back to its default order for those two.

#### Example: search for a product

```json
{
  "mode": "search",
  "searchQuery": "iphone",
  "sortBy": "priceAsc",
  "inStockOnly": true,
  "maxItems": 20
}
````

#### Example: browse a built-in category, filtered by price and rating

```json
{
  "mode": "byCategory",
  "rootCategory": "10004",
  "minPrice": 1000,
  "maxPrice": 50000,
  "minRating": 4,
  "excludeAdultItems": true,
  "maxItems": 50
}
```

#### Example: fetch full product details by URL

```json
{
  "mode": "productDetails",
  "productIds": ["https://mm.ru/product/2560933"],
  "includeSimilarProducts": true,
  "maxItems": 10
}
```

#### Example: pull reviews for a product

```json
{
  "mode": "reviews",
  "productIds": ["2560933"],
  "reviewsLimit": 50,
  "maxItems": 50
}
```

#### Example: discover category IDs

```json
{
  "mode": "categoryTree",
  "leafCategoriesOnly": true,
  "maxItems": 200
}
```

### Use cases

- **Price monitoring** — track a product line's prices and discounts over time
- **Assortment research** — pull every product in a category to analyze the catalog
- **Competitive intelligence** — compare seller ratings, stock levels, and pricing across a niche
- **Catalog enrichment** — fetch full spec sheets (characteristics, SKUs, images) for a known product list
- **Category discovery** — list the full category tree with per-category product counts to plan what to scrape next
- **Voice of customer / sentiment analysis** — pull real review text, star ratings, and pros/cons for a known product list

### Other Russian marketplace actors by CrawlerBros

| Actor | URL |
|---|---|
| Citilink Scraper - Russian Electronics Store Products | <https://apify.com/crawlerbros/citilink-scraper> |
| DNS-Shop Scraper | <https://apify.com/crawlerbros/dns-shop-scraper> |
| Eldorado Scraper | <https://apify.com/crawlerbros/eldorado-scraper> |
| ETM Electrical Equipment Scraper | <https://apify.com/crawlerbros/etm-scraper> |
| Holodilnik.ru Scraper | <https://apify.com/crawlerbros/holodilnik-scraper> |
| Lemanapro Scraper | <https://apify.com/crawlerbros/lemanapro-scraper> |
| Magnit Market (mm.ru) Scraper (this actor) | <https://apify.com/crawlerbros/magnit-market-scraper> |
| Maxidom Scraper | <https://apify.com/crawlerbros/maxidom-scraper> |
| Megamarket.ru Scraper | <https://apify.com/crawlerbros/megamarket-scraper> |
| M.Video Scraper | <https://apify.com/crawlerbros/mvideo-scraper> |
| Onlinetrade.ru Scraper | <https://apify.com/crawlerbros/onlinetrade-scraper> |
| Ozon Scraper - Products, Categories & Search | <https://apify.com/crawlerbros/ozon-scraper> |
| Petrovich Building Materials Scraper | <https://apify.com/crawlerbros/petrovich-scraper> |
| Regard Scraper | <https://apify.com/crawlerbros/regard-scraper> |
| Russkiy Svet (rs24.ru) Electrical Equipment Scraper | <https://apify.com/crawlerbros/russkiysvet-scraper> |
| Technopark.ru Scraper - Products, Categories & Search | <https://apify.com/crawlerbros/technopark-scraper> |
| VseInstrumenti.ru Scraper | <https://apify.com/crawlerbros/vseinstrumenti-scraper> |
| Wildberries Scraper | <https://apify.com/crawlerbros/wildberries-scraper> |
| X-Com Shop Scraper | <https://apify.com/crawlerbros/xcom-shop-scraper> |
| Yandex Market Pro Scraper | <https://apify.com/crawlerbros/yandex-pro-scraper> |

### FAQ

**Do I need an mm.ru account or cookies?**
No. Every mode uses mm.ru's own public web-app APIs with no login required.

**Does this cost extra for proxy?**
No. mm.ru's APIs are reachable directly without a proxy; the actor uses the
free Apify AUTO proxy group by default for resilience, at no extra cost.

**Where do I find a category ID?**
Run the actor once with `mode=categoryTree` to get every category ID, title,
and product count in one dataset. Or browse mm.ru, open a category, and copy
the number from the URL (`https://mm.ru/category/10044` → ID is `10044`). Or
pick one of the 20 built-in top-level categories via `rootCategory`.

**Are prices in rubles?**
Yes — `priceRub` and related fields are converted to whole rubles for you,
regardless of the currency unit mm.ru's own API happens to return internally.

**Why do some products have no `rating` or `priceRub` field?**
mm.ru simply doesn't return that data for every listing (e.g. brand-new
products with no reviews yet). This actor omits fields it can't populate
rather than sending misleading zeros or nulls.

**Why does `productRatingBreakdown` not match the number of reviews returned?**
It always reflects mm.ru's full review set for the product, not just the
subset emitted for a given run (capped by `reviewsLimit`/`maxItems`).

**Is this affiliated with Magnit or mm.ru?**
No, this is an independent third-party actor that uses mm.ru's public APIs.
It is not affiliated with, endorsed by, or sponsored by Magnit or mm.ru.

**How fresh is the data?**
Every run fetches live data directly from mm.ru at the moment the actor
runs — nothing is cached or pre-scraped.

# Actor input Schema

## `mode` (type: `string`):

What to fetch.

## `searchQuery` (type: `string`):

Free-text search query, e.g. `iphone`, `ноутбук`, `телевизор`.

## `categoryId` (type: `string`):

A numeric mm.ru category ID (e.g. `10044`) or a full category URL (e.g. `https://mm.ru/category/10044`). Overrides `rootCategory` if both are set. In `byCategory` mode, fetches products in this category. In `categoryTree` mode, scopes the listed tree to this category's subtree (omit to list the entire tree). Use `rootCategory` below for a curated list of top-level categories, or find deeper category IDs by browsing mm.ru and copying the numeric ID from the URL -- or by running `categoryTree` mode first.

## `rootCategory` (type: `string`):

Pick one of mm.ru's 20 top-level categories. Ignored if `categoryId` is also set.

## `productIds` (type: `array`):

Numeric mm.ru product IDs (e.g. `2560933`) or full product URLs (e.g. `https://mm.ru/product/2560933`).

## `reviewsLimit` (type: `integer`):

Max number of reviews to emit per product ID, newest first. The `productRatingBreakdown`/`productReviewsTotal`/`productAvgRating` fields on every emitted review always reflect mm.ru's full review set for that product, not just this capped subset.

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

How to order results. Popularity/price/rating sorting is confirmed to reorder mm.ru's results server-side. Newest and discount sorting are accepted by mm.ru without error but confirmed to have no effect on result order (mm.ru silently falls back to its default order for these two) -- an upstream mm.ru API limitation.

## `cityId` (type: `integer`):

mm.ru delivery-city ID. Only affects delivery-date estimates on returned items, not which products match. Defaults to `1`.

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

Drop products cheaper than this, in Russian rubles.

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

Drop products more expensive than this, in Russian rubles.

## `minRating` (type: `number`):

Drop products rated below this (0-5 scale).

## `inStockOnly` (type: `boolean`):

Only emit products currently in stock.

## `excludeAdultItems` (type: `boolean`):

Skip products flagged as adult/18+ content.

## `includeSimilarProducts` (type: `boolean`):

Enrich each product detail record with a `similarProducts` array (up to 10 related items with price, rating, reviews, image) from mm.ru's own "similar products" API. Adds one extra request per product ID.

## `leafCategoriesOnly` (type: `boolean`):

Only emit categories with no subcategories (the ones actually usable as a `categoryId` seed for `byCategory` mode). Skips intermediate/parent nodes.

## `maxItems` (type: `integer`):

Hard cap on emitted records.

## `proxyConfiguration` (type: `object`):

mm.ru's public APIs are reachable without a proxy; the free Apify AUTO group is used by default for resilience at zero extra cost.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "iphone",
  "rootCategory": "",
  "productIds": [
    "https://mm.ru/product/2560933"
  ],
  "reviewsLimit": 5,
  "sortBy": "popularityDesc",
  "cityId": 1,
  "inStockOnly": false,
  "excludeAdultItems": false,
  "includeSimilarProducts": true,
  "leafCategoriesOnly": false,
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Dataset containing all scraped mm.ru products, categories (categoryTree mode), or customer reviews (reviews mode).

# 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 = {
    "mode": "search",
    "searchQuery": "iphone",
    "rootCategory": "",
    "productIds": [
        "https://mm.ru/product/2560933"
    ],
    "reviewsLimit": 5,
    "sortBy": "popularityDesc",
    "cityId": 1,
    "inStockOnly": false,
    "excludeAdultItems": false,
    "includeSimilarProducts": true,
    "leafCategoriesOnly": false,
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/magnit-market-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 = {
    "mode": "search",
    "searchQuery": "iphone",
    "rootCategory": "",
    "productIds": ["https://mm.ru/product/2560933"],
    "reviewsLimit": 5,
    "sortBy": "popularityDesc",
    "cityId": 1,
    "inStockOnly": False,
    "excludeAdultItems": False,
    "includeSimilarProducts": True,
    "leafCategoriesOnly": False,
    "maxItems": 10,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/magnit-market-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "search",
  "searchQuery": "iphone",
  "rootCategory": "",
  "productIds": [
    "https://mm.ru/product/2560933"
  ],
  "reviewsLimit": 5,
  "sortBy": "popularityDesc",
  "cityId": 1,
  "inStockOnly": false,
  "excludeAdultItems": false,
  "includeSimilarProducts": true,
  "leafCategoriesOnly": false,
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call crawlerbros/magnit-market-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=crawlerbros/magnit-market-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Magnit Market (mm.ru) Scraper",
        "description": "Scrape Magnit Market (mm.ru / Магнит Маркет) - Russia's marketplace by Magnit. Search products, browse by category, fetch full product details (prices, ratings, stock, images, seller info, characteristics and SKUs), or pull real customer reviews.",
        "version": "1.0",
        "x-build-id": "hcZNCf6nR3l9g0wI6"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/crawlerbros~magnit-market-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-crawlerbros-magnit-market-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/crawlerbros~magnit-market-scraper/runs": {
            "post": {
                "operationId": "runs-sync-crawlerbros-magnit-market-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/crawlerbros~magnit-market-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-crawlerbros-magnit-market-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "mode",
                    "proxyConfiguration"
                ],
                "properties": {
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "search",
                            "byCategory",
                            "productDetails",
                            "categoryTree",
                            "reviews"
                        ],
                        "type": "string",
                        "description": "What to fetch.",
                        "default": "search"
                    },
                    "searchQuery": {
                        "title": "Search query (mode=search)",
                        "type": "string",
                        "description": "Free-text search query, e.g. `iphone`, `ноутбук`, `телевизор`."
                    },
                    "categoryId": {
                        "title": "Category ID or URL (mode=byCategory, categoryTree)",
                        "type": "string",
                        "description": "A numeric mm.ru category ID (e.g. `10044`) or a full category URL (e.g. `https://mm.ru/category/10044`). Overrides `rootCategory` if both are set. In `byCategory` mode, fetches products in this category. In `categoryTree` mode, scopes the listed tree to this category's subtree (omit to list the entire tree). Use `rootCategory` below for a curated list of top-level categories, or find deeper category IDs by browsing mm.ru and copying the numeric ID from the URL -- or by running `categoryTree` mode first."
                    },
                    "rootCategory": {
                        "title": "Root category (mode=byCategory, categoryTree, convenience picker)",
                        "enum": [
                            "",
                            "10020",
                            "1821",
                            "10004",
                            "10012",
                            "10018",
                            "10005",
                            "10002",
                            "10016",
                            "10019",
                            "10014",
                            "10013",
                            "10003",
                            "10007",
                            "10006",
                            "10009",
                            "10015",
                            "10010",
                            "10011",
                            "10008",
                            "10017"
                        ],
                        "type": "string",
                        "description": "Pick one of mm.ru's 20 top-level categories. Ignored if `categoryId` is also set.",
                        "default": ""
                    },
                    "productIds": {
                        "title": "Product IDs or URLs (mode=productDetails, reviews)",
                        "type": "array",
                        "description": "Numeric mm.ru product IDs (e.g. `2560933`) or full product URLs (e.g. `https://mm.ru/product/2560933`).",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "reviewsLimit": {
                        "title": "Reviews per product (mode=reviews)",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Max number of reviews to emit per product ID, newest first. The `productRatingBreakdown`/`productReviewsTotal`/`productAvgRating` fields on every emitted review always reflect mm.ru's full review set for that product, not just this capped subset.",
                        "default": 20
                    },
                    "sortBy": {
                        "title": "Sort order (mode=search, byCategory)",
                        "enum": [
                            "popularityDesc",
                            "popularityAsc",
                            "priceAsc",
                            "priceDesc",
                            "ratingDesc",
                            "ratingAsc",
                            "newDesc",
                            "newAsc",
                            "discountDesc",
                            "discountAsc"
                        ],
                        "type": "string",
                        "description": "How to order results. Popularity/price/rating sorting is confirmed to reorder mm.ru's results server-side. Newest and discount sorting are accepted by mm.ru without error but confirmed to have no effect on result order (mm.ru silently falls back to its default order for these two) -- an upstream mm.ru API limitation.",
                        "default": "popularityDesc"
                    },
                    "cityId": {
                        "title": "City ID",
                        "minimum": 1,
                        "maximum": 999999,
                        "type": "integer",
                        "description": "mm.ru delivery-city ID. Only affects delivery-date estimates on returned items, not which products match. Defaults to `1`.",
                        "default": 1
                    },
                    "minPrice": {
                        "title": "Min price (RUB)",
                        "minimum": 0,
                        "maximum": 100000000,
                        "type": "integer",
                        "description": "Drop products cheaper than this, in Russian rubles."
                    },
                    "maxPrice": {
                        "title": "Max price (RUB)",
                        "minimum": 0,
                        "maximum": 100000000,
                        "type": "integer",
                        "description": "Drop products more expensive than this, in Russian rubles."
                    },
                    "minRating": {
                        "title": "Min rating",
                        "minimum": 0,
                        "maximum": 5,
                        "type": "number",
                        "description": "Drop products rated below this (0-5 scale)."
                    },
                    "inStockOnly": {
                        "title": "In stock only",
                        "type": "boolean",
                        "description": "Only emit products currently in stock.",
                        "default": false
                    },
                    "excludeAdultItems": {
                        "title": "Exclude adult items",
                        "type": "boolean",
                        "description": "Skip products flagged as adult/18+ content.",
                        "default": false
                    },
                    "includeSimilarProducts": {
                        "title": "Include similar products (mode=productDetails)",
                        "type": "boolean",
                        "description": "Enrich each product detail record with a `similarProducts` array (up to 10 related items with price, rating, reviews, image) from mm.ru's own \"similar products\" API. Adds one extra request per product ID.",
                        "default": true
                    },
                    "leafCategoriesOnly": {
                        "title": "Leaf categories only (mode=categoryTree)",
                        "type": "boolean",
                        "description": "Only emit categories with no subcategories (the ones actually usable as a `categoryId` seed for `byCategory` mode). Skips intermediate/parent nodes.",
                        "default": false
                    },
                    "maxItems": {
                        "title": "Max items",
                        "minimum": 1,
                        "maximum": 2000,
                        "type": "integer",
                        "description": "Hard cap on emitted records.",
                        "default": 10
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "mm.ru's public APIs are reachable without a proxy; the free Apify AUTO group is used by default for resilience at zero extra cost.",
                        "default": {
                            "useApifyProxy": true
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
