# 2GIS Scraper — Phones, Emails & Reviews | Парсер 2ГИС (`innolabs/2gis-scraper`) Actor

2GIS scraper & API: export places with phones, emails, websites, VK/Telegram/WhatsApp links, address, rating, hours and reviews for any city and search query. No login.

- **URL**: https://apify.com/innolabs/2gis-scraper.md
- **Developed by:** [Tristan Leroux](https://apify.com/innolabs) (community)
- **Categories:** Lead generation, Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

Pay per event

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 Scraper — Phones, Emails & Reviews | Парсер 2ГИС

Turn any 2GIS search — "кофе" in Moscow, "стоматология" in Kazan, "coffee" in Dubai — into a clean lead list with **phone numbers, emails, websites and VK / Telegram / WhatsApp / Instagram links**, plus address, rating, opening hours, coordinates and, if you want them, reviews. No login, no 2GIS API key. Export as JSON, CSV or Excel, or pull results through the Apify API.

> **Парсер 2ГИС без API-ключа.** Выгружает организации из 2ГИС по городу и поисковому запросу: телефоны, e-mail, сайты, ссылки на ВКонтакте, Telegram, WhatsApp, адрес, район, рубрики, рейтинг, часы работы, координаты и отзывы. До 10 000 организаций на один запрос, а с «Deep search» — больше (разбивка по районам). Выгрузка в Excel, CSV или JSON.

### What does 2GIS Scraper do?

You give it cities and search queries, exactly as you would type them into 2GIS. For every city × query it walks the 2GIS search results and opens each place's card to collect its contacts. Every place becomes one row:

- **Contacts:** `phones` (dialable, e.g. `+79160663469`), `emails`, `website`, all `websites`, and `socials` — one link per network (VK, Telegram, WhatsApp, Odnoklassniki, Instagram, Facebook, YouTube, TikTok, Max, Dzen, Rutube, LinkedIn, Pinterest…).
- **Place:** name, address, district, city, categories, coordinates (`lat`/`lon`), opening hours per weekday, photo count, chain (`orgId`/`orgName`), 2GIS link.
- **Reputation:** rating, number of reviews, and optionally the reviews themselves (author, stars, text, date, likes), newest first.

In a test run of 300 Moscow coffee shops, 86% had a phone, 90% a social link, 69% a website and 4% a public email — contacts are only there when the business publishes them in 2GIS.

Works for Moscow, Saint Petersburg, Novosibirsk, Yekaterinburg, Kazan and the other Russian cities on 2GIS, plus cities served from 2GIS's country sites such as Almaty, Astana, Tashkent, Bishkek, Minsk and Dubai (use the city slug from the 2GIS link, e.g. `almaty` from `2gis.kz/almaty`).

### Use cases

- **B2B sales and lead generation** — every dentist, car service or beauty salon in a city with phone, email and website, ready for your CRM or cold-calling list.
- **Messenger and social outreach** — agencies and SMM freelancers collect Telegram, WhatsApp and VK links of local businesses in one export.
- **Market research and expansion planning** — count competitors by district before opening a new location, map them with coordinates, compare ratings.
- **Reputation monitoring** — pull the newest reviews of your branches or your competitors' every week.
- **Data enrichment** — add verified addresses, hours, categories and geo-coordinates to an existing list of companies.
- **Analysts and researchers** — complete datasets of a business category across a whole city, beyond the 10,000-result limit of one 2GIS search.

### How much does it cost?

You pay only for the places and reviews saved to your dataset (pay per event). Duplicates are never charged.

| Event | What you pay for | Free plan | Paid plans (from) |
| --- | --- | --- | --- |
| `place` | one place with its contacts | $2.00 per 1,000 | $1.50 per 1,000 |
| `review` | one review (only when **Include reviews** is on) | $0.50 per 1,000 | $0.30 per 1,000 |

Examples:

- **1,000 coffee shops in Moscow with contacts** cost $2.00 on the Free plan and $1.50 on a Gold+ plan.
- **500 dental clinics with up to 20 reviews each** (500 places + 10,000 reviews) cost $1.00 + $5.00 = $6.00 on the Free plan and $0.75 + $3.00 = $3.75 on a Gold+ plan.

The Apify Free plan includes $5 monthly credit — enough for about 2,500 places with contacts every month. Use **Max items** to put a hard cap on any run.

### How to use 2GIS Scraper

In Apify Console:

1. Open 2GIS Scraper and click **Try for free**.
2. Enter one or more **Cities** (`moscow`, `spb`, `kazan`, `almaty`… or a 2GIS city link).
3. Enter one or more **Search queries** (`кофе`, `стоматология`, `автосервис`…). Every city × query pair is searched.
4. Set **Max places per city/query** (default 30). Turn on **Include reviews** if you need them.
5. Click **Start**. Places appear in the dataset while the run is still going.
6. Download the results as Excel, CSV or JSON from the **Storage** tab.

Through the API:

1. Get your API token in Apify Console → Settings → Integrations.
2. Call the actor with your input (see [Integrations and API](#integrations-and-api)) and read the dataset items from the response.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `cities` | array of strings | — (required) | City slugs (`moscow`, `spb`, `novosibirsk`, `almaty`, `dubai`…) or 2GIS city links (`https://2gis.ru/kazan`). |
| `queries` | array of strings | — (required) | What you would type into 2GIS search: `кофе`, `стоматология`, `автосервис`, `салон красоты`. |
| `includeReviews` | boolean | `false` | Also save the reviews of every place, one row per review, newest first. |
| `maxResultsPerQuery` | integer | `30` | Places kept from each city × query, up to 100,000. |
| `deepSearch` | boolean | `false` | Go past the 10,000-places limit of one 2GIS search by repeating it district by district (see [Limits](#limits)). |
| `maxReviewsPerPlace` | integer | `20` | Review cap per place when reviews are on. |
| `maxItems` | integer | `1000` | Hard cap on rows (places + reviews) for the whole run, which also caps the cost. |
| `proxyConfiguration` | object | Apify Proxy | Proxy settings; recommended for large runs. |
| `debug` | boolean | `false` | Verbose log. |

Example — every coffee place in Moscow, as deep as 2GIS goes:

```json
{
    "cities": ["moscow"],
    "queries": ["кофе"],
    "maxResultsPerQuery": 20000,
    "deepSearch": true,
    "maxItems": 20000
}
```

Example — dentists in two cities with their latest reviews:

```json
{
    "cities": ["moscow", "spb"],
    "queries": ["стоматология"],
    "includeReviews": true,
    "maxResultsPerQuery": 100,
    "maxReviewsPerPlace": 20,
    "maxItems": 5000
}
```

### Output

One row per place (`"type": "place"`) and, with reviews on, one row per review (`"type": "review"`). A place from a real run on 2026-11-02:

```json
{
    "type": "place",
    "placeId": "70000001064534699",
    "name": "Comme à Paris, французская кофейня-кондитерская",
    "city": "Москва",
    "citySlug": "moscow",
    "address": "Ленинградский проспект, 36",
    "district": "Аэропорт",
    "categories": ["Кофейни", "Пекарни", "Кондитерские изделия"],
    "rating": 4.8,
    "reviewsCount": 24,
    "phones": ["+79160663469"],
    "emails": ["info@commeaparis.ru"],
    "website": "http://commeaparis.ru",
    "websites": ["http://commeaparis.ru"],
    "socials": {
        "vkontakte": "https://vk.com/commeaparis",
        "whatsapp": "https://wa.me/79104520508",
        "telegram": "https://t.me/commeaparismsk"
    },
    "hours": {
        "Mon": "08:00-22:00",
        "Tue": "08:00-22:00",
        "Wed": "08:00-22:00",
        "Thu": "08:00-22:00",
        "Fri": "08:00-22:00",
        "Sat": "09:00-22:00",
        "Sun": "09:00-22:00"
    },
    "lat": 55.792065,
    "lon": 37.561501,
    "photosCount": 26,
    "orgId": "70000001018413368",
    "orgName": "Comme à Paris, французская кофейня-кондитерская",
    "purpose": null,
    "url": "https://2gis.ru/moscow/firm/70000001064534699"
}
```

A review:

```json
{
    "type": "review",
    "placeId": "70000001113359188",
    "reviewId": "312671295",
    "author": "Айша Болатбек",
    "rating": 5,
    "text": "Отличная кофейня, вернусь ещё",
    "date": "2026-11-02T18:22:09.436602+07:00",
    "likes": 0,
    "provider": "2gis",
    "isVerified": false
}
```

Field notes:

- `phones` are in international format, ready to dial or import into a CRM.
- `website` is the business's own site; links to social networks that 2GIS lists as a "website" are moved to `socials`. `websites` lists every site the business published.
- `socials` keys are the network names (`vkontakte`, `telegram`, `whatsapp`, `odnoklassniki`, `instagram`, `facebook`, `youtube`, `tiktok`, `max`, `dzen`, `rutube`, `linkedin`, `pinterest`, `twitter`…), one link each. In CSV/Excel they become columns such as `socials/telegram`.
- `emails`, `website` and `socials` are empty when the business did not publish them.
- `rating` and `reviewsCount` are for this branch (not the whole chain). Places of the same chain share `orgId`.
- `hours` keys are `Mon`…`Sun`; a day with a break looks like `"10:00-13:00, 14:00-20:00"`.
- A review's `text` is empty when the author left only stars; `date` is the last edit date.

### Integrations and API

Run the actor and get the results in one HTTP call:

```bash
curl -X POST "https://api.apify.com/v2/acts/innolabs~2gis-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"cities": ["moscow"], "queries": ["кофе"], "maxResultsPerQuery": 50}'
```

Python (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("innolabs/2gis-scraper").call(
    run_input={"cities": ["kazan"], "queries": ["стоматология"], "maxResultsPerQuery": 200}
)
for place in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(place["name"], place["phones"], place["emails"], place["socials"])
```

- **Make, Zapier, n8n** — use the Apify app/node to start the actor and send new places to Google Sheets, your CRM or a messenger.
- **Scheduling** — create a schedule in Apify Console (for example every Monday) to refresh your lists or collect new reviews.
- **Webhooks** — get notified when a run finishes and fetch the dataset automatically.
- **AI agents (MCP)** — Claude, Cursor and other MCP clients can call 2GIS Scraper through the Apify MCP server at https://mcp.apify.com.

### FAQ

#### Is it legal to scrape 2GIS?

The actor collects only publicly visible business listing data — the same information anyone sees on 2gis.ru without logging in. It does not access accounts or private data. Check 2GIS's terms and the data protection laws that apply to you (for example 152-FZ in Russia or GDPR), especially before using contacts for marketing.

#### Do I need proxies?

Small runs usually work without one. For large runs keep the default Apify Proxy on: 2GIS rate-limits busy IP addresses and blocks some networks. If a city returns errors, try a proxy located in that country.

#### How many places can I get per search?

One 2GIS search returns at most 10,000 places, and the actor reads all of them if you raise **Max places per city/query**. For bigger categories turn on **Deep search**: the actor repeats the query for every district of the city and merges the results without duplicates. For "кофе" in Moscow that gave 12,677 unique places instead of 10,000.

#### Can I get only new places or new reviews?

Each run returns the current state of 2GIS. For an incremental feed, schedule the actor and compare `placeId` (places) or `reviewId` (reviews) with your previous export; reviews come newest first, so a small **Max reviews per place** is enough to catch new ones.

#### What happens if a city or a search fails?

The failure is logged in the run summary and the actor moves on to the next city or query; places already collected stay in the dataset. An unknown city slug is reported as "city failed". A search with no results simply returns 0 places.

#### Why does a place have no email or website?

The actor returns what the business published on its 2GIS card. Many small businesses list only a phone or a Telegram/WhatsApp link.

### Limits

- **10,000 places per 2GIS search.** 2GIS stops serving results after 10,000 for one search, even when it shows a larger total. **Deep search** goes past it by splitting the search by city district (measured on 2026-11-02 for "кофе" in Moscow: 10,000 places without it, 12,677 with it). Places that 2GIS does not assign to any district (a small share, mostly vending machines) are reachable only through the first 10,000.
- **Deep search takes time.** It reads every result page of every district — for "кофе" in Moscow about 14 minutes of search pages — on top of opening each place's card for contacts, which runs at roughly 6 places per second (300 places in 49 seconds in our test). Expect a full 12,000-place city run to take around an hour.
- **Contacts depend on the business.** Most places list a phone (86% of Moscow coffee shops in our test); emails are rare (4%).
- **Reviews come from 2GIS's review service.** If it is unreachable, places are still saved without reviews.
- **Cities without districts.** Smaller towns (for example Kolomna) have no city districts in 2GIS, so Deep search adds nothing there — such towns rarely reach 10,000 results anyway.

# Changelog

This Actor's version history is a separate document: https://apify.com/innolabs/2gis-scraper/changelog.md

# Actor input Schema

## `cities` (type: `array`):

2GIS city slugs or city URLs, e.g. moscow, spb, novosibirsk, kazan, almaty, https://2gis.ru/ekaterinburg. Each city is searched separately.

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

What you would type into 2GIS search, e.g. кофе, стоматология, автосервис, салон красоты. Every city × query pair is searched.

## `includeReviews` (type: `boolean`):

Also save the reviews of every place found, one dataset item per review, newest first.

## `maxResultsPerQuery` (type: `integer`):

How many places to keep from each city × query search. A single 2GIS search returns at most 10,000 places; turn on Deep search to go beyond that.

## `deepSearch` (type: `boolean`):

When a search stops before 2GIS's own result count (2GIS serves at most 10,000 places per search), repeat it district by district and merge the results without duplicates. Raise 'Max places per city/query' above 10,000 to use it.

## `maxReviewsPerPlace` (type: `integer`):

Review cap for every place when Include reviews is on.

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

Hard cap on dataset items (places + reviews) for the whole run. The run stops cleanly when reached, so this also caps the cost.

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

Apify Proxy settings. 2GIS geo-filters some networks and rate-limits busy IPs; a proxy is recommended for large runs.

## `debug` (type: `boolean`):

Log every search page and any contact/review fetch that failed.

## Actor input object example

```json
{
  "cities": [
    "moscow"
  ],
  "queries": [
    "кофе"
  ],
  "includeReviews": false,
  "maxResultsPerQuery": 30,
  "deepSearch": false,
  "maxReviewsPerPlace": 20,
  "maxItems": 1000,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "debug": false
}
```

# Actor output Schema

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

All items produced by the run, one JSON object per record.

# 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 = {
    "cities": [
        "moscow"
    ],
    "queries": [
        "кофе"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("innolabs/2gis-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 = {
    "cities": ["moscow"],
    "queries": ["кофе"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("innolabs/2gis-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 '{
  "cities": [
    "moscow"
  ],
  "queries": [
    "кофе"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call innolabs/2gis-scraper --silent --output-dataset

```

## MCP server setup

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