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

Extract business listings from 2GIS in Dubai, Moscow, Almaty and other cities: names, addresses, phones, emails, websites, social links, ratings and opening hours. Optionally add public reviews as separate rows for lead generation and local market research.

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

## Pricing

from $3.00 / 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.

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ГИС

2GIS Scraper collects public business listings and optional customer reviews from 2GIS in Dubai, Russia and Kazakhstan, for lead generation and local market research. Get business names, addresses, phone numbers, websites, email addresses, social links, categories, ratings and opening hours in a dataset you can export to CSV, Excel or JSON.

2GIS is a widely used city directory in Russia and Kazakhstan and also covers Dubai and the wider UAE. One 2GIS business card can carry several phone numbers, an email address, a website and the business's social profiles. This actor turns a search such as "cafe in Dubai" or "стоматология Алматы" into rows you can filter, deduplicate and load into a CRM.

### Use cases for a 2GIS scraper

- **Lead generation.** Build call and email lists of restaurants, clinics, salons, contractors or retailers in one city, with phones, emails and websites ready for outreach or a CRM import.
- **Local market research.** Count businesses per category and district, compare ratings and review counts, and see how dense a niche is before opening a location.
- **Reputation monitoring.** Collect the newest public reviews of your own branches or of competitors, including the official reply, and track unanswered feedback.
- **Data enrichment.** Start from a list of known 2GIS firm URLs and refresh their contacts, opening hours and ratings.
- **Expansion into the Gulf and CIS.** Map competitors in Dubai, Moscow, Saint Petersburg, Almaty or Astana with one consistent schema across countries.

### What the 2GIS Scraper returns

A place row represents a business branch rather than an entire organization. This matters when a chain has several addresses or when you compare businesses within one city. Each place has its own stable `place_id`, public 2GIS page URL and retrieval timestamp. Where available, the organization identifier and branch count help you recognize related locations.

Contact information comes from the public business listing. The actor keeps phone numbers together in `phones`, provides the first number as `phone`, and returns email addresses in lowercase without duplicates. `website` contains the business website URL. Social links are grouped by their contact type, such as Instagram, Facebook or Telegram. Businesses without a public contact field still appear in the dataset; the missing value is null or an empty list.

Optional reviews are separate rows. Each review includes a review identifier and the identifier, name and public URL of the business it concerns. You can join reviews to places using `place_id`, or filter the dataset by `record_type` before exporting the two groups separately.

### Input

Start with `queries`, an array of search terms, plus a `city` and `domain`. City values use the names or slugs recognized by 2GIS, including moscow, spb, almaty, astana and dubai. The supported domains are `2gis.ru`, `2gis.kz` and `2gis.ae`. A single target with an unknown city returns the input error `Unknown 2GIS city '…'` without collecting or charging any rows. In a list, invalid targets are skipped with a warning while valid targets continue. The same check applies to the city inside a search or firm URL. The domain determines the language of listing fields: Russian for the Russian and Kazakhstan domains, and English for the UAE domain. Review text stays in its original language.

You can instead supply `start_urls`. Accepted URLs point to a 2GIS search page or a firm page on a supported domain. A search URL supplies its own city and search term. Its `/page/n` starts after `(n-1)*12` search results; returned positions start at 1 for the collected rows. A firm URL retrieves that specific business. A firm URL ending in `/tab/reviews` is also accepted. Enable `include_reviews` to collect its reviews.

The default `limit` is 100 places per search, with a range of 1 to 10,000. `include_reviews` defaults to false. When enabled, `max_reviews` defaults to 20 reviews per place, with a maximum of 5,000. Larger values collect more data and increase the number of billable rows. Start with a small search to check whether the city, term and fields meet your needs before collecting a larger dataset.

Search cafes in Dubai with up to ten reviews each:

```json
{"queries":["cafe"],"city":"dubai","domain":"2gis.ae","limit":20,"include_reviews":true,"max_reviews":10}
```

Search in Russian on the Moscow catalog:

```json
{"queries":["кафе"],"city":"moscow","domain":"2gis.ru","limit":3}
```

Collect one known business and its reviews:

```json
{"start_urls":["https://2gis.ae/dubai/firm/70000001006365610"],"include_reviews":true,"max_reviews":12}
```

### Output

Every row has `record_type`, either `place` or `review`. It also has `_type`, `source`, `platform`, `fetched_at` and `row_id`. These fields make exports easier to identify and combine with later collections.

Place rows contain `firm_id`, `place_id`, `name`, `full_name`, `url`, `address`, `street`, `postal_code`, `city`, `state`, `country_code`, `lat`, `lng`, `category`, `categories`, `rating`, `reviews_count`, `ratings_count`, `phones`, `phone`, `emails`, `website`, `socials` and `opening_hours`. Additional fields include address notes, organization information and the source update timestamp. Opening hours retain the published intervals; an interval ending after midnight remains in the day on which it starts.

Review rows contain `review_id`, `place_id`, `place_name`, `place_url`, `rating`, `text`, `author_name`, `published_at`, `likes`, `is_verified` and `reply_text`. When available, the actor also returns an author identifier, edit timestamp, comment count, review photo URLs, provider and official reply timestamp. All returned review timestamps are expressed in UTC. Reviews are collected newest first. Only reviews with an integer rating from 1 to 5 are delivered; unrated entries from other providers are skipped while collection continues through the available pages.

Written reviews and star-only ratings are different measures. `reviews_count` is the count of written reviews reported for a place. `ratings_count` also includes ratings without review text. A place can therefore have a larger ratings count than reviews count. Neither field promises that the actor will collect that many rows; your `max_reviews` determines the requested limit.

#### Example place row

A real place row from the firm-URL input above, collected on 6 October 2026 (opening hours shortened to two days). Listings change, so a new run can return different values.

```json
{
  "_type": "local.place",
  "record_type": "place",
  "row_id": "place:70000001006365610",
  "place_id": "70000001006365610",
  "firm_id": "70000001006365610",
  "name": "Hard Rock",
  "full_name": "Hard Rock, cafe",
  "url": "https://2gis.ae/dubai/firm/70000001006365610",
  "address": "Dubai Festival City Mall, 9, Crescent Drive, Dubai",
  "address_comment": "2 Floor",
  "city": "Dubai",
  "district": "Al Kheeran",
  "country_code": "AE",
  "lat": 25.22365,
  "lng": 55.351308,
  "category": "Cafe / Restaurants",
  "rating": 4.6,
  "reviews_count": 136,
  "ratings_count": 155,
  "phones": ["+97142328900"],
  "phone": "+97142328900",
  "emails": ["sales@hardrockdubai.ae"],
  "website": "http://cafe.hardrock.com",
  "socials": {
    "instagram": ["https://instagram.com/hardrockcafedxb"],
    "facebook": ["https://facebook.com/hardrockcafedxb"]
  },
  "opening_hours": {
    "Mon": [{"from": "12:00", "to": "01:00"}],
    "Fri": [{"from": "12:00", "to": "02:00"}]
  },
  "branch_count": 3,
  "domain": "2gis.ae"
}
```

#### Example review row

```json
{
  "_type": "local.review",
  "record_type": "review",
  "row_id": "review:271412257",
  "review_id": "271412257",
  "place_id": "70000001006365610",
  "place_name": "Hard Rock",
  "place_url": "https://2gis.ae/dubai/firm/70000001006365610",
  "rating": 5,
  "text": "What a food",
  "author_name": "Saqib Khan",
  "author_reviews_count": 20,
  "published_at": "2026-08-22T18:07:46.112Z",
  "likes": 0,
  "is_verified": false,
  "provider": "2gis",
  "photo_urls": [],
  "reply_text": null
}
```

A search row also carries the search term and its position in the results. From the Moscow input above, the first result was the bar "Руки Вверх!" at Можайское шоссе, 45Б with `query: "кафе"`, `position: 1`, rating 4.8 from 332 reviews and the phone `+74951205368`.

### Pricing

Places and reviews are separate billable events. Contacts belong to the place row and have no separate contact event. The actor's pricing panel shows the current price for each event. There is no custom run-start event in this product's billing configuration, and empty results produce no place or review event. Billing counts the rows actually delivered to the dataset, after deduplication and any free-plan cap.

Users without a paid Apify plan receive at most ten dataset rows per run. This is a combined cap across places and reviews. Paid users retain their requested place and review limits. If you enable reviews on the free plan, the ten available rows may include both types; check `record_type` when interpreting the export.

### How this 2GIS scraper compares

| | This actor | Typical alternatives |
|---|---|---|
| Places and reviews | One actor, one dataset, joined by `place_id` | Often a separate places actor and reviews actor |
| Contacts | Phones, emails, website and social links included in the place price | Sometimes billed as an extra contact event |
| Countries | 2gis.ru, 2gis.kz and 2gis.ae, one schema | Often one domain or Russian-only fields |
| Run-start fee | None | Some charge per start |
| Opening hours | Structured intervals per weekday | Often a text string |

Compared with a Google Maps scraper, this actor reads a different source: 2GIS has its own catalog, categories and reviews for Russian, Kazakh and Emirati cities. Many teams run both and join the results on phone number or website.

### Collection behavior

The actor continues larger searches automatically. Each collection response can contain a continuation cursor, and the actor follows it while keeping the original search settings. API users can pass `next_cursor` back as `cursor` with the same input. Changing a search term or limit while reusing a cursor is rejected, because the continuation belongs to the original request.

Public listings and reviews can change during a collection. Stable row identifiers help avoid duplicates, but this is a current public-data collection rather than a historical snapshot. If an individual review request fails, the business row remains available and the output reports a warning. Check `partial` and `warnings` in the output record before using a collection as a complete sample.

### FAQ

#### Which cities and countries does the 2GIS Scraper support?

Any city on 2gis.ru, 2gis.kz and 2gis.ae, such as Moscow, Saint Petersburg, Novosibirsk, Almaty, Astana and Dubai. Choose the domain that matches the city; Russian and Kazakhstan listings come in Russian, UAE listings in English.

#### Can I collect only a specific business?

Yes. Put its public 2GIS firm URL in `start_urls`. You receive one place row, and optional review rows if `include_reviews` is enabled. This is useful when you already have a list of business URLs and want comparable contacts or review fields.

#### Are reviews nested inside the business row?

No. Reviews are dataset rows with `record_type: review`. Their `place_id` matches the business identifier, making the relationship explicit in CSV exports, database imports and other tabular workflows.

#### Why is a phone, website or rating missing?

The actor reports the fields available in the public listing. Some businesses publish fewer contacts or have no rating yet. Missing values are preserved as null or empty lists so you can distinguish unavailable data from a filled field.

#### Can I search in Russian?

Yes. Search terms are passed as written, so "кафе", "стоматология" or "автосервис" work on the Russian and Kazakhstan domains, and English terms work on 2gis.ae.

#### Does the actor translate reviews or collect private information?

It returns public review text as published, without translation. It does not request private customer records. Use the returned public business and review data in accordance with the source's terms and the requirements that apply to your use case.

# Actor input Schema

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

Search terms to run in the selected city. Provide queries or start_urls.

## `city` (type: `string`):

2GIS city slug or name, for example moscow, almaty or dubai. Applies to queries.

## `domain` (type: `string`):

Determines the language and country of query searches. URLs supply their own domain.

## `start_urls` (type: `array`):

HTTPS search or firm URLs on 2gis.ru, 2gis.kz or 2gis.ae. Search /page/n starts after (n-1)\*12 places; positions start at 1 for the collected rows. A firm URL can end in /tab/reviews.

## `limit` (type: `integer`):

Maximum unique places per search. Larger searches continue automatically in the Apify actor.

## `include_reviews` (type: `boolean`):

Return public reviews as separate rows linked to the place by place_id.

## `max_reviews` (type: `integer`):

Maximum reviews per place, newest first. Applies when include_reviews is true.

## `cursor` (type: `string`):

Opaque next_cursor from a previous response. Keep all other input fields unchanged.

## Actor input object example

```json
{
  "city": "moscow",
  "domain": "2gis.ru",
  "start_urls": [
    "https://2gis.ae/dubai/firm/70000001006365610"
  ],
  "limit": 100,
  "include_reviews": false,
  "max_reviews": 20
}
```

# Actor output Schema

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

One row per 2GIS place, plus one row per review when include_reviews is on; record_type tells them apart.

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

Status, row counts per type, charged events and next_cursor for continuing a large search.

## `errors` (type: `string`):

Failures with a code and a redacted message. Absent when the run had none.

# 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 = {
    "start_urls": [
        "https://2gis.ae/dubai/firm/70000001006365610"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/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 = { "start_urls": ["https://2gis.ae/dubai/firm/70000001006365610"] }

# Run the Actor and wait for it to finish
run = client.actor("s-r/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 '{
  "start_urls": [
    "https://2gis.ae/dubai/firm/70000001006365610"
  ]
}' |
apify call s-r/2gis-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/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/cW6OynOwo0oHLR7CJ/builds/5NlkI0fyLRUTmZRza/openapi.json
