# Russian Marketplace Product Card & Specs Scraper (`isolovyev/ru-product-cards`) Actor

Scrape product cards from Russian online stores: title, image links and full specifications as name-value pairs, exactly as the store publishes them. Give it product URLs, or product names and it finds the direct link itself. Optional ready-to-publish card structure.

- **URL**: https://apify.com/isolovyev/ru-product-cards.md
- **Developed by:** [Ivan Solovyev](https://apify.com/isolovyev) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.00 / 1,000 basic cards

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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.

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

## 🏷️ Russian Marketplace Product Card & Specs Scraper

<table width="100%">
<tr>
<td style="padding:24px 28px;background:#EEF2FF;border:1px solid #C7D2FE;border-top:4px solid #4F46E5;border-radius:12px">
<span style="font-size:23px;font-weight:800;color:#1E1B4B;line-height:1.3">Product cards from Russian stores: title, image links and full specifications as name-value pairs.</span><br>
<span style="font-size:15px;color:#4B5563;line-height:1.6">Give it the product URLs you already have, or just product names - the Actor finds the direct card link itself. Specifications come back exactly as the store publishes them, so normalisation stays on your side.</span>
</td>
</tr>
</table>

<table width="100%">
<tr>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #E0E7FF;border-radius:10px 0 0 10px;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#4338CA">🔗 URLs or names</span><br>
<span style="font-size:12px;color:#57534E">Feed a list of product URLs, or let the Actor search by product name</span>
</td>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #E0E7FF;border-left:none;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#4338CA">📋 Full specs</span><br>
<span style="font-size:12px;color:#57534E">From a handful to 80+ name-value pairs per card, unchanged from the source</span>
</td>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #E0E7FF;border-left:none;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#4338CA">🖼️ Image links</span><br>
<span style="font-size:12px;color:#57534E">Direct links to the store's own images, service icons filtered out</span>
</td>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #E0E7FF;border-left:none;border-radius:0 10px 10px 0;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#4338CA">💳 Pay per result</span><br>
<span style="font-size:12px;color:#57534E">Cards that could not be scraped are not billed at all</span>
</td>
</tr>
</table>

### ✨ Overview

**Scrape product cards from Russian online stores and marketplaces - one Actor, one unified schema.**

Feed the Actor a list of product URLs (the primary way to use it) or a list of product names. For
names it finds the direct card link itself. For every card it returns the title, links to the
product images and the full specification table as `name - value` pairs, exactly as the store
publishes them. There is no mapping to a common dictionary: you normalise on your side, which is
what catalogue pipelines usually need.

Optionally the Actor also emits a ready-to-publish card structure: brand, category, cleaned
attributes and a draft description assembled strictly from the specifications.

Russian stores serve data only from a Russian IP, so a residential proxy with country RU is
required. It is set by default.

### 🚀 How to use

1. Put your product URLs into **startUrls**, one per line, as plain strings.
2. Or leave that empty and put product names into **queries** instead.
3. Pick the stores in **platforms**.
4. Keep **proxyConfiguration** on Apify Residential proxy with country RU.
5. Run it, then pull the dataset over the API.

```json
{
  "startUrls": [
    "https://www.regard.ru/product/748719/noutbuk-lenovo-thinkpad-e16-gen-2/",
    "https://www.dns-shop.ru/product/8bd39b9ce0d0ed20/noutbuk-lenovo-v15-g4/"
  ],
  "fetchSpecs": true
}
````

### 📤 Output

One dataset item per product card:

| Field | What it holds |
|---|---|
| `title` | product name as published by the store |
| `images` | direct links to the product images |
| `imageCount` | how many images were found |
| `specs` | specifications as `[{name, value}]`, unchanged from the source |
| `specCount` | number of specification rows |
| `url` | direct link to the product card |
| `platform` | which store the card came from |
| `price` | price where the store exposes it |
| `billedAs` | which tariff this card was billed under |
| `card` | optional ready-to-publish structure: brand, category, cleaned attributes, draft description |

### ⚙️ Input

| Field | Meaning |
|---|---|
| `startUrls` | direct product URLs, one per line. **Primary mode**, covers 16 of the 19 stores listed below. |
| `queries` | product names to search for, when you do not have the URLs. **Available for a subset of stores**, see Supported stores. |
| `platforms` | which stores to query. |
| `maxLinksPerQuery` | how many cards to take per search query. |
| `fetchSpecs` | also fetch the specifications tab where a store keeps it on a separate page. |
| `buildCards` | also emit the ready-to-publish card structure. |
| `proxyConfiguration` | residential proxy, country RU. Required by the stores. |

### 🛒 Supported stores

Coverage differs from store to store: some serve their data over an ordinary request, others sit
behind industrial anti-bot protection and need a stronger channel. The list below is what the Actor
scrapes today, not a wish list.

#### Two ways to give the Actor work

The Actor accepts either direct product URLs (`startUrls`) or product names to look up (`queries`).
These are not equivalent: a direct URL works on 16 of the 19 stores, while search by name
additionally needs the store's own search to be open and is available on 13 of them.

| Store | Direct URL | Search by name |
|---|---|---|
| Wildberries | yes | yes |
| Regard | yes | yes |
| Citilink | yes | yes |
| DNS | yes | yes |
| Magnit Market | yes | yes |
| Technopark | yes | yes |
| Holodilnik.ru | yes | yes |
| Megamarket | yes | yes |
| VseInstrumenti | yes | yes |
| Petrovich | yes | yes |
| Lemana PRO | yes | yes |
| ETM | yes | yes |
| RS24 | yes | yes |
| Ozon | not yet | not yet |
| Yandex Market | yes | no |
| XCOM | yes | no |
| M.Video | yes | no |
| Eldorado | not yet | not yet |
| OnlineTrade | not yet | not yet |

**When a store cannot be searched by name**, the run logs `поиск по названию не поддерживается`
for that store, produces no card and charges nothing. The rest of the input keeps running.

**RS24** sits behind protection that only a real browser gets through, so its cards take noticeably longer than the rest. **Yandex Market, XCOM and M.Video** are scraped by direct URL; their name search returns no product cards. **Ozon** answers roughly twice out of eight attempts, so it is not offered as working. **Eldorado** lets a request through roughly once in five attempts, so it is not offered as working. **OnlineTrade** is closed behind an image challenge. Listed so the coverage is honest, not as a promise.

### 💳 Pricing

Billing is per result, and the rate depends on how hard the card was to get:

| Event | When it applies |
|---|---|
| **Basic card** | the card was scraped over an ordinary request |
| **Premium card** | the store is protected and a paid access channel was required |
| **Nothing charged** | the card could not be scraped: empty results are never billed |

The same store can fall into either tier on different days, because protection on these platforms
gets switched on and off. The Actor always tries the cheap route first. Every dataset item carries
`billedAs`, so an invoice can be checked line by line.

### ⚠️ Notes

- Specifications are returned as published. Two stores describing the same product will disagree on
  wording, and that is intentional: mapping them onto one dictionary is a decision only you can make.
- Depth varies a lot by store. Measured on live runs, one card carries from about three pairs to
  just over eighty; a short table means the store publishes little, not that rows were dropped.
- Image links point at the store's own CDN. Files are not copied or re-hosted.

### 🇷🇺 RU / На русском

**Карточки товаров с российских интернет-магазинов: название, ссылки на фото и полные
характеристики парами «свойство - значение», ровно как их публикует магазин.**

Задачу можно ставить двумя способами, и они не равнозначны. Основной - **прямыми ссылками на
товар** (`startUrls`): вы отдаёте список адресов, по одному в строке, и получаете по каждому
карточку; этот способ работает по 16 магазинам из 19, перечисленных ниже. Второй -
**списком названий** (`queries`), тогда актор сам находит прямую ссылку на карточку; для этого
нужен ещё и открытый поиск на стороне магазина, поэтому способ доступен не везде.

**Если магазин не принимает поиск по названию**, в журнал прогона уходит строка
«поиск по названию не поддерживается», карточка не создаётся и плата не списывается. Остальные
записи вашего списка при этом обрабатываются как обычно.

- **Характеристики как есть.** Никакого приведения к общему словарю: два магазина опишут один
  товар по-разному, и это намеренно. Нормализация остаётся на вашей стороне, потому что решение,
  как сводить формулировки, можете принять только вы.
- **Ссылки на фото** ведут на хранилище самого магазина, файлы не копируются. Служебная графика
  (значки условий доставки, баннеры, снимки из отзывов) в выдачу не попадает.
- **Список ссылок терпит грязь.** Пробелы от копирования, схема заглавными, адрес без схемы,
  повторы и метки перехода - всё приводится к рабочему виду, повтор снимается и оплачивается один
  раз. Мусорная строка, посторонний домен и ссылка на обзор вместо товара пропускаются
  с пометкой, прогон не прерывается.
- **Глубина сильно разная.** По замерам на живых прогонах на одну карточку приходится от трёх
  пар до восьмидесяти с небольшим. Короткая таблица означает, что магазин публикует мало,
  а не что строки потерялись при сборе.
- **Готовая структура карточки** по желанию: бренд, категория, очищенные атрибуты и черновик
  описания, собранный строго из характеристик.

**Охват площадок различается.** Часть магазинов отдаёт данные обычным запросом, часть закрыта
промышленной защитой и требует усиленного канала.

| Магазин | По прямой ссылке | По названию товара |
|---|---|---|
| Wildberries, Регард, Ситилинк, DNS, Магнит Маркет | да | да |
| Технопарк, Холодильник.ру, Мегамаркет, ЭТМ, RS24 | да | да |
| ВсеИнструменты, Петрович, Лемана ПРО | да | да |
| Яндекс.Маркет, XCOM, М.Видео | да | нет |
| Ozon, Эльдорадо, OnlineTrade | пока нет | пока нет |

Три площадки в предпоследней строке собираются по прямым ссылкам, а их поиск по названию
карточек не возвращает. RS24 закрыт защитой, которую проходит только настоящий браузер, поэтому
карточки с него собираются дольше остальных. Эльдорадо пропускает обращение примерно раз из пяти, Ozon - дважды из восьми,
поэтому рабочими они не заявлены. У OnlineTrade страница закрыта проверкой с картинкой. Перечислено,
чтобы охват был честным, а не как обещание.

**Тарификация по результату.** Обычный тариф - карточка снята простым запросом; усиленный - магазин
закрыт защитой и понадобился платный канал доступа. Если карточку снять не удалось, не
списывается ничего. Один и тот же магазин в разные дни может попасть в любой из двух тарифов:
защита на площадках включается и выключается, а актор всегда пробует дешёвый путь первым. У каждой
записи проставлено поле `billedAs`, так что счёт проверяется построчно.

Российские магазины отдают данные только с российского адреса, поэтому нужен резидентный прокси со
страной RU - он стоит по умолчанию.

### 🔗 Все наши акторы для данных по России, Казахстану и СНГ

<span style="font-size:14px;color:#4B5563">Одна линейка для маркетплейсов, розничных сетей, госзакупок и проверки контрагентов - соседний актор открывается одним кликом по карточке.</span>

<table width="100%">
<tr>
<td style="padding:0;width:33.33%;background:#FFFFFF;border:1px solid #E0E7FF;border-top:3px solid #4F46E5;border-radius:10px 0 0 10px;vertical-align:top">
<a href="https://apify.com/isolovyev/marketplace-seller-leads" style="display:block;padding:14px 12px;text-decoration:none">
<span style="font-size:13px;font-weight:800;color:#4338CA">🛍️ Лиды продавцов маркетплейсов</span><br>
<span style="font-size:11px;color:#57534E">продавцы WB / Ozon / Яндекс.Маркет / Kaspi с ИНН и ОГРН</span>
</a>
</td>
<td style="padding:0;width:33.33%;background:#FFFFFF;border:1px solid #E0E7FF;border-left:none;border-top:3px solid #4F46E5;vertical-align:top">
<a href="https://apify.com/isolovyev/zakupki-tender-monitor" style="display:block;padding:14px 12px;text-decoration:none">
<span style="font-size:13px;font-weight:800;color:#4338CA">📄 Тендеры 44-ФЗ / 223-ФЗ</span><br>
<span style="font-size:11px;color:#57534E">госзакупки, нацрежим, реестр российского ПО</span>
</a>
</td>
<td style="padding:0;width:33.33%;background:#FFFFFF;border:1px solid #E0E7FF;border-left:none;border-top:3px solid #4F46E5;border-radius:0 10px 10px 0;vertical-align:top">
<a href="https://apify.com/isolovyev/ru-counterparty-check" style="display:block;padding:14px 12px;text-decoration:none">
<span style="font-size:13px;font-weight:800;color:#4338CA">🔍 Проверка контрагента по ИНН</span><br>
<span style="font-size:11px;color:#57534E">5 источников, скоринг риска</span>
</a>
</td>
</tr>
<tr>
<td style="padding:0;width:33.33%;background:#FFFFFF;border:1px solid #E0E7FF;border-top:3px solid #4F46E5;border-radius:10px 0 0 10px;vertical-align:top">
<a href="https://apify.com/isolovyev/ru-software-registry-check" style="display:block;padding:14px 12px;text-decoration:none">
<span style="font-size:13px;font-weight:800;color:#4338CA">🏛️ Реестр российского ПО</span><br>
<span style="font-size:11px;color:#57534E">проверка по ИНН + досье заявителя</span>
</a>
</td>
<td style="padding:0;width:33.33%;background:#FFFFFF;border:1px solid #E0E7FF;border-left:none;border-top:3px solid #4F46E5;vertical-align:top">
<a href="https://apify.com/isolovyev/ru-marketplaces-price-monitor" style="display:block;padding:14px 12px;text-decoration:none">
<span style="font-size:13px;font-weight:800;color:#4338CA">📈 Цены на маркетплейсах</span><br>
<span style="font-size:11px;color:#57534E">WB / Ozon / Яндекс.Маркет / Avito, трекинг цены</span>
</a>
</td>
<td style="padding:0;width:33.33%;background:#FFFFFF;border:1px solid #E0E7FF;border-left:none;border-top:3px solid #4F46E5;border-radius:0 10px 10px 0;vertical-align:top">
<a href="https://apify.com/isolovyev/kaspi-price-monitor" style="display:block;padding:14px 12px;text-decoration:none">
<span style="font-size:13px;font-weight:800;color:#4338CA">🇰🇿 Цены и позиции на Kaspi.kz</span><br>
<span style="font-size:11px;color:#57534E">Казахстан, позиция в выдаче и цена</span>
</a>
</td>
</tr>
<tr>
<td style="padding:0;width:33.33%;background:#FFFFFF;border:1px solid #E0E7FF;border-top:3px solid #4F46E5;border-radius:10px 0 0 10px;vertical-align:top">
<a href="https://apify.com/isolovyev/ru-retail-chains-scraper" style="display:block;padding:14px 12px;text-decoration:none">
<span style="font-size:13px;font-weight:800;color:#4338CA">🏪 Розничные сети РФ</span><br>
<span style="font-size:11px;color:#57534E">Магнит, Метро, М.Видео, Дикси, Глобус, Купер в единой схеме</span>
</a>
</td>
<td style="padding:0;width:33.33%;background:#FFFFFF;border:1px solid #E0E7FF;border-left:none;border-top:3px solid #4F46E5;vertical-align:top">
<a href="https://apify.com/isolovyev/ru-retail-chains-extended" style="display:block;padding:14px 12px;text-decoration:none">
<span style="font-size:13px;font-weight:800;color:#4338CA">🛒 Ашан: цены и остатки</span><br>
<span style="font-size:11px;color:#57534E">цена, старая цена, остаток в штуках, рейтинг</span>
</a>
</td>
<td style="padding:14px 12px;width:33.33%;background:#EEF2FF;border:1px solid #C7D2FE;border-left:none;border-top:3px solid #4F46E5;border-radius:0 10px 10px 0;vertical-align:top">
<span style="font-size:13px;font-weight:800;color:#1E1B4B">🏷️ Карточки товаров</span><br>
<span style="font-size:11px;color:#57534E">название, фото и характеристики с 17 магазинов по ссылке или названию</span><br>
<span style="font-size:10px;font-weight:800;color:#4F46E5;letter-spacing:0.5px">● ВЫ ЗДЕСЬ</span>
</td>
</tr>
</table>

### 💬 Вопросы и поддержка

Нашли ошибку или есть вопрос? Откройте тикет на вкладке **Issues** этого актора.

***

# Actor input Schema

## `startUrls` (type: `array`):

Direct links to product cards, one per line. This is the PRIMARY mode and it works for every store the Actor supports. Plain strings are expected (https://shop.ru/product/123). Use 'queries' instead when you only know the product name.

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

Product names or models. The Actor finds the direct card link by name and then scrapes it. This mode is NOT available for every store: where a store cannot be searched by name, the run logs 'поиск по названию не поддерживается' for that store, creates no card and charges nothing. See the Coverage section of the README for the per-store list.

## `platforms` (type: `array`):

Which Russian stores to query. Direct links work for every store listed here; search by product name works for a subset (see README). Keep to one store for the fastest run.

## `speedLane` (type: `string`):

Split the queue by how long a store takes. Platform usage is billed by run TIME, so one slow store makes the whole run expensive: measured 27 Jul, a mixed run cost about $0.024 per card against $0.0045 for fast stores only. Run the two lanes separately to cut that. Slow lane: Megamarket, VseInstrumenti, RS24, Eldorado, Petrovich, OnlineTrade, Ozon.

## `maxLinksPerQuery` (type: `integer`):

How many product cards to scrape per query per store.

## `buildCards` (type: `boolean`):

Also emit a normalized card structure (brand, category, cleaned attributes, draft description) built from the parsed data. Off by default: it is an extra paid event on top of each card.

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

Russian stores serve data only from a Russian IP. A residential-grade proxy with country RU is required.

## `method1Key` (type: `string`):

Credentials for method 1 (link lookup by product name). Needed for stores without an open search page. Provided by the operator.

## `method1Account` (type: `string`):

Account identifier that goes with the method 1 key.

## `method2User` (type: `string`):

Credentials for method 2 (page retrieval for stores behind industrial protection). Provided by the operator.

## `method2Pass` (type: `string`):

Password that goes with the method 2 user.

## `method3User` (type: `string`):

Credentials for method 3 (fallback page retrieval). Provided by the operator.

## `method3Pass` (type: `string`):

Password that goes with the method 3 user.

## `bridgeUrl` (type: `string`):

Address of the operator relay used for stores whose network path is unreachable from the cloud.

## `bridgeToken` (type: `string`):

Shared secret for the relay.

## Actor input object example

```json
{
  "startUrls": [],
  "queries": [
    "ноутбук Lenovo LOQ",
    "чайник Bosch"
  ],
  "platforms": [
    "regard",
    "holodilnik"
  ],
  "speedLane": "all",
  "maxLinksPerQuery": 3,
  "buildCards": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "RU"
  }
}
```

# 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 = {
    "startUrls": [],
    "queries": [
        "ноутбук Lenovo"
    ],
    "platforms": [
        "regard",
        "holodilnik"
    ],
    "maxLinksPerQuery": 3,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "RU"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("isolovyev/ru-product-cards").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 = {
    "startUrls": [],
    "queries": ["ноутбук Lenovo"],
    "platforms": [
        "regard",
        "holodilnik",
    ],
    "maxLinksPerQuery": 3,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "RU",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("isolovyev/ru-product-cards").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 '{
  "startUrls": [],
  "queries": [
    "ноутбук Lenovo"
  ],
  "platforms": [
    "regard",
    "holodilnik"
  ],
  "maxLinksPerQuery": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "RU"
  }
}' |
apify call isolovyev/ru-product-cards --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=isolovyev/ru-product-cards",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Russian Marketplace Product Card & Specs Scraper",
        "description": "Scrape product cards from Russian online stores: title, image links and full specifications as name-value pairs, exactly as the store publishes them. Give it product URLs, or product names and it finds the direct link itself. Optional ready-to-publish card structure.",
        "version": "0.1",
        "x-build-id": "1GNsYn8okd37Z5eT3"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/isolovyev~ru-product-cards/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-isolovyev-ru-product-cards",
                "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/isolovyev~ru-product-cards/runs": {
            "post": {
                "operationId": "runs-sync-isolovyev-ru-product-cards",
                "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/isolovyev~ru-product-cards/run-sync": {
            "post": {
                "operationId": "run-sync-isolovyev-ru-product-cards",
                "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",
                "properties": {
                    "startUrls": {
                        "title": "Product URLs",
                        "type": "array",
                        "description": "Direct links to product cards, one per line. This is the PRIMARY mode and it works for every store the Actor supports. Plain strings are expected (https://shop.ru/product/123). Use 'queries' instead when you only know the product name.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "queries": {
                        "title": "Product names to search",
                        "type": "array",
                        "description": "Product names or models. The Actor finds the direct card link by name and then scrapes it. This mode is NOT available for every store: where a store cannot be searched by name, the run logs 'поиск по названию не поддерживается' for that store, creates no card and charges nothing. See the Coverage section of the README for the per-store list.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "platforms": {
                        "title": "Stores / marketplaces",
                        "type": "array",
                        "description": "Which Russian stores to query. Direct links work for every store listed here; search by product name works for a subset (see README). Keep to one store for the fastest run.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "ozon",
                                "wildberries",
                                "yandexmarket",
                                "megamarket",
                                "mvideo",
                                "eldorado",
                                "dns",
                                "citilink",
                                "regard",
                                "xcom",
                                "technopark",
                                "onlinetrade",
                                "holodilnik",
                                "mm",
                                "vseinstrumenti",
                                "petrovich",
                                "lemanapro",
                                "rs24",
                                "etm"
                            ],
                            "enumTitles": [
                                "Ozon",
                                "Wildberries",
                                "Yandex Market",
                                "Megamarket",
                                "M.Video",
                                "Eldorado",
                                "DNS",
                                "Citilink",
                                "Regard",
                                "Xcom",
                                "Technopark",
                                "OnlineTrade",
                                "Holodilnik",
                                "Magnit Market",
                                "VseInstrumenti",
                                "Petrovich",
                                "Leroy Merlin (Lemana)",
                                "RS24",
                                "ETM"
                            ]
                        },
                        "default": [
                            "regard",
                            "citilink",
                            "holodilnik"
                        ]
                    },
                    "speedLane": {
                        "title": "Speed lane",
                        "enum": [
                            "all",
                            "fast",
                            "slow"
                        ],
                        "type": "string",
                        "description": "Split the queue by how long a store takes. Platform usage is billed by run TIME, so one slow store makes the whole run expensive: measured 27 Jul, a mixed run cost about $0.024 per card against $0.0045 for fast stores only. Run the two lanes separately to cut that. Slow lane: Megamarket, VseInstrumenti, RS24, Eldorado, Petrovich, OnlineTrade, Ozon.",
                        "default": "all"
                    },
                    "maxLinksPerQuery": {
                        "title": "Cards per query",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "How many product cards to scrape per query per store.",
                        "default": 3
                    },
                    "buildCards": {
                        "title": "Build ready-to-publish card",
                        "type": "boolean",
                        "description": "Also emit a normalized card structure (brand, category, cleaned attributes, draft description) built from the parsed data. Off by default: it is an extra paid event on top of each card.",
                        "default": false
                    },
                    "proxyConfiguration": {
                        "title": "Proxy",
                        "type": "object",
                        "description": "Russian stores serve data only from a Russian IP. A residential-grade proxy with country RU is required.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ],
                            "apifyProxyCountry": "RU"
                        }
                    },
                    "method1Key": {
                        "title": "Method 1 key (optional)",
                        "type": "string",
                        "description": "Credentials for method 1 (link lookup by product name). Needed for stores without an open search page. Provided by the operator."
                    },
                    "method1Account": {
                        "title": "Method 1 account (optional)",
                        "type": "string",
                        "description": "Account identifier that goes with the method 1 key."
                    },
                    "method2User": {
                        "title": "Method 2 user (optional)",
                        "type": "string",
                        "description": "Credentials for method 2 (page retrieval for stores behind industrial protection). Provided by the operator."
                    },
                    "method2Pass": {
                        "title": "Method 2 password (optional)",
                        "type": "string",
                        "description": "Password that goes with the method 2 user."
                    },
                    "method3User": {
                        "title": "Method 3 user (optional)",
                        "type": "string",
                        "description": "Credentials for method 3 (fallback page retrieval). Provided by the operator."
                    },
                    "method3Pass": {
                        "title": "Method 3 password (optional)",
                        "type": "string",
                        "description": "Password that goes with the method 3 user."
                    },
                    "bridgeUrl": {
                        "title": "Relay address (optional)",
                        "type": "string",
                        "description": "Address of the operator relay used for stores whose network path is unreachable from the cloud."
                    },
                    "bridgeToken": {
                        "title": "Relay secret (optional)",
                        "type": "string",
                        "description": "Shared secret for the relay."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
