# 2GIS Places Scraper: Phones, Emails, Websites (`amitaviv/2gis-places-scraper`) Actor

Scrape 2GIS businesses by search term and city (Russia, Kazakhstan, UAE and other 2GIS countries) or 2GIS URLs: name, categories, address, coordinates, phones, emails, websites, social links, hours, rating, branch count. Gets past the 60-place limit map area by area. New-places-only mode.

- **URL**: https://apify.com/amitaviv/2gis-places-scraper.md
- **Developed by:** [Amit Aviv](https://apify.com/amitaviv) (community)
- **Categories:** Lead generation, Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 places

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

## 2GIS Places Scraper: Phones, Emails, Websites

Business listings from 2GIS (2gis.ru, 2gis.kz, 2gis.ae and the other 2GIS country sites) for a search term in a city, or for pasted 2GIS search, category and place URLs: name, categories, address, coordinates, phones, emails, websites, social links, opening hours, rating, review count and branch count. It reads 2GIS's public pages over plain HTTP (no browser, no login), gets past 2GIS's 60-places-per-search limit by searching the city map area by area, and you pay only for places delivered; a run that delivers nothing because of an error or a block ends as Failed, never as a green empty run.

### What you get

- Name, short name and descriptor ("Demokrat" + "стоматологический центр"), 2GIS categories (names and rubric ids, main one first)
- Street address, full address, where in the building ("Д блок; 1 этаж"), street, house number, postcode, district, city, region, country, latitude and longitude
- Contacts as the business publishes them on 2GIS: phones (international format), emails, websites (the business's own URL, not 2GIS's redirect link), social and messenger links (VK, Telegram, WhatsApp, Instagram, Facebook, YouTube and others), faxes
- Opening hours per weekday, open 24/7 flag
- Rating, number of reviews, number of ratings, number of photos
- Organisation id and name, and how many branches the organisation has on 2GIS
- Features 2GIS lists for the place (payment methods, Wi-Fi, services, average bill and so on), advertising flag, when the listing was added and last updated
- One record per place, as JSON, CSV or Excel, or through the API. A place is delivered and charged once per run, however many searches or map areas list it.
- A run summary (`OUTPUT_SUMMARY` in the run's key-value store): what was requested, delivered and charged, how many places 2GIS lists for each search, how many map areas were searched, what was left out and why, and why the run stopped.

What it does not return: review texts, reviewer names, photos, menus and price lists, anything behind a login.

### How it gets past 2GIS's 60-place limit

2GIS shows at most 60 places (5 pages of 12) for one search, even when it says it has thousands. The actor first reads the search as 2GIS lists it (its own order, most relevant first). When 2GIS has more, it searches the map area by area with 2GIS's own "search here" filter, which gives each map view its own count: a view that lists more than 60 places is cut into four quarters and searched again, until every view lists 60 or fewer. It covers the map 2GIS shows for the search first, then the rest of the city's bounds. Places found twice are delivered once.

**Only the city you named.** 2GIS groups cities into areas, and its search lists places from the whole area: the Almaty area includes Talgar, Kaskelen and Konaev, and the Bishkek area is all of Kyrgyzstan. By default a search term in a city delivers only places 2GIS files under that city (Troitsk and Zelenograd count as their own cities, not as Moscow); the others are not charged, and the status message says how many were left out among the places read, also when the run stops at **Max places per search** (OUTPUT_SUMMARY has the count as `otherTownsInArea`). Turn on **Include nearby towns of the 2GIS area** (`includeWholeArea`) to get the whole area. A pasted search URL always gets what 2GIS lists for it, the whole area included.

Measured: dentistry in Karaganda, 2GIS's search listed 225. In the city only (the default) the actor delivered 183, left out 5 in other towns and 4 listings in a private person's name (run `ey1GQyPaNFNeKWWEN`); these 183 are every Karaganda place that an earlier run over the whole area delivered (that run's other 31 were in Temirtau, Saran and two villages). Dentistry in Almaty, where 2GIS's search listed 1,207: in a test run from our own server without the contacts step the map search found 1,343 different places in the whole 2GIS Almaty area (with nearby towns), 99% of the 1,358 that 2GIS counted for it. A pasted "search here" URL for central Almaty (cafés) gave exactly the 172 places 2GIS counted for that view (`ZPjlPyphWsQsUw71Y`).

Turn this off with **Get past 2GIS's 60-place limit** if you only want 2GIS's first 60.

### What is left out by default

**Listings in a private person's name** (`includeIndividuals`, off) are not delivered and not charged; the status message says how many were left out among the places read, also when the run stops at **Max places per search** (OUTPUT_SUMMARY: `individualsWithheld`). These are listings where any part of the name 2GIS shows is a person's name: sole traders ("ИП …", also as a descriptor: "Стоматологическая клиника, ИП Хелаев М.Я."), names with initials ("Нотариус Ахметова Л.К.", "Доктор Алексеев В. А."), full names with a patronymic ("Иванова Мария Петровна"), and a common first name with a surname ("Репетитор Иванова Мария"). Their names and phones are personal data. It is a heuristic on the name: in our tests it caught all 36 notaries listed by name in Karaganda, held back 4 of 218 dentistry listings there (solo practices named after the doctor), and among 2,531 different places delivered by our test runs it flagged no business by mistake. A person's name written in another form (only a first name, a name in Latin letters such as "Dr. Abdullayev") is not recognised. Turn it on only if you have a lawful basis to process such data; the records then carry `isIndividual: true`.

**A sole trader behind a business.** 2GIS often adds the legal owner to a business's organisation name ("Россиянка, кафе, ИП Казак И.А."). The business is delivered, but `organizationName` comes without the person's name ("Россиянка, кафе") unless `includeIndividuals` is on.

### How to use

1. Type what you are looking for into **Search terms or 2GIS URLs**, as you would in 2GIS (`стоматология`, `кофейня`, `автосервис`, `dentist` on 2gis.ae). Several entries are fine.
2. Type the **City**: `Москва`, `Almaty`, `Dubai`, `Новосибирск`, or the code from a 2GIS address (`2gis.ru/novosibirsk/…`). Several cities: separate them with `;`. Or skip this and paste a 2GIS search or category URL; its filters are kept.
3. Set **Max places per search** and press Start.
4. Download the results from the Output tab, or read them from the API.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `queries` | list of text | none (required) | Search terms, 2GIS search or category URLs (`https://2gis.ru/moscow/search/Кофейни/rubricId/162`, filters such as sort and "has photos" are kept), or place URLs (`https://2gis.kz/almaty/firm/70000001047564924` returns that one place). A search URL copied with a place card open (`…/search/кафе/firm/…`) reads the whole search. URLs from any 2GIS country site are accepted, with or without `https://`. Entries from other sites, building pages (`/geo/…`) and, when `location` is empty, search terms are ignored and listed in the summary; the rest of the input still runs. |
| `location` | text | empty | The city for the search terms. Several, separated by `;`: every term is searched in every city. Needed for search terms, not for URLs. |
| `maxItems` | number | 100 | Stop after this many places for each search (each term in each city, or each URL). Up to 100,000. |
| `splitLargeSearches` | yes/no | yes | Search the city map area by area when 2GIS has more than 60 places. See above. |
| `includeWholeArea` | yes/no | no | Also deliver places in the other towns of the city's 2GIS area. See above. |
| `includeIndividuals` | yes/no | no | Also deliver listings in a private person's name. See above. |
| `onlyNew` | yes/no | no | Deliver and charge only places earlier runs have not delivered. See "Only new places". |
| `monitorKey` | text | empty | Name of the "only new" memory, to keep two schedules apart. |
| `proxyConfiguration` | proxy | off | Not needed. See the FAQ. |

This input was run as `uFJ3oeLe28hcpfEh7` (a 2gis.ae search, a 2gis.ru category URL and a 2gis.kz place URL; 31 places, all with their place page read):

```json
{
  "queries": [
    "https://2gis.ae/dubai/search/dentist",
    "https://2gis.ru/moscow/search/Кофейни/rubricId/162",
    "https://2gis.kz/almaty/firm/70000001047564924"
  ],
  "maxItems": 15
}
```

### Example result

The place URL from run `uFJ3oeLe28hcpfEh7` on 2026-10-20, unedited except that the list of 24 features is shortened:

```json
{
  "id": "70000001047564924",
  "url": "https://2gis.kz/almaty/firm/70000001047564924",
  "name": "Demokrat, стоматологический центр",
  "shortName": "Demokrat",
  "descriptor": "стоматологический центр",
  "categories": ["Частные стоматологии"],
  "categoryIds": ["222"],
  "primaryCategory": "Частные стоматологии",
  "address": "микрорайон Коктем-3, 24 к1",
  "fullAddress": "Алматы, микрорайон Коктем-3, 24 к1",
  "addressComment": "Д блок; 1 этаж",
  "street": "микрорайон Коктем-3",
  "houseNumber": "24 к1",
  "postcode": "050000",
  "district": "Бостандыкский район",
  "city": "Алматы",
  "region": "Алматы",
  "country": "Казахстан",
  "latitude": 43.234488,
  "longitude": 76.919835,
  "phone": "+77072837030",
  "phones": ["+77072837030"],
  "email": "demokrat.almaty@gmail.com",
  "emails": ["demokrat.almaty@gmail.com"],
  "website": "http://demokrat-almaty.kz/?utm_source=2_Gis&utm_medium=link&utm_campaign=site",
  "websites": ["http://demokrat-almaty.kz/?utm_source=2_Gis&utm_medium=link&utm_campaign=site"],
  "socialLinks": [
    { "type": "vkontakte", "url": "https://vk.com/public201210007" },
    { "type": "facebook", "url": "https://facebook.com/demokratalmaty" },
    { "type": "instagram", "url": "https://instagram.com/demokrat_almaty" },
    { "type": "youtube", "url": "https://youtube.com/channel/UC--tZvU0u92McnNWbZfF7Rw" },
    { "type": "whatsapp", "url": "https://wa.me/77768063377" }
  ],
  "faxes": [],
  "openingHours": {
    "Mon": ["09:00-19:00"], "Tue": ["09:00-19:00"], "Wed": ["09:00-19:00"], "Thu": ["09:00-19:00"],
    "Fri": ["09:00-19:00"], "Sat": ["09:00-19:00"], "Sun": ["09:00-19:00"]
  },
  "isOpen24x7": false,
  "scheduleComment": null,
  "rating": 4.9,
  "reviewCount": 928,
  "ratingCount": 1243,
  "photoCount": 82,
  "attributes": ["Скидки", "Взрослый стоматолог-хирург", "Взрослый ортодонт", "Взрослый стоматолог-ортопед", "Имплантация", "Взрослый пародонтолог", "…"],
  "organizationId": "70000001047564923",
  "organizationName": "Demokrat, стоматологический центр",
  "branchCount": 1,
  "isPromoted": false,
  "isIndividual": false,
  "createdAt": "2021-01-13T01:00:00Z",
  "updatedAt": "2026-09-10T15:47:18Z",
  "timezoneOffsetMinutes": 300,
  "detailsFetched": true,
  "searchQuery": null,
  "searchCity": null,
  "scrapedAt": "2026-10-20T14:14:01.059Z"
}
```

(`fullAddress` in that run was `null`: place pages carry no full address; since build 0.1.8 it is built from the city and the street address, as shown.)

| Field | Meaning |
|---|---|
| `id` | 2GIS's id of the place (branch); stable between runs. |
| `url` | The place's page on 2GIS. |
| `phone`, `email`, `website` | The first of `phones`, `emails`, `websites`. |
| `socialLinks` | `[{type, url}]`. WhatsApp links are given without 2GIS's pre-filled greeting. |
| `openingHours` | Per weekday; an empty list is a closed day; `null` when 2GIS has no hours. |
| `rating`, `reviewCount`, `ratingCount` | 2GIS's figures for this branch. |
| `organizationId`, `branchCount` | The organisation all branches share, and how many branches it has on 2GIS. |
| `isPromoted` | 2GIS marks the listing as advertising. |
| `detailsFetched` | `true`: the contacts come from the place's own page. A place whose page 2GIS does not send is left out and not charged (the status message says how many), so delivered records have it `true`. |
| `searchQuery`, `searchCity` | The search that found the place (empty for a pasted place URL). |

Fields 2GIS does not provide for a place are `null` (lists are empty), never missing.

### Pricing

Pay per event. You pay for what is delivered, not for time or memory.

| Event | Free plan | Bronze | Silver | Gold and above |
|---|---|---|---|---|
| Actor start (once per run) | $0.003 | $0.003 | $0.003 | $0.003 |
| Place delivered, contacts included | $0.0036 | $0.003 | $0.0027 | $0.0024 |

Worked example on Bronze: 1 search, 500 places = 500 × $0.003 + $0.003 = **$1.503**. A scheduled "only new" run that finds 4 new places costs 4 × $0.003 + $0.003 = $0.015; a run that finds nothing new costs the start fee, $0.003.

- Places that were not delivered are not charged: places of other cities and towns, places found twice, listings left out by `includeIndividuals`, places whose page 2GIS did not send.
- The maximum total charge you set for a run is respected: the actor stops before it would go over, keeps what was delivered, and says so in the status message (run `3b6pO9XFJ7vGJ176K`: limit $0.018 = start + 5 places, exactly 5 delivered).

### Reliability and failure behaviour

| What happened | Run status | Status message (from real runs) |
|---|---|---|
| Places delivered | Succeeded | `Scraped 31 places from 3 queries` |
| 2GIS has no places for your search | Succeeded | `0 results: 2GIS has no places for this query` |
| 2GIS lists places, but every one is left out by your settings | Succeeded | `0 places delivered: all 60 places 2GIS listed were left out by this input's settings — 15 places in other towns of the 2GIS Казань area not delivered (turn on "includeWholeArea" to get them); 45 listings in a private person's name not delivered (…)` (notaries in Kazan, run `kpt24sPlVf0hyyFMG`) |
| Some entries worked, some failed | Succeeded | `Scraped … places from 2 queries — 1 of 2 queries failed ("…": …)` |
| Nothing delivered because of errors or blocking | **Failed** | `No places delivered: 2GIS blocked every attempt; try again later. No places were charged (the start fee applies).` |
| Input the actor cannot use | **Failed**, within 2 seconds | `Nothing to do: the input has no "queries". Add a search term such as "стоматология" with "location": "Almaty", or a 2GIS search or place URL. …` |
| City not found | **Failed** | `… "Atlantis" was not recognised as a 2GIS city: …` |
| Stopped at Max places, some places left out by your settings | Succeeded | `Scraped 40 places from 1 query — 1 place in other towns of the 2GIS Новосибирск area not delivered (turn on "includeWholeArea" to get them)` (run `v7Uov547FQ5VkkOuf`, Max places 40; the count is of the places read before the stop) |
| Maximum charge reached | Succeeded | `Scraped 5 places from 1 query — stopped at the maximum charge set for this run` |
| Run timeout close | Succeeded | `Scraped 22 places from 1 query — stopped just before the run timeout; raise the timeout to get the rest` (run `GdmTqSMXQDeUwqQPn`, 18-second timeout: stopped while place pages were being read; the 22 finished places were delivered, the unfinished ones were not charged; the run ended 4.6 s before its timeout) |
| Run timeout so short that no place could be read | **Failed** | `No places delivered before the run timeout: raise the run timeout and try again. No places were charged (the start fee applies).` (run `9uZGx1Z9k9PggKJlq`, 50 seconds on 2gis.kg, whose search pages took up to 40 s each) |

- No proxy is needed: test runs went straight from Apify's servers to 2GIS. In the 1,000-place run 2GIS refused 2 of 1,154 requests; the actor switched to Apify Proxy by itself, said so in the log and summary, and finished (`qaN2Hn9L6y2Z1XbgN`). If 2GIS refused most requests, it would move on to residential proxy (tested offline only).
- Requests are retried up to 3 times with increasing pauses on network errors, HTTP 429 and 5xx. A map view that still gets no answer is asked once more at the end, then skipped; the status message says how many map areas could not be read.
- Places are saved and charged page by page. A run that is aborted, times out or is resurrected keeps what was delivered and never delivers or charges the same place twice.
- In all test runs (2026-10-20 to 2026-10-24) the charged places equalled the delivered places, counted after the run's charges had settled.

### Limits

- **Speed depends on the 2GIS country site.** 2GIS sends Apify's servers its pages slowly, and each place needs its own place page for the contacts. Measured on 2gis.ru and 2gis.kz: 39-55 places a minute for runs of 100 to 1,000 places (300 Almaty dentists in 7.2 minutes, `rWfKYs4PgUdVxmFLd`; 1,000 in 26 minutes, `qaN2Hn9L6y2Z1XbgN`). 2gis.kg and 2gis.ae answered Apify's servers far more slowly: 5-8 places a minute on .kg (80 Bishkek coffee places in 15.6 minutes, `fKOj3t9tta3Yb4OVK`; 440 in 59 minutes, `aQtQVOeJQwB7cUFcC`) and about 4 a minute on .ae (19 Dubai dentists in 4.9 minutes, `ikgML9vskAA3vHMec`). The other country sites were not measured. Give large runs a long timeout: with the default hour, expect roughly 2,000 places on .ru/.kz and a few hundred on .kg or .ae.
- **City areas.** By default only the city you named is delivered (see above). With `includeWholeArea` or a pasted URL you get the whole 2GIS area, which can be a whole country (Kyrgyzstan for Bishkek); every record has its own `city`.
- **Coverage.** The map search finds what 2GIS lists for each map view. Where one building or block lists more than 60 matching places even at street level (a large shopping centre), only 60 of them can be read; the status message says how many such spots there were. In our tests coverage of 2GIS's own count for the area was 99%.
- **Languages.** Names, addresses and categories come in the language 2GIS uses for the country site: Russian on 2gis.ru and 2gis.kz, English on 2gis.ae.
- **Contacts.** Only what the business publishes on 2GIS. In a 10-place Moscow test every place had a phone and opening hours, 7 an email and 7 a website (`yrWfUb4voJMSZXdMp`).

### Only new places (monitoring)

1. Turn on **Only new places** and save the input as a task.
2. Schedule the task (daily or weekly).
3. The first run delivers what it finds (up to the maximum). Every later run delivers and charges only places it has not delivered before for the same search and city; a run with nothing new ends as Succeeded with `0 new places…` and charges only the start fee.

Tested: Karaganda dentistry delivered 183 places (`ey1GQyPaNFNeKWWEN`), then the same input `0 new places in 1 monitored query` with 0 places charged (`KqvdpGJzbAPH0l7CO`, 63 seconds). A later run still reads the whole city's map to find new places, but reads no place pages for places it already knows. When a later run hits the maximum, the rest of the new places come in the run after it.

The memory is a key-value store named `2gis-places-scraper-monitor` in your own account (one record per search, city and monitor name). Delete the store or change **Monitor name** to start over.

### FAQ

**Do I need a proxy?** No. Leave the proxy setting empty. If 2GIS refuses requests, the actor falls back to Apify Proxy on its own.

**Why do I get more, or fewer, places than 2GIS's search count?** 2GIS's search shows 60, and its count covers its whole area (nearby towns included) for the map view it picks. The actor searches the whole city map, so it finds more than 60; by default it keeps to the city you named, so it can deliver fewer than 2GIS's count. Turn on `includeWholeArea` for the whole area.

**Can I get only one district?** Open 2GIS, search, move the map to the district, press "Искать здесь" / "Search here", and paste that URL: the actor searches that view only (tested: `ZPjlPyphWsQsUw71Y`, 172 of 172).

**Can I run it from code?** Yes: the API, the Apify clients for JavaScript and Python, Make, Zapier, n8n. The Output tab shows the URLs.

**What happens when 2GIS changes its pages?** Runs fail loudly ("2GIS answered without the page data this actor reads") instead of returning empty data. Report the run id under Issues.

### Related actors

- [2GIS Reviews Scraper](https://apify.com/amitaviv/2gis-reviews-scraper): the reviews of 2GIS places (text, rating, date, business replies). Feed it the place URLs this actor returns.
- [Yandex Maps Scraper](https://apify.com/amitaviv/yandex-maps-scraper): the same kind of business data from Yandex Maps (Russia, Turkey, Kazakhstan and more). Many businesses list on both: run both for the same city to fill gaps in phones and websites.

### Legal and responsible use

This actor collects business listing data that 2GIS shows publicly without a login: business names, addresses, switchboard phones, websites and opening hours as the businesses publish them. By default it does not deliver listings in a private person's name (see "What is left out by default"), and it never returns reviews, reviewer names or anything behind a login.

You are responsible for how you use the data: respect 2GIS's terms, copyright and database rights, and data-protection and anti-spam law (GDPR, Russia's 152-FZ, Kazakhstan's law on personal data and others) in your country and the country of the data. Do not use the output for unsolicited marketing where the law requires consent. If you are unsure, ask a lawyer before you build on it.

### Changelog

- 2026-10-24: the status message names places left out in other towns and listings in a private person's name also when a search stops at Max places per search (before, only when it ran to its end).
- 2026-10-24: first version: by default only the named city (`includeWholeArea` for the whole 2GIS area); sole traders recognised in any part of a listing's name and removed from organisation names; building URLs and search terms without a city are skipped instead of failing the run.

### Support

Open an issue on the actor's **Issues** tab with the run id.

# Actor input Schema

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

What to search for, as you would type it into 2GIS, e.g. "стоматология", "кофейня", "car service" (searched in each city of "location"). You can also paste 2GIS addresses: a search or category page (e.g. https://2gis.ru/moscow/search/Кофейни/rubricId/162, its filters are kept; a search URL with a place card open reads the whole search) or a place page (https://2gis.kz/almaty/firm/70000001047564924) for that one place. Building pages (/geo/…) are not places and are skipped.

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

The 2GIS city to search in, as 2GIS writes it or in English, e.g. "Москва", "Almaty", "Dubai", "Новосибирск", or the city code from a 2GIS address (2gis.ru/<code>/…). Several cities: separate them with ";". Only places 2GIS files under that city are delivered (see the next option). Not needed for pasted URLs.

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

Maximum number of places delivered for each search term in each city (and each pasted search URL), from 1 to 100,000; default 100. Apart from the start fee you pay only per delivered place.

## `splitLargeSearches` (type: `boolean`):

2GIS shows at most 60 places for one search. On (default): when it has more, the city's map is searched area by area until "Max places per search" is reached or the city is covered. Off: only the first 60 places, in 2GIS's own order.

## `includeWholeArea` (type: `boolean`):

Off (default): a search term in a city delivers only places 2GIS files under that city. On: also the other towns 2GIS puts in the same area, which can be large (the Almaty area includes Talgar and Kaskelen; the Bishkek area is all of Kyrgyzstan). Pasted search URLs always get what 2GIS lists for them.

## `includeIndividuals` (type: `boolean`):

Off (default): listings whose name is a private person's name (sole traders "ИП …", names such as "Иванова Мария Петровна") are not delivered and not charged; the run summary counts them. Turn on only if you have a lawful basis (e.g. under the GDPR) to process such personal data.

## `onlyNew` (type: `boolean`):

Off (default): every run delivers the places it finds. On: deliver and charge only places that earlier runs of this actor in your account have not delivered for the same search and city. The first run delivers everything it finds. The memory is a key-value store named "2gis-places-scraper-monitor" that the actor creates in your account.

## `monitorKey` (type: `string`):

Only with onlyNew. A free name for the monitor memory, e.g. almaty-dentists-weekly. Runs with the same search, city and monitor name share one memory.

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

Default and recommended: no proxy. 2GIS answered Apify's own addresses in our tests. If 2GIS refuses a request anyway, the actor switches to Apify Proxy by itself (datacenter, then residential). Choose a proxy here only to force one.

## Actor input object example

```json
{
  "queries": [
    "кофейня"
  ],
  "location": "Москва",
  "maxItems": 10,
  "splitLargeSearches": true,
  "includeWholeArea": false,
  "includeIndividuals": false,
  "onlyNew": false
}
```

# Actor output Schema

## `results` (type: `string`):

All delivered places as JSON, one object per place. Main fields: id, url, name, categories, primaryCategory, address, fullAddress, district, city, country, latitude, longitude, phone, phones, email, emails, website, websites, socialLinks, openingHours, rating, reviewCount, organizationId, branchCount, attributes, detailsFetched, searchQuery, scrapedAt. A value 2GIS does not give is null (lists are empty).

## `resultsCsv` (type: `string`):

All delivered places as a CSV file, one row per place, with the same fields as the JSON output (lists are flattened into columns).

## `summary` (type: `string`):

JSON record OUTPUT_SUMMARY: what was requested, delivered and charged; per search how many places 2GIS lists, how many map areas were searched, places outside the city and listings in a private person's name left out; failed or ignored inputs; why the run stopped.

# 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 = {
    "queries": [
        "кофейня"
    ],
    "location": "Москва",
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("amitaviv/2gis-places-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 = {
    "queries": ["кофейня"],
    "location": "Москва",
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("amitaviv/2gis-places-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 '{
  "queries": [
    "кофейня"
  ],
  "location": "Москва",
  "maxItems": 10
}' |
apify call amitaviv/2gis-places-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,amitaviv/2gis-places-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/SbcrLzd5mp0SZkGOK/builds/sV7MOu9zWIOf0B6jd/openapi.json
