# 🧪 Yandex Maps Reviews Scraper — Full Review Export (`thenetaji/yandex-maps-reviews-scraper`) Actor

Export a Yandex Maps organisation's reviews with the stars, full text and its language, the reviewer's name and contributor level, likes and dislikes, attached photographs, and Yandex's own per-aspect summary of what reviewers praise and complain about.

- **URL**: https://apify.com/thenetaji/yandex-maps-reviews-scraper.md
- **Developed by:** [The Netaji](https://apify.com/thenetaji) (community)
- **Categories:** Business, Marketing, Automation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.21 / 1,000 reviews

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

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

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

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

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

# README

## Yandex Maps Reviews Scraper

Every written review of a Yandex Maps organisation, as a spreadsheet. Each row carries the
stars, the full text and the language it was written in, when it was last edited, whether
Yandex has pinned it, the reviewer's name, public id and contributor level, likes and
dislikes, the photographs attached to it — and Yandex's own per-aspect summary of what
reviewers praise and complain about, on every row.

The walk reaches the end. Yandex's review counts agree with themselves across page sizes —
6,001 reviews is 301 pages of 20 and 121 pages of 50 — so `maxItems: 0` genuinely means every
review rather than as many as the pager happens to hand over.

### Accepted input

`placeUrls` is required and takes one organisation per line, as either the numeric id
(`1018907821`) or the page address
(`https://yandex.com/maps/org/pushkin/1018907821/`). Both are accepted in the same list.
Every [Yandex Maps Scraper](https://apify.com/thenetaji/yandex-maps-scraper) row publishes
both, as `id` and as `url`, which is how the two Actors compose.

`reviewSort` chooses the ordering: newest first (the default), highest rated first, or lowest
rated first. **Yandex's own relevance ordering is deliberately not offered.** It answers with a
perfectly healthy response carrying no reviews at all, which would read as an organisation
with none — the worst possible failure on a reviews export, because it is indistinguishable
from a real answer.

`language` picks the language the response comes back in: English, Russian, Turkish or
Ukrainian. It does not translate the reviews themselves — each carries the language it was
written in, under `text_language`.

`maxItems` defaults to `100` and caps **each organisation separately**, so twenty
organisations with a cap of 100 returns up to 2,000 rows rather than 100 shared between them.
`0` means no limit.

There is no page-size input. It is always fifty, which is the largest that works: asking for a
hundred returns a body with neither reviews nor totals in it — not an error, just nothing.

```json
{
  "placeUrls": ["1018907821"],
  "reviewSort": "newest",
  "language": "en_US",
  "maxItems": 500
}
```

### Response fields

```json
{
  "place_id": "1018907821",
  "sort": "newest",
  "language": "en_US",
  "review_id": "aXaLK0yGz9E1MsCLBc8sMg",
  "business_id": "1018907821",
  "review_rating": 5,
  "review_text": "Прекрасное место, обязательно вернусь.",
  "text_language": "ru",
  "updated_at": "2026-08-01T10:12:00Z",
  "pinned": false,
  "author_name": "Мария",
  "author_public_id": "b5702370dd1141b080fb8693fe2991fc",
  "author_level": "Знаток города 7 уровня",
  "author_avatar_url_template": "https://avatars.mds.yandex.net/get-yapic/…/{size}",
  "likes": 12,
  "dislikes": 1,
  "photos": [],
  "total_reviews": 6001,
  "total_pages": 121,
  "page": 1,
  "page_size": 50,
  "reviews_remaining": 5951,
  "aspects": { "food": 4.8, "service": 4.5 }
}
```

Fields absent from a review are returned as null rather than omitted, so every row has the
same shape.

The review's own fields are namespaced away from the organisation's: `review_rating` is the
stars this review gave, and `place_id` is the organisation it belongs to. A dataset that used
`rating` for both would be unsortable.

`author_level` is Yandex's own contributor level for the reviewer, which is the cheapest signal
available for weighting an opinion. `author_reviews`-style totals are not published, because
Yandex does not state one here.

`author_avatar_url_template` contains a literal `{size}` and is **not a fetchable address**. It
is published as the template it is rather than filled in with a size this Actor picked, because
a picked size is a decision you did not make.

`aspects` is Yandex's own per-aspect summary for the organisation — the things reviewers praise
and complain about, scored. It describes the organisation rather than the review, so it repeats
on every row of one organisation.

`total_reviews` and `total_pages` are Yandex's own and they are consistent: 6,001 reviews is
301 pages of 20 and 121 pages of 50. That is why the walk trusts them, unlike the estimate on
the Maps search, which grows as you page.

### Behaviour on partial results

The walk goes to `total_pages` and stops there — never on "did this page come back full",
which is unreliable on any paged surface and would ask for a page past the end of every
organisation with a round number of reviews.

An organisation that no longer resolves is skipped with a line in the run log and the rest of
the list still runs. An entry that is not an organisation is skipped before any request is
made.

An organisation with no written reviews is a successful run with no rows, and the run log says
so explicitly. Coverage is deepest in Russia and the CIS: a Moscow restaurant carried 6,001
written reviews while Manhattan coffee shops carried none. That is real sparsity in Yandex's
data rather than a failed read, and the log line exists so an empty dataset is not mistaken for
one.

### Frequently asked questions

**How many reviews can I actually get?**
All of them. Yandex's review totals agree with themselves across page sizes, so a walk to
`total_pages` is a complete walk. That is unusual — the Maps search on the same site publishes
an estimate that grows as you page — and it is why `maxItems: 0` is a safe thing to set here.

**Why is the relevance ordering missing?**
Because it does not work. Yandex answers it with a healthy response carrying no reviews at all,
and an Actor that offered it would produce empty datasets that look exactly like organisations
with no reviews. Only measured orderings are offered.

**Does the ordering change which reviews I get?**
Only their order, on a complete walk. If you cap the run with `maxItems`, the ordering decides
which slice you keep — which is exactly when highest-rated or lowest-rated matters.

**The organisation's page says thousands of reviews and I got far fewer.**
Check which number you read. Yandex counts people who **rated** separately from people who
**wrote**, and only the second has text to export. [Yandex Maps Place
Scraper](https://apify.com/thenetaji/yandex-maps-place-scraper) publishes both as
`rating_count` and `review_count`, and `review_count` is the one this Actor reaches.

**Does `language` translate the reviews?**
No. It sets the language of the response around them; each review carries the language it was
actually written in, under `text_language`. Nothing here translates a review, because a
translated review attributed to its author is a quote they did not write.

**Where do I get organisation ids?**
From [Yandex Maps Scraper](https://apify.com/thenetaji/yandex-maps-scraper) — every row
publishes both an `id` and a `url`, and either works here.

**Is a Yandex account or API key required?**
No. No account, session cookie or key of any kind is supplied to the Actor or needed by it.

### Related Actors

[Yandex Maps Scraper](https://apify.com/thenetaji/yandex-maps-scraper) is where the ids come
from: organisations by name, category or address, centred anywhere in the world, with phone
numbers and opening hours already on each search row.

[Yandex Maps Place Scraper](https://apify.com/thenetaji/yandex-maps-place-scraper) reads one
organisation in full, and is where to check `review_count` before planning a large harvest.

[Yandex Search Scraper](https://apify.com/thenetaji/yandex-search-scraper) is the other half
of this site: web results with paid placements flagged on every row.

# Actor input Schema

## `placeUrls` (type: `array`):

Yandex Maps organisations, one per line — a numeric id such as 1018907821, or the page address, https://yandex.com/maps/org/pushkin/1018907821/. Every Maps search row publishes both an `id` and a `url`, and either is accepted here, which is how the runs compose without anything assembling an address.

## `reviewSort` (type: `string`):

How to order the reviews. Yandex's own relevance ordering is deliberately not offered: it answers with a healthy response carrying no reviews at all, which would read as an organisation with none.

## `language` (type: `string`):

The language titles, addresses and opening hours come back in. This is a closed set: a locale outside it is refused upstream rather than falling back to a default, so offering more would be offering a failure.

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

Maximum reviews to save for each organisation in the list. Set 0 for no limit — the walk reaches the end, because Yandex's review totals agree with themselves across page sizes. Reviews come 50 to a request.

## Actor input object example

```json
{
  "placeUrls": [
    "1018907821"
  ],
  "reviewSort": "newest",
  "language": "en_US",
  "maxItems": 50
}
```

# Actor output Schema

## `dataset` (type: `string`):

All records scraped by this run

# 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 = {
    "placeUrls": [
        "https://yandex.com/maps/org/pushkin/1018907821/"
    ],
    "reviewSort": "newest",
    "language": "en_US",
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("thenetaji/yandex-maps-reviews-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 = {
    "placeUrls": ["https://yandex.com/maps/org/pushkin/1018907821/"],
    "reviewSort": "newest",
    "language": "en_US",
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("thenetaji/yandex-maps-reviews-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "placeUrls": [
    "https://yandex.com/maps/org/pushkin/1018907821/"
  ],
  "reviewSort": "newest",
  "language": "en_US",
  "maxItems": 50
}' |
apify call thenetaji/yandex-maps-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,thenetaji/yandex-maps-reviews-scraper"
        }
    }
}

```

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

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/xJo3oa8QatxcOBX0f/builds/LC4h9k9bFOM1wmfK2/openapi.json
