# ETM Electrical Equipment Scraper (`crawlerbros/etm-scraper`) Actor

Scrape ETM.ru - a major Russian B2B electrical-equipment retailer. Search products, browse categories, or fetch full product details: prices, specifications, images, certificates, package/logistics data, per-warehouse stock, and analog products.

- **URL**: https://apify.com/crawlerbros/etm-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** E-commerce, Automation, Integrations
- **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

## ETM Scraper

Scrape [ETM.ru](https://www.etm.ru) — one of Russia's largest B2B electrical-equipment
distributors, selling circuit breakers, cables, sockets, luminaires, tools, and
industrial-automation components. Search by keyword, browse any product
category, or pull full product details: price, specifications, images,
certificates, and stock availability.

### What this actor does

- **Four modes:** `search`, `byCategory`, `productDetails`, `categoryFacets`
- **Search** — free-text keyword search across ETM's full catalog
- **Category browsing** — paginate any category by its id/slug or catalog URL, optionally
  filtered to a single manufacturer/brand
- **Product details** — full specs, certificates, technical documents, package/logistics
  data, structured per-warehouse stock, and real analog/substitute products
- **Category/search facets** — the real subcategory and brand breakdown (with ETM's own
  live product counts per facet) for a category or search query, useful for discovering
  narrower categories/brands to feed back into `byCategory`
- **Empty fields are omitted** — every record only contains fields ETM actually returned

### Output per product

**Search / category listing records:**
- `productId`, `sku`, `name`
- `brand`, `brandSeries`, `brandSlug`
- `countryOfOrigin`, `packaging`, `unit`
- `price`, `currency`, `priceLabel` (e.g. "promotional price")
- `availabilityText`, `pickupText`
- `categoryCode`
- `thumbnailUrl`, `imageUrl`
- `isNew` — only present when ETM flags the product as newly listed
- `productUrl`
- `scrapedAt`

**Product-detail records** additionally include:
- `description`, `etmCode`, `packagingInfo`, `warranty`, `paymentMethods`
- `brandId` (ETM's internal manufacturer id)
- `priceRetail`, `cashbackAmount` (ETM loyalty cashback, RUB, when offered)
- `categoryPath[]`, `category`, `categoryUrl` — full breadcrumb trail
- `images[]` (full-size)
- `specifications[]` — `{name, value}` pairs (power, voltage, dimensions, IP rating, etc.)
- `certificates[]` — `{name, type, fileUrl}` (EAC/GOST conformity certificates, PDF)
- `technicalDocuments[]` — `{name, type, url}` (datasheets, manuals, PDF)
- `packages[]` — `{unit, quantity, weightKg, lengthM, widthM, heightM, volumeL}` per
  packaging unit (single item, factory box, pallet, etc.) — real logistics data for
  freight/shipping calculations
- `stockByWarehouse[]` — `{warehouseType, quantity, deliveryTime}` (or `{warehouseType,
  status}` for backorder/made-to-order items) — a structured breakdown per ETM
  warehouse network (supplier distribution center, local warehouse, etc.), not just
  one combined text label
- `analogs[]` — real substitute/equivalent products ETM itself recommends, shaped
  identically to a listing record (`productId`, `name`, `brand`, `price`,
  `productUrl`, …) so it's a drop-in swap for cross-brand sourcing
- `ratingValue`, `reviewCount` — only present when the product has actual customer
  reviews (omitted rather than emitted as `0`/`0` on the vast majority of products
  that have none yet)
- `discontinued`, `isNew`
- `externalArt`, `certificateName`, `relatedProducts[]` — occasionally present
  instead of `brandId`/`warranty`/`paymentMethods`/`packages[]`/`stockByWarehouse[]`/
  `ratingValue`/`analogs[]` on an older ETM page shape; whichever shape a given
  product page returns determines which of these two field groups you get
- `scrapedAt`

**Category/search facet records** (`mode=categoryFacets`) contain instead:
- `queryType` (`category` or `search`), `query` (the input you gave)
- `categoryCode`, `categoryName`, `categoryUrl`, `categoryPath[]` — the category itself
  and its breadcrumb (only for `category` queries; omitted for free-text `search` queries)
- `subcategories[]` — `{categoryCode, categoryName, categorySlug, productCount, categoryUrl}`
  for every subcategory ETM shows within the current result set, each with its own live
  product count
- `brands[]` — `{brandId, brandName, brandSlug, productCount, brandFilter}` for every
  manufacturer ETM shows within the current result set, each with its own live product
  count — `brandFilter` is a ready-to-use value for the `byCategory` mode's `brand` input
- `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | select | `search` | `search` / `byCategory` / `productDetails` / `categoryFacets` |
| `searchQuery` | string | `автомат` | Free-text query (mode=search, or mode=categoryFacets) |
| `category` | string | – | Category id+slug or catalog URL (mode=byCategory, or mode=categoryFacets) |
| `brand` | string | – | Optional brand filter, `<brandId>_<brandSlug>` or a brand-filtered catalog URL (mode=byCategory only) |
| `productUrls` | array | – | Product URLs or numeric IDs (mode=productDetails) |
| `maxItems` | int | `10` | Hard cap on emitted records (1–500) |
| `proxyConfiguration` | proxy | Residential (RU) | Required — see "Why is residential proxy required?" in the FAQ |

#### Example: search for circuit breakers

```json
{
  "mode": "search",
  "searchQuery": "автомат",
  "maxItems": 20
}
````

#### Example: browse a category

```json
{
  "mode": "byCategory",
  "category": "501010_avtomaticheskie_vykljuchateli",
  "maxItems": 50
}
```

#### Example: fetch specific products

```json
{
  "mode": "productDetails",
  "productUrls": [
    "https://www.etm.ru/cat/nn/7416742",
    "6187756"
  ]
}
```

#### Example: browse a category filtered to one brand

```json
{
  "mode": "byCategory",
  "category": "5004_avtomaticheskie_vykljuchateli",
  "brand": "432_iek",
  "maxItems": 50
}
```

#### Example: get subcategory/brand breakdown for a category

```json
{
  "mode": "categoryFacets",
  "category": "5004_avtomaticheskie_vykljuchateli"
}
```

### Use cases

- **Price monitoring** — track electrical-equipment pricing across brands
- **Catalog enrichment** — pull specifications and certificates for procurement systems
- **Market research** — analyze category assortment and brand coverage
- **Sourcing** — find in-stock alternatives across manufacturers for a given product class
- **Compliance** — verify EAC/GOST certification documents for imported equipment

### 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 (this actor) | <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 | <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

**Why does this actor require a residential proxy?** ETM.ru's own block page
states the reason: it geo-restricts access to Russian IP ranges. This isn't
a workaround for scraping etiquette — non-Russian visitors (VPN users
included) get the same block in a normal browser.

**Can I search in English?** ETM's catalog is Russian-language; search terms
should be in Russian (e.g. `автомат`, `кабель`, `розетка`) for relevant
results. Product data returned (names, specs) is also in Russian, matching
the site's audience.

**What does `category` accept?** Either the bare `<code>_<slug>` identifier
(e.g. `501010_avtomaticheskie_vykljuchateli`) or a full catalog URL from
etm.ru — both are accepted interchangeably.

**Why are some products missing `priceRetail`?** ETM shows a single price for
most SKUs; `priceRetail` only appears when the site returns a distinct retail
price alongside the wholesale/contract price.

**Are prices in rubles?** Yes — all `price` fields are in RUB (Russian rubles),
matching ETM's own currency.

**What if a product has no listed price?** ETM occasionally omits price for
discontinued or made-to-order items; the `price` field is omitted rather than
set to `0` or `null` in that case.

**What are `analogs[]`?** ETM's own substitute/equivalent-product
recommendations for the item (e.g. an alternative manufacturer's version of
the same lamp/breaker/socket) — useful for sourcing when a specific brand is
out of stock. Only present when ETM lists at least one analog for that SKU.

**What is `stockByWarehouse[]`?** ETM tracks availability per warehouse
network (its own distribution center vs. a local regional warehouse vs.
made-to-order), each with its own quantity and delivery estimate. This field
gives that breakdown as structured data instead of a single combined text
string; `availabilityText` still carries the human-readable summary for
convenience.

**How do I find the right `brand` value for `byCategory`?** Run
`mode=categoryFacets` on the category first — every entry in its `brands[]`
array includes a `brandFilter` value (e.g. `432_iek`) ready to paste into the
`brand` input.

**Does the `brand` filter work on `mode=search`?** No — it's only supported on
`mode=byCategory`. ETM's brand-filtered URL pattern is category-scoped
(`<categoryCode>_<categorySlug>-<brandId>_<brandSlug>`); free-text search
doesn't expose the same URL-level filter.

**Is the `brand` filter on `mode=byCategory` guaranteed accurate?** Yes — ETM's
own brand-filtered category URL isn't consistently honored server-side for
every category (it can silently return the full, unfiltered category page),
so the actor additionally checks every product's manufacturer against the
requested brand before including it in the output. You will only ever see
products from the brand you asked for, even on categories where ETM's URL
filter itself doesn't take effect (in that case the actor pages further into
the category, as needed, to keep finding matches). If a `brand` is requested
that genuinely has no products in the category (typo, wrong id, or a brand
that just isn't sold in that category — some ETM categories carry 10,000+
products across dozens of brands), the actor stops after several consecutive
fully-empty pages rather than paging through the entire category, and reports
this via the run's status message instead of silently returning nothing.

**What if I pass a `productUrls` numeric ID that doesn't exist?** ETM's own
product page for an unrecognized bare ID (e.g. `1`) can resolve to an
unrelated fallback product rather than a 404 — this is the site's own
behavior, not the actor's. The output record always reflects whichever real
product ETM actually returned for that URL/ID; double-check the returned
`productUrl` against what you intended if you're passing bare numeric IDs
that weren't sourced from a search/category/facets result first.

**Are `categoryFacets` product counts accurate?** Yes — `productCount` on each
subcategory/brand facet is ETM's own live count for that facet within the
current category or search result set, not an estimate.

# Actor input Schema

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

What to fetch from ETM.ru.

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

Free-text search term, e.g. автомат (circuit breaker), кабель (cable), розетка (socket).

## `category` (type: `string`):

Category id+slug (e.g. `501010_avtomaticheskie_vykljuchateli`) or a full catalog URL (e.g. `https://www.etm.ru/catalog/501010_avtomaticheskie_vykljuchateli`). Top-level examples: `010_elektrika_i_svet` (electrics & light), `030_vodosnabzhenie_i_vodootvedenie` (water supply), `050_instrument_i_osnastka` (tools), `080_sistemy_bezopasnosti` (security systems). For `mode=categoryFacets`, either this or `searchQuery` may be given.

## `brand` (type: `string`):

Restrict category browsing to one manufacturer. Accepts `<brandId>_<brandSlug>` (e.g. `432_iek`) or a full brand-filtered catalog URL (e.g. `https://www.etm.ru/catalog/5004_avtomaticheskie_vykljuchateli-432_iek`). Get real brand ids/slugs for a category from `mode=categoryFacets`'s `brands[].brandFilter` field first.

## `productUrls` (type: `array`):

Product page URLs (e.g. `https://www.etm.ru/cat/nn/7416742`) or bare numeric product IDs (e.g. `7416742`).

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

Hard cap on emitted records.

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

ETM.ru geo-blocks non-Russian IP addresses at the network edge (returns HTTP 444 / a "forbidden IP address, possible VPN" page). A residential proxy located in Russia is required to reach the site — see the README "Data Source" section for details.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "автомат",
  "category": "501010_avtomaticheskie_vykljuchateli",
  "productUrls": [
    "https://www.etm.ru/cat/nn/7416742"
  ],
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "RU"
  }
}
```

# Actor output Schema

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

Dataset containing all scraped ETM.ru products.

# 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": "автомат",
    "category": "501010_avtomaticheskie_vykljuchateli",
    "productUrls": [
        "https://www.etm.ru/cat/nn/7416742"
    ],
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "RU"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/etm-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": "автомат",
    "category": "501010_avtomaticheskie_vykljuchateli",
    "productUrls": ["https://www.etm.ru/cat/nn/7416742"],
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "RU",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/etm-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": "автомат",
  "category": "501010_avtomaticheskie_vykljuchateli",
  "productUrls": [
    "https://www.etm.ru/cat/nn/7416742"
  ],
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "RU"
  }
}' |
apify call crawlerbros/etm-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "ETM Electrical Equipment Scraper",
        "description": "Scrape ETM.ru - a major Russian B2B electrical-equipment retailer. Search products, browse categories, or fetch full product details: prices, specifications, images, certificates, package/logistics data, per-warehouse stock, and analog products.",
        "version": "1.0",
        "x-build-id": "6vOig2vDJdnUGdD2w"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/crawlerbros~etm-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-crawlerbros-etm-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~etm-scraper/runs": {
            "post": {
                "operationId": "runs-sync-crawlerbros-etm-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~etm-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-crawlerbros-etm-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",
                            "categoryFacets"
                        ],
                        "type": "string",
                        "description": "What to fetch from ETM.ru.",
                        "default": "search"
                    },
                    "searchQuery": {
                        "title": "Search query (mode=search)",
                        "type": "string",
                        "description": "Free-text search term, e.g. автомат (circuit breaker), кабель (cable), розетка (socket).",
                        "default": "автомат"
                    },
                    "category": {
                        "title": "Category (mode=byCategory / categoryFacets)",
                        "type": "string",
                        "description": "Category id+slug (e.g. `501010_avtomaticheskie_vykljuchateli`) or a full catalog URL (e.g. `https://www.etm.ru/catalog/501010_avtomaticheskie_vykljuchateli`). Top-level examples: `010_elektrika_i_svet` (electrics & light), `030_vodosnabzhenie_i_vodootvedenie` (water supply), `050_instrument_i_osnastka` (tools), `080_sistemy_bezopasnosti` (security systems). For `mode=categoryFacets`, either this or `searchQuery` may be given."
                    },
                    "brand": {
                        "title": "Brand filter (mode=byCategory, optional)",
                        "type": "string",
                        "description": "Restrict category browsing to one manufacturer. Accepts `<brandId>_<brandSlug>` (e.g. `432_iek`) or a full brand-filtered catalog URL (e.g. `https://www.etm.ru/catalog/5004_avtomaticheskie_vykljuchateli-432_iek`). Get real brand ids/slugs for a category from `mode=categoryFacets`'s `brands[].brandFilter` field first."
                    },
                    "productUrls": {
                        "title": "Product URLs or IDs (mode=productDetails)",
                        "type": "array",
                        "description": "Product page URLs (e.g. `https://www.etm.ru/cat/nn/7416742`) or bare numeric product IDs (e.g. `7416742`).",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxItems": {
                        "title": "Max items",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Hard cap on emitted records.",
                        "default": 10
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "ETM.ru geo-blocks non-Russian IP addresses at the network edge (returns HTTP 444 / a \"forbidden IP address, possible VPN\" page). A residential proxy located in Russia is required to reach the site — see the README \"Data Source\" section for details.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ],
                            "apifyProxyCountry": "RU"
                        }
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
