# Yandex Maps Scraper - Businesses, Places & Leads (`abotapi/yandex-maps-scraper`) Actor

Scrape Yandex Maps businesses and places by keyword or URL for lead generation, research and market analysis. Парсер Яндекс Карт: сбор данных о компаниях и местах по запросу или ссылке для поиска клиентов, исследований и анализа рынка.

- **URL**: https://apify.com/abotapi/yandex-maps-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Features:** Limited permissions
- **Stats:** 6 total users, 0 monthly users, 98.4% runs succeeded, 2 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.80 / 1,000 business records

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Yandex Maps Scraper: Business Listings, Contact Info & Reviews

Yandex Maps Scraper turns Yandex Maps into structured business data. Search by keyword or paste direct business, category or search links, or mix both in one run, to get names, addresses, categories, ratings, contact details, opening hours, price levels, photos and reviews for cafes, shops, offices and any other place listed on Yandex Maps. Export the results to JSON, CSV or Excel, or pull them straight into your app through the API.

### Why This Scraper?

- **Two ways to find businesses.** Search by keyword (with the location resolved to map coordinates automatically) or paste direct Yandex Maps links. Both feeds merge into one dataset.
- **Rich business records.** Contact info, categories, ratings, price levels, opening hours, traffic patterns and up to 10 photo URLs per business, read straight from the source page.
- **Reviews on demand.** Turn on business details to pull recent reviews per business, with billing that scales with how many you request.
- **Cost-aware pagination.** Cap how many businesses each search saves and how many result pages it walks, so you only pay for what you collect.
- **Built for schedules.** Incremental mode returns only new and changed businesses on recurring runs, and resume continues one interrupted walk without repeating work.
- **A refused run fails loudly** instead of quietly returning an empty dataset.

### Use Cases

- **Local business directories and lead lists:** build a database of cafes, shops or service providers in a city or district, complete with contact info.
- **Competitive and market research:** compare ratings, review counts and price levels for a category of business across a region.
- **Reputation monitoring:** pull recent reviews for specific businesses to track sentiment over time.
- **Location intelligence:** use coordinates, addresses and traffic patterns to study business density and foot traffic by area.
- **Recurring data feeds:** schedule the actor and use incremental mode to get only new, changed or closed businesses since the last run.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live record.

| Field | Example |
| --- | --- |
| `source` / `id` | `"yandex_maps"` / `"123456789012"` |
| `title` / `seoname` | `"Riverside Coffee House"` / `"riverside_coffee_house"` |
| `url` | `"https://yandex.com/maps/org/123456789012/"` |
| `searchString` / `rank` | `"coffee shop"` / `1` |
| `address` / `addressParts` | `"Springfield, Example Ave 42"` / `{ "country": "Sampleland", "street": "Example Ave", "house": "42" }` |
| `postalCode` / `country` | `"12345"` / `"Sampleland"` |
| `categoryName` / `categories` | `"Coffee shop"` / `["Coffee shop", "Bakery"]` |
| `phone` / `phones` / `website` | `"+1 555 0101"` / `["+1 555 0101"]` / `"https://example-coffeehouse.example"` |
| `totalScore` / `reviewsCount` | `4.6` / `128` |
| `workingTime` / `schedule` | `{ "text": "daily, 8:00 AM to 8:00 PM", "openNow": true }` / opening hours per weekday |
| `priceLevels` / `trafficHistogram` | `{ "price_category": "above average", "average_bill": "1500-1800 RUB" }` / hourly visit intensity per weekday (when available) |
| `photosCount` / `photoUrls` / `logoUrl` | `24` / up to 10 photo URLs / business logo image URL |
| `awards` / `reviewAspects` / `placeSummary` | Yandex award, review topics with positive / neutral / negative counts, and the short place summary Yandex shows on the card (each only when Yandex publishes it) |
| `chainName` / `chainId` / `chainSlug` | the chain a branch belongs to (chain members only); `chainBranchesInCity` adds its branch count when Chain branch count is on |
| `menu` | menu block: source, last update, total items and items with title, description, price, currency, volume and photo; the card shows the popular items, Full menu returns the whole menu |
| `productCatalog` / `promo` | showcase offers or services with prices, and the active promotion (only when published) |
| `phonesDetailed` / `socialLinks` | each phone with dialable form, type, label and extension; social links with their readable handle |
| `additionalAddress` / `categoryIds` | floor or mall detail, and category ids matching the category names |
| `panorama` / `entrances` | street panorama (id, position, heading, tilt, preview) and mapped entrance points |
| `bookingPartner` / `bookingAvailability` / `bookingLinks` | table-booking partner, whether slots are offered, and booking links |
| `legalInfo` / `references` | legal entity name and tax id as shown for advertising labelling (companies only: sole-proprietor details of private individuals are never included), and partner-system ids |
| `photos` / `posts` | photo gallery (Max photos per business) and owner posts and events (Max posts per business) |
| `reviews` | recent reviews (author, rating, text, date, plus photos with ids and credit, videos, translations and language name); details mode only |
| `location` / `scrapedAt` | `{ "lat": 40.71, "lng": -74.01 }` / `"2026-09-30T12:00:00.000Z"` |
| `raw` | the matched source object, when Include raw payload is on |

The Output tab offers four views of the same rows: Businesses, Contacts & leads (phones, website), Reviews (the nested reviews list per business) and Changes since last run (incremental mode: change type and changed fields).

Incremental mode adds `changeType` (`NEW`, `UPDATED`, `UNCHANGED`, `REAPPEARED` or `EXPIRED`), `changedFields`, `firstSeenAt` and `lastSeenAt` to every row; see Resume and recurring updates below.

### How to Use

1. Pick a way to find businesses: enter **Search terms** with a **Location** (keyword search), add **Start URLs** (direct business, category or search page links), or both in the same run.
2. Turn **Business details & reviews** on or off, and set **Max reviews per business** if you want reviews.
3. Set **Max results per search** and **Max pages per search** to control run size and cost, then click **Start**.
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Search for coffee shops in a city:**

```json
{
  "searchStringsArray": ["coffee shop"],
  "location": "Austin, TX",
  "maxResultsPerSearch": 20
}
```

**Scrape one business page directly:**

```json
{
  "startUrls": [
    { "url": "https://yandex.com/maps/org/example_bakery/123456789/" }
  ],
  "fetchDetails": true,
  "maxReviews": 20
}
```

**Supported Start URL shapes** (the Start URLs field is pre-filled with one example of each, and the default run scrapes them):

| Shape | Example |
| --- | --- |
| Business page (slug + id) | `https://yandex.com/maps/org/no_plates_coffee/124606085044/` |
| Business page (id only) | `https://yandex.com/maps/org/124606085044/` |
| Business reviews tab | `https://yandex.com/maps/org/no_plates_coffee/124606085044/reviews/` |
| Russian host | `https://yandex.ru/maps/org/no_plates_coffee/124606085044/` |
| Search with position | `https://yandex.com/maps/?ll=-74.006%2C40.7128&z=12&text=coffee` |
| Search, text only | `https://yandex.com/maps/?text=restaurants` |
| City search | `https://yandex.com/maps/202/new-york/search/restaurants/` |
| City category | `https://yandex.com/maps/202/new-york/category/coffee_shop/` |

**Behaviour change:** leaving Start URLs untouched now scrapes one example of each shape above (previously nothing). Clear the field to run keyword search only. The `.ru` host and the `/reviews/` tab are normalised to the business page. Short share links (`/maps/-/CODE`) and `/maps/search/{query}/` without a city id are not supported: they are skipped with a warning in the log and the run is treated as an incomplete scan. If **Location** cannot be resolved to coordinates, a warning is logged and the keyword search runs without a map position.

**Filtered search-card-only rows (Wi-Fi, Italian or Japanese cuisine; faster, cheaper):**

```json
{
  "searchStringsArray": ["restaurants"],
  "location": "Moscow",
  "filters": ["wi_fi", "type_cuisine:italian_cuisine,japanese_cuisine"],
  "maxResultsPerSearch": 50,
  "fetchDetails": false
}
```

**Recurring monitoring of a search:**

```json
{
  "searchStringsArray": ["car wash"],
  "location": "Manchester",
  "incrementalMode": true,
  "emitExpired": true
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/yandex-maps-scraper").call(run_input={"searchStringsArray": ["coffee shop"], "location": "Austin, TX"})
for business in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(business["title"], business.get("address"))
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/yandex-maps-scraper').call({ searchStringsArray: ['coffee shop'], location: 'Austin, TX' });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### How Max results per search shapes a walk

Each search term or start URL is walked page by page (25 businesses per results page) until it reaches the site's own last page, or until the business cards scanned so far for that search reach **Max results per search**, whichever comes first. That cap counts every card scanned, not unique rows actually saved: a card repeated on the page, a business already saved earlier in the same run by another search term or start URL, and a business already collected by the run you are resuming all count toward it. So an overlapping search, or a resumed run, can stop paging with far fewer new rows than **Max results per search** calls for. Raise **Max results per search** (raising **Max pages per search** alone does not help here), or run overlapping searches in separate runs, to collect the rest.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run or dataset ID and the actor skips every business id already collected there (before opening its page, saving or billing it), so you don't pay twice. An ID that matches no run or dataset you can read fails the run immediately instead of starting over. Skipped businesses still count toward **Max results per search**, so raise it on the resumed run.
- **Incremental mode** (`incrementalMode`) is for recurring runs over the same search. Each business is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED` or `EXPIRED` (only after a run that scanned the whole tracked scope, and only with `emitExpired`). `stateKey` names or shares the stored baseline; leaving it empty auto-derives one from the search settings, so two runs with identical search settings share a baseline automatically. With incremental mode off, output is exactly as before.
- **EXPIRED rows are not capped by Max results per search.** On a run that reaches the natural end of its tracked scope, every previously tracked business missing from this run gets one EXPIRED row, however many that is.
- **EXPIRED safety:** a business is only marked EXPIRED after a run that walked every search from its first results page to the natural end of the results. A search or start URL that was refused, a page that could not be read, a walk cut by Max pages, a start URL that begins at `?page=2` or later, and a Max results cap all make the run an incomplete scan, so no EXPIRED rows are produced and the saved baseline for those businesses is kept. A search whose businesses are all unchanged is a normal result, not a failure.
- **Ignore fields when detecting changes:** `ignoreFieldsForChanges` lists fields that must not count as a change (for example `photosCount`, or a dotted path such as `addressParts.street` for nested fields). They stay in the output rows but never turn a business into UPDATED or show in `changedFields`. Already ignored by default: `scrapedAt`, `rank`, `raw`, `searchString`, `reviews` (use `reviewsCount` to see new reviews), `trafficHistogram`, `photoUrls`, `logoUrl`. Changing the list never causes a one-time wave of UPDATED rows.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape: the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each business, not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify → Settings → Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `searchStringsArray` | array | `["restaurants"]` | Search queries to run on Yandex Maps. |
| `startUrls` | array | (none) | Direct Yandex Maps targets to scrape, one search, category, or business page per row. |
| `location` | string | `New York, NY` | Free-text region for keyword searches, resolved to map coordinates. Ignored by `startUrls`. |
| `filters` | array | `[]` | Yandex Maps own filters, one per row: `good_place`, `wi_fi`, `open_now`, or `type_cuisine:italian_cuisine,japanese_cuisine`. Several rows combine. Applied to keyword searches and to search or category URLs without their own filter; a filter Yandex does not apply is reported in the run log. |
| `maxResultsPerSearch` | integer | `20` | Maximum businesses to save per search. |
| `maxPagesPerSearch` | integer | `0` | Results pages walked per search (25 businesses each). `0` = no page cap; Max results per search is the only cap that stops a walk early. |
| `includeRaw` | boolean | `false` | Include the matched raw source object in each dataset row, for debugging. |
| `fetchDetails` | boolean | `true` | Open each business page and read its reviews, opening hours and photo totals. Off = faster, search-card-only rows. |
| `maxReviews` | integer | `3` | Per-business review count when Business details & reviews is on. Billing scales with volume. |
| `maxPhotos` | integer | `0` | Photos to list per business (needs Business details & reviews). `0` = off. |
| `maxPosts` | integer | `0` | Owner posts and events to list per business (needs Business details & reviews). `0` = off. |
| `includeMenu` | boolean | `false` | Return the whole menu from the business menu tab instead of the popular-items preview. About 0.8 MB of page transfer per business with a menu. |
| `includeChainBranches` | boolean | `false` | Add the chain's branch count in the same city to chain members (one chain page of about 1.8 MB per distinct chain per run). |
| `language` | string | `en-US` | Browser locale. Currently informational: pages are always requested in English. |
| `resumeFromRunId` | string | (none) | Paste a previous run ID or dataset ID to continue a full-catalogue walk across separate runs. |
| `incrementalMode` | boolean | `false` | Recurring monitoring: reruns the same search and classifies each business as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED. |
| `stateKey` | string | (none) | Optional. Name the incremental baseline explicitly. Auto-derived from the search settings when left empty. |
| `emitUnchanged` | boolean | `false` | Incremental mode only. Also save UNCHANGED businesses. |
| `emitExpired` | boolean | `false` | Incremental mode only. Also save a row for businesses no longer found, once the walk reaches its natural end. |
| `ignoreFieldsForChanges` | array | `[]` | Incremental mode only. Fields (dotted paths allowed) that never count as a change. |
| `proxyConfiguration` | object | Datacenter (`useApifyProxy: true`) | Connection settings used for all requests. Pick the residential group if the datacenter pool is refused. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each business to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which item pages are created. |
| `maxNotifyListings` | integer | (none set; falls back to 200) | Cap on businesses written to each connector per run. Does not affect the dataset. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live record.

```json
{
  "source": "yandex_maps",
  "id": "123456789012",
  "title": "Riverside Coffee House",
  "scrapedAt": "2026-09-30T12:00:00.000Z",
  "searchString": "coffee shop",
  "rank": 1,
  "url": "https://yandex.com/maps/org/123456789012/",
  "address": "Springfield, Example Ave 42",
  "addressParts": { "country": "Sampleland", "street": "Example Ave", "house": "42" },
  "postalCode": "12345",
  "country": "Sampleland",
  "categoryName": "Coffee shop",
  "categories": ["Coffee shop", "Bakery"],
  "phone": "+1 555 0101",
  "phones": ["+1 555 0101"],
  "website": "https://example-coffeehouse.example",
  "totalScore": 4.6,
  "reviewsCount": 128,
  "workingTime": { "text": "daily, 8:00 AM to 8:00 PM", "openNow": true, "openNowText": "Open now" },
  "priceLevels": { "price_category": "above average", "average_bill": "1500-1800 RUB" },
  "photosCount": 24,
  "photoUrls": ["https://avatars.mds.yandex.net/example/orig"],
  "logoUrl": "https://avatars.mds.yandex.net/example/80x80",
  "seoname": "riverside_coffee_house",
  "reviews": [
    { "authorName": "Alex Sample", "authorLevel": "Level 3 Local Expert", "rating": 5, "text": "Cozy corner, good pastries.", "date": "2026-09-01T12:00:00Z" }
  ],
  "location": { "lat": 40.71, "lng": -74.01 }
}
```

### Plan Requirement

The default connection works out of the box, and the actor rotates connections automatically when one is refused. For large or frequent runs, or if the default pool is refused often, the residential group under **Connection** gives more headroom.

### FAQ

#### How much does it cost?

You pay per business saved, plus the detail-enrichment charge when **Business details & reviews** is on: 1 unit per business whose page was read, plus 1 unit per started block of 10 reviews delivered (10 reviews = 1 extra unit, 25 = 3; the default of 3 reviews = 1 unit in total). Photos, posts, the full menu and the chain branch count are read from the same business page visit and are included in that detail-enrichment unit: turning them on adds no extra charge, only extra page transfer through your proxy. Rows that are unchanged and not saved are not charged. The **Pricing** tab shows the current rates. Use **Max results per search** to cap the cost of any run.

#### Is it legal to scrape Yandex Maps?

This actor collects only publicly available business listing data. You are responsible for how you use it: follow Yandex's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Reviews and photos may be subject to third-party rights.

#### What's the difference between Resume and Incremental mode?

Resume (`resumeFromRunId`) continues ONE specific interrupted run from a pasted run or dataset ID; it does not remember anything between separate scheduled runs. Incremental mode reruns the SAME search on a schedule and reports only what changed since the last run. Combining both is only safe on the very first incremental run, before a baseline exists.

#### Can I get only new, changed or closed businesses on a schedule?

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. Turn on **Include expired businesses in output** to also get a row for businesses that disappeared from the results, once a run completes a full scan of the tracked search.

#### Why did I get fewer businesses than Max results per search?

The cap is checked against business cards scanned for that search, not unique rows saved. If the page repeats a business, a business was already collected earlier in the same run by another search term or start URL, or it was already collected by the run you are resuming, it still counts, and the walk can stop before delivering the full count. Raise **Max results per search** to collect more. In incremental mode, UNCHANGED businesses are also left out of the dataset unless **Include unchanged businesses in output** is on.

#### Why did my run fail instead of returning an empty dataset?

If the maps search refuses every request across all the given inputs, the run stops with a clear message so "nothing found" is never confused with "nothing could be read". Run it again in a few minutes, or with a different connection setting. If only some searches or URLs could be read, you still get what was found.

One known quirk: the same "No results" failure currently also appears when a run saves zero rows for a benign reason, namely an incremental run where nothing changed (every business UNCHANGED and no EXPIRED rows) or a resumed run where every business found was already collected. The scan itself worked, and in incremental mode the log still shows "state saved for the next scheduled run". Turn on **Include unchanged businesses in output** if a scheduled incremental run must never end as failed.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

### 🔗 Want more Yandex data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🧩 <a href="https://apify.com/abotapi/yandex-serp-scraper"><b>Yandex Search Scraper</b></a><br>Scrape Yandex web, image and video search results with URLs, snippets and organic...</td><td>📇 <a href="https://apify.com/abotapi/google-maps-scraper"><b>Google Maps Scraper</b></a><br>Extract business data from Google Maps at scale. Get names, addresses, phone numbers...</td></tr>
<tr><td>📇 <a href="https://apify.com/abotapi/2gis-places-scraper"><b>2GIS</b></a><br>Extract business and place data from 2GIS.com at scale. Get names, addresses, phones...</td><td>✈️ <a href="https://apify.com/abotapi/naver-map-scraper"><b>Naver Map Scraper</b></a><br>Scrape Naver Map places by keyword or URL: names, categories, ratings, phones, addresses...</td></tr>
<tr><td>📇 <a href="https://apify.com/abotapi/bbb-org-scraper"><b>BBB Scraper</b></a><br>Scrape bbb.org (Better Business Bureau, USA &amp; Canada) business profiles: BBB rating...</td><td>📇 <a href="https://apify.com/abotapi/hipages-business-scraper"><b>HiPages Scraper</b></a><br>Scrape business listings from HiPages Australia by category, location, or URL. Extract...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/yandex-maps-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

## `searchStringsArray` (type: `array`):

Search queries to run on Yandex Maps.

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

Direct Yandex Maps targets - one per row: business page (with or without slug, .com, .ru or m. mobile host, a ?ol=biz\&oid= link, or its /reviews/ tab), a ?text= search URL, a city search /maps/{geoId}/{city}/search/{query}/ (percent-encoded queries and ?page=N supported) or a city category page /maps/{geoId}/{city}/category/{rubric}/. Unsupported shapes (short /maps/-/ share links, /maps/search/{query}/ without a city id) are skipped with a warning. The default scrapes one example of each shape.

## `location` (type: `string`):

Free-text region for keyword searches (resolved to map coordinates via the open OpenStreetMap geocoder). Ignored by startUrls.

## `filters` (type: `array`):

Native Yandex Maps filters applied to keyword searches and to search / category / ?text= URLs that do not already carry their own filter. One per row: "good_place" (yes/no filter), "wi_fi", "open_now", or "type_cuisine:italian_cuisine,japanese_cuisine" (list filter with one or more values). Several rows combine. Available ids depend on the category (restaurants offer good_place, wi_fi, business_lunch, takeaway, type_cuisine and more). A filter Yandex does not apply is reported in the run log. Leave empty for no filtering.

## `maxResultsPerSearch` (type: `integer`):

Maximum businesses to save per search.

## `maxPagesPerSearch` (type: `integer`):

SERP pages walked per search (25 businesses each). 0 = no page cap - Max results per search is the only cap that stops a walk early.

## `includeRaw` (type: `boolean`):

Include the matched raw Yandex response object in each dataset row for debugging.

## `fetchDetails` (type: `boolean`):

Open each business page and read its reviews, opening hours and photo totals. Turn OFF for fast, search-card-only rows

## `maxReviews` (type: `integer`):

Per-business review count when details mode is on. Billing scales with volume: the detail-enrichment surcharge bills 1 unit per enriched row plus 1 unit per started block of 10 reviews (10 reviews = 1 extra unit, 25 = 3, 1000 = 101) - heavy review pulls bill their transfer.

## `maxPhotos` (type: `integer`):

Photos to list per business (id, url, size, tags, credit) when details mode is on. 0 = off. Adds one read per business, included in the existing detail-enrichment unit; no extra charge.

## `maxPosts` (type: `integer`):

Owner posts and events to list per business (text, publication time, photos) when details mode is on. 0 = off. Adds one or more reads per business, included in the existing detail-enrichment unit; no extra charge.

## `includeMenu` (type: `boolean`):

Read the business menu tab and return the whole menu (all categories, prices, volumes, photos, source, last update) instead of the popular-items preview on the card. Restaurants and shops that publish a menu only. Adds about 0.8 MB of page transfer per business with a menu; included in the existing detail-enrichment unit, no extra charge.

## `includeChainBranches` (type: `boolean`):

For businesses that belong to a chain, add how many branches the chain has in the same city (one chain page read of about 1.8 MB per distinct chain per run). Included in the existing detail-enrichment unit, no extra charge.

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

Browser locale.

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

Apify Proxy settings used for all requests. Datacenter (no group) by default; pick RESIDENTIAL when the datacenter pool is refused.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue a full-catalogue walk across separate runs. Businesses already collected there (matched by business id) are skipped, so this run only saves the new ones. Leave empty for a normal fresh run. Distinct from Incremental mode below — this continues one specific interrupted run, not recurring monitoring.

## `incrementalMode` (type: `boolean`):

When ON, this actor remembers the previous run of the SAME search (see State key) and classifies each business as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED. UNCHANGED and EXPIRED rows are not saved to the dataset unless enabled below — this is what keeps a scheduled recurring run cheap. Default OFF (every run returns every business, as today). Combining with Resume from a previous run above is only safe on the very first incremental run (no baseline yet) — once a baseline exists, remove Resume from a previous run or set a different State key.

## `stateKey` (type: `string`):

Manually name the incremental baseline for this search, e.g. "nyc-coffee". Leave empty to auto-derive one from the search settings — two runs with the exact same search settings then share a baseline automatically. Set this explicitly if you want to run several DIFFERENT search configs against the SAME named baseline, or keep configs that happen to match fully separate.

## `emitUnchanged` (type: `boolean`):

When ON, incremental mode also saves businesses with no detected change (changeType="UNCHANGED") to the dataset, instead of only NEW/UPDATED/REAPPEARED. This returns — and bills for — every business every run, defeating the point of incremental mode for most use cases. Default OFF.

## `emitExpired` (type: `boolean`):

When ON, incremental mode also saves a row (changeType="EXPIRED") for each previously-tracked business that no longer appears, once this run reaches the natural end of the search results (skipped on a capped, resumed, or otherwise incomplete run — those cannot tell "gone" apart from "not reached yet"). This returns — and bills for — an extra row per disappeared business. Default OFF.

## `ignoreFieldsForChanges` (type: `array`):

Field names that must NOT count as a change in incremental mode, e.g. photosCount or addressParts.street (dotted paths reach nested fields, including inside lists). Ignored fields stay in the output rows; they just never turn an unchanged business into UPDATED and never appear in changedFields. Already ignored by default: scrapedAt, rank, raw, searchString, reviews (use reviewsCount to detect new reviews), trafficHistogram, photoUrls, logoUrl.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per business (title + key fields), not the full JSON — the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on businesses written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "searchStringsArray": [
    "restaurants"
  ],
  "startUrls": [
    {
      "url": "https://yandex.com/maps/org/no_plates_coffee/124606085044/"
    },
    {
      "url": "https://yandex.com/maps/org/124606085044/"
    },
    {
      "url": "https://yandex.com/maps/org/no_plates_coffee/124606085044/reviews/"
    },
    {
      "url": "https://yandex.ru/maps/org/no_plates_coffee/124606085044/"
    },
    {
      "url": "https://yandex.com/maps/?ll=-74.006%2C40.7128&z=12&text=coffee"
    },
    {
      "url": "https://yandex.com/maps/?text=restaurants"
    },
    {
      "url": "https://yandex.com/maps/202/new-york/search/restaurants/"
    },
    {
      "url": "https://yandex.com/maps/202/new-york/category/coffee_shop/"
    },
    {
      "url": "https://yandex.com/maps/?ol=biz&oid=1018907821"
    },
    {
      "url": "https://yandex.com/maps/213/moscow/search/%D0%BA%D0%BE%D1%84%D0%B5/"
    },
    {
      "url": "https://yandex.com/maps/213/moscow/search/coffee/?page=2"
    },
    {
      "url": "https://m.yandex.com/maps/org/192990200894/"
    }
  ],
  "location": "New York, NY",
  "maxResultsPerSearch": 20,
  "maxPagesPerSearch": 0,
  "includeRaw": false,
  "fetchDetails": true,
  "maxReviews": 3,
  "maxPhotos": 0,
  "maxPosts": 0,
  "includeMenu": false,
  "includeChainBranches": false,
  "language": "en-US",
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": []
}
```

# Actor output Schema

## `businesses` (type: `string`):

No description

## `contacts` (type: `string`):

No description

## `reviews` (type: `string`):

No description

## `changes` (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 = {
    "searchStringsArray": [
        "restaurants"
    ],
    "startUrls": [
        {
            "url": "https://yandex.com/maps/org/no_plates_coffee/124606085044/"
        },
        {
            "url": "https://yandex.com/maps/org/124606085044/"
        },
        {
            "url": "https://yandex.com/maps/org/no_plates_coffee/124606085044/reviews/"
        },
        {
            "url": "https://yandex.ru/maps/org/no_plates_coffee/124606085044/"
        },
        {
            "url": "https://yandex.com/maps/?ll=-74.006%2C40.7128&z=12&text=coffee"
        },
        {
            "url": "https://yandex.com/maps/?text=restaurants"
        },
        {
            "url": "https://yandex.com/maps/202/new-york/search/restaurants/"
        },
        {
            "url": "https://yandex.com/maps/202/new-york/category/coffee_shop/"
        },
        {
            "url": "https://yandex.com/maps/?ol=biz&oid=1018907821"
        },
        {
            "url": "https://yandex.com/maps/213/moscow/search/%D0%BA%D0%BE%D1%84%D0%B5/"
        },
        {
            "url": "https://yandex.com/maps/213/moscow/search/coffee/?page=2"
        },
        {
            "url": "https://m.yandex.com/maps/org/192990200894/"
        }
    ],
    "location": "New York, NY",
    "maxResultsPerSearch": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    },
    "ignoreFieldsForChanges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/yandex-maps-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 = {
    "searchStringsArray": ["restaurants"],
    "startUrls": [
        { "url": "https://yandex.com/maps/org/no_plates_coffee/124606085044/" },
        { "url": "https://yandex.com/maps/org/124606085044/" },
        { "url": "https://yandex.com/maps/org/no_plates_coffee/124606085044/reviews/" },
        { "url": "https://yandex.ru/maps/org/no_plates_coffee/124606085044/" },
        { "url": "https://yandex.com/maps/?ll=-74.006%2C40.7128&z=12&text=coffee" },
        { "url": "https://yandex.com/maps/?text=restaurants" },
        { "url": "https://yandex.com/maps/202/new-york/search/restaurants/" },
        { "url": "https://yandex.com/maps/202/new-york/category/coffee_shop/" },
        { "url": "https://yandex.com/maps/?ol=biz&oid=1018907821" },
        { "url": "https://yandex.com/maps/213/moscow/search/%D0%BA%D0%BE%D1%84%D0%B5/" },
        { "url": "https://yandex.com/maps/213/moscow/search/coffee/?page=2" },
        { "url": "https://m.yandex.com/maps/org/192990200894/" },
    ],
    "location": "New York, NY",
    "maxResultsPerSearch": 20,
    "proxyConfiguration": { "useApifyProxy": True },
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/yandex-maps-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 '{
  "searchStringsArray": [
    "restaurants"
  ],
  "startUrls": [
    {
      "url": "https://yandex.com/maps/org/no_plates_coffee/124606085044/"
    },
    {
      "url": "https://yandex.com/maps/org/124606085044/"
    },
    {
      "url": "https://yandex.com/maps/org/no_plates_coffee/124606085044/reviews/"
    },
    {
      "url": "https://yandex.ru/maps/org/no_plates_coffee/124606085044/"
    },
    {
      "url": "https://yandex.com/maps/?ll=-74.006%2C40.7128&z=12&text=coffee"
    },
    {
      "url": "https://yandex.com/maps/?text=restaurants"
    },
    {
      "url": "https://yandex.com/maps/202/new-york/search/restaurants/"
    },
    {
      "url": "https://yandex.com/maps/202/new-york/category/coffee_shop/"
    },
    {
      "url": "https://yandex.com/maps/?ol=biz&oid=1018907821"
    },
    {
      "url": "https://yandex.com/maps/213/moscow/search/%D0%BA%D0%BE%D1%84%D0%B5/"
    },
    {
      "url": "https://yandex.com/maps/213/moscow/search/coffee/?page=2"
    },
    {
      "url": "https://m.yandex.com/maps/org/192990200894/"
    }
  ],
  "location": "New York, NY",
  "maxResultsPerSearch": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/yandex-maps-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/yandex-maps-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/SN6AdkrVpugyTz56F/builds/uLQSTvabaTgv6ezmN/openapi.json
