# VkusVill Price & Stock Monitor (`sashaebashu/vkusvill-monitor`) Actor

Scrape & monitor the VkusVill (vkusvill.ru) grocery catalogue — price, customer rating and review count per product — and track what changed between runs: price moves, stock flips and products dropping out of the catalogue. Cheap datacenter proxy, no browser.

- **URL**: https://apify.com/sashaebashu/vkusvill-monitor.md
- **Developed by:** [Sasha Ebashu](https://apify.com/sashaebashu) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/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.

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

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

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

# README

## VkusVill Price & Stock Monitor

Scrapes the **VkusVill** grocery catalogue (vkusvill.ru) by category — product name, price, customer
rating, review count, brand and stock — and tracks how prices and availability change between runs.

Runs on Apify's cheap **datacenter** proxy. No browser, no residential proxy, no CAPTCHA solving.

### What you get

One row per product:

`store`, `productId`, `name`, `brand`, **`price`**, `currency`, `available`, **`rating`**,
`reviewsCount`, `description`, `image`, `url`, `categoryName`, `categoryPath`, `scrapedAt`

Every field is populated on every row in normal operation — a sample run returned 72/72 products
with all 15 fields filled, including a 4.6 rating off 644 reviews per item.

#### Monitor mode

Each row also gets `changeType`, `previousPrice`, `priceLow30`, `priceHigh30`, `firstSeenAt`,
`lastConfirmedAt`.

| `changeType` | Means |
|---|---|
| `new` | First time this product was seen in this scope |
| `price_up` / `price_down` | The price moved |
| `stock_change` | Availability flipped |
| `out_of_stock` | Was in the catalogue before and has now vanished from it |
| `unchanged` | Nothing moved |

**About `out_of_stock`:** a product that leaves the listing has gone out of stock or been delisted.
It is reported **once** (carrying its last known name, URL and price), then dropped from the
snapshot. This detection is **skipped** whenever the run did not cover every category in full — cut
short by the time budget, the cost cap, `Max results`, or a category that returned nothing — because
then "missing" would just mean "not reached". The log says so when that happens.

Turn on **Output only changed products** to drop `unchanged` rows — you then pay for and read only
what actually moved. History keeps updating for everything either way.

### Input

| Field | What it does |
|---|---|
| **Category URLs** | Categories to scrape. Paste from the browser (`https://vkusvill.ru/goods/sladosti-i-deserty/`) or just the slug. |
| **Crawl all categories** | Discover categories from VkusVill's sitemap (35 top-level categories) instead of listing them. |
| **Category filter** | With the sitemap crawl: keep only categories whose URL contains this text. Note the slugs are transliterated — dairy is `molochnye-produkty-yaytso`, not `moloko`. |
| **Max categories from sitemap** | Safety cap for the sitemap crawl. |
| **Max pages per category** | 24 products per page; the Actor stops on its own when a category ends. |
| **Max results** | Global cap. 0 = no limit. |
| **Monitor mode / Output only changed** | Change-tracking, described above. |

### Notes & limits

- **The listing is the data source.** VkusVill marks every product card up with schema.org
  **microdata** (`itemprop` attributes), which the Actor reads card by card — no product pages are
  fetched, which is what keeps it cheap.
- **Pagination is `?PAGEN_1=N`.** The more obvious `?page=N` is silently ignored by the site and
  returns page 1 again, so anything built on it would re-scrape the same 24 products.
- **One national catalogue.** VkusVill's sitemaps only ever expose the `msk` set and the category
  pages carry no city selector, so there is no per-city or per-store price dimension to configure —
  unlike some other Russian chains.
- The Actor honours your **Maximum cost per run**: it stops when the cap is reached and says so,
  instead of scraping pages the platform would discard.
- If a category yields nothing, it is reported in the log and saved to the `EMPTY_CATEGORIES` record
  rather than passing silently.

# Actor input Schema

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

VkusVill catalogue categories to scrape. Paste the URL from your browser (https://vkusvill.ru/goods/sladosti-i-deserty/) or just the slug. Leave empty and turn on "Crawl all categories" to take the whole catalogue.

## `crawlSitemap` (type: `boolean`):

Discover categories from VkusVill's own sitemap instead of listing them by hand. Combine with the filter and limit below.

## `categoryFilter` (type: `string`):

Only used with "Crawl all categories". Keeps categories whose URL contains this text, e.g. `moloko`, `sladosti`, `ovoshchi`.

## `maxCategoriesFromSitemap` (type: `integer`):

Safety cap for the sitemap crawl. 0 = no limit.

## `maxPagesPerCategory` (type: `integer`):

Each page holds 24 products. The Actor stops earlier by itself when a category runs out of pages.

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

Stop after this many products in total. 0 = no limit.

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

Parallel page requests.

## `monitorMode` (type: `boolean`):

Compare against the previous run for the SAME categories and label every row: new / price\_up / price\_down / stock\_change / out\_of\_stock / unchanged, plus previous price, 30-day low & high, and first-seen / last-confirmed stamps.

## `onlyChanges` (type: `boolean`):

Monitor mode only — drop the `unchanged` rows so you pay for and read only what moved. History is still updated for everything.

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

VkusVill works over Apify's cheap datacenter proxy — the default is fine.

## Actor input object example

```json
{
  "categoryUrls": [
    "https://vkusvill.ru/goods/sladosti-i-deserty/"
  ],
  "crawlSitemap": false,
  "maxCategoriesFromSitemap": 30,
  "maxPagesPerCategory": 10,
  "maxItems": 0,
  "maxConcurrency": 6,
  "monitorMode": false,
  "onlyChanges": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `changes` (type: `string`):

No description

## `details` (type: `string`):

No description

# 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 = {
    "categoryUrls": [
        "https://vkusvill.ru/goods/sladosti-i-deserty/"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("sashaebashu/vkusvill-monitor").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 = {
    "categoryUrls": ["https://vkusvill.ru/goods/sladosti-i-deserty/"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("sashaebashu/vkusvill-monitor").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "categoryUrls": [
    "https://vkusvill.ru/goods/sladosti-i-deserty/"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call sashaebashu/vkusvill-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sashaebashu/vkusvill-monitor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/YaKBp2aqlanrbho52/builds/7NfhfWKCj4dqcdxl9/openapi.json
