2GIS $1💰 Extract Phones, Emails, Reviews & Locations
Pricing
from $1.00 / 1,000 results
2GIS $1💰 Extract Phones, Emails, Reviews & Locations
From $1/1K. Extract business and place data from 2GIS.com at scale. Get names, addresses, phones, emails, websites, social links, opening hours, ratings, reviews, photos, coordinates, and 80+ fields per place. Supports all regions covered by 2GIS with fast, low-cost extraction.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
2
Bookmarked
49
Total users
12
Monthly active users
10 days ago
Last modified
Categories
Share
2GIS Places Scraper: Phones, Emails, Hours and Reviews
2GIS is a mapping and business directory service used across Russia, Kazakhstan, the United Arab Emirates, Saudi Arabia and more than a dozen other countries in the CIS, the Gulf and beyond, similar to Google Maps for places. This scraper turns 2GIS into a structured places API: names, addresses, phone numbers, emails, websites, social links, per day opening hours, ratings, reviews, photos, coordinates and 80+ fields per place. Search by keyword or category in a city, around coordinates, or inside a map area, or paste 2GIS links or IDs directly, then export to JSON, CSV or Excel, or read the results through the API.
Why This Scraper?
- One flexible search. Combine a WHAT (a text query and/or a category) with a WHERE (a city, coordinates with a radius, or a map area bounding box) in a single mode, plus a separate mode for direct 2GIS links or IDs.
- 80+ fields per place, with every contact channel split out individually: primary phone, all phones, email, website, WhatsApp, Telegram, Instagram, VK, Facebook and more.
- Reviews on demand. Pull full review text, author, rating, date, source (2GIS or Flamp), photos and the official reply, filtered by rating, keyword, date or whether it has a reply.
- Structured opening hours. All seven days, each with an explicit open or closed status, plus a ready to read summary string.
- Wide coverage. Russia, Kazakhstan, Uzbekistan, Kyrgyzstan, Azerbaijan, Georgia, Armenia, the UAE, Saudi Arabia, Qatar, Kuwait, Czechia, Italy and every other region 2GIS covers.
- Built for monitoring. Incremental mode classifies places and reviews as new, updated, unchanged or reappeared (and expired for places) on recurring runs, so a schedule returns only what changed.
- Nothing dropped. The full upstream contact, attribute and administrative blocks are kept alongside the flat, ready to use fields.
Use Cases
- Lead generation and sales prospecting: build contact lists of phones, emails and websites for a category across a city or region.
- Local SEO and directory audits: check how a business appears on 2GIS, including hours, photos, rating and categories.
- Competitive and market research: map every competitor in a category across a city, with ratings and review counts.
- Reputation monitoring: pull all reviews for a set of places, including official replies, to track sentiment over time.
- Data enrichment: attach verified addresses, coordinates and contact details to an existing list of businesses through URL mode.
Data You Get
Sample shape: values are illustrative placeholders, not from a live listing.
| Field | Example |
|---|---|
name | Кофейня Сюрприз |
rating | 4.6 |
reviewCount | 128 |
phone | +74951234567 |
phones | ["+74951234567"] |
email | info@example.com |
website | http://example.com |
whatsapp | https://wa.me/74951234567 |
telegram | https://t.me/example |
instagram | https://instagram.com/example |
vk | https://vk.com/example |
fullAddress | Москва, Тверская улица, 5 |
city | Москва |
latitude / longitude | 55.7558 / 37.6173 |
primaryRubric | Кофейни |
rubrics | ["Кофейни", "Кафе"] |
isPromoted | false |
is24x7 | false |
hoursText | Mon: 09:00-21:00; Tue: 09:00-21:00; ...; Sun: closed |
photos | ["https://cdn.example.com/0000.jpg"] |
orgName | Sample Org |
Review records (pushed to the same dataset when maxReviews is above zero, with recordType set to review) carry the review text, rating, author, dates, source, photos and the official reply, keyed to their place by placeId.
How to Use
- Pick a mode:
search(combine a WHAT with a WHERE) orurl(paste 2GIS links or IDs). - In search mode, set a WHAT (
queryand/orcategoryQuery) and a WHERE (city, orlatitude/longitudewithradiusMeters, or abboxmap area). Leave WHAT empty to pull every place in the area. - Add filters (minimum rating, phone or website required, skip promoted entries), and set
maxReviewsabove zero to also fetch reviews. - Set Max places to control run size and cost, then click Start. Download the dataset as JSON, CSV or Excel, or read it through the API.
By text query in a city:
{"mode": "search","query": ["кофейня"],"city": "Москва","maxResults": 200}
By category around coordinates:
{"mode": "search","query": [],"categoryQuery": ["Рестораны"],"latitude": "55.7558","longitude": "37.6173","radiusMeters": 1000,"maxResults": 100}
In a map area, with reviews:
{"mode": "search","query": [],"categoryQuery": ["Аптеки"],"bbox": "37.55,55.70,37.70,55.80","maxReviews": 10}
From 2GIS URLs or IDs:
{"mode": "url","urls": ["https://2gis.ru/moscow/firm/70000001063551091","https://2gis.ru/moscow/search/coffee","70000001063551091"],"maxReviews": 50}
URL mode: supported shapes
| Shape | Example | Result |
|---|---|---|
| Raw numeric firm ID | 70000001063551091 | one place |
| Place page (any 2GIS domain) | https://2gis.ru/moscow/firm/70000001063551091, https://2gis.kz/almaty/firm/70000001041444514 | one place |
| Search page (any 2GIS domain, the city in the link scopes the search) | https://2gis.ru/moscow/search/%D0%BA%D0%BE%D1%84%D0%B5%D0%B9%D0%BD%D1%8F, https://2gis.ae/dubai/search/cafe | places matching the query in that city |
| Building page | https://2gis.kz/almaty/inside/9430047375164168 | places inside the building |
| Short link | https://go.2gis.com/<code> | followed to the real page, then handled as above |
A link that cannot be understood, a short link that cannot be resolved, or a city in a link that 2GIS does not know is skipped with a warning in the run log. It is never a silent empty result.
Default input: if you leave the 2GIS URLs or IDs field untouched in URL mode, the actor now scrapes one example of each shape above (capped by Max places) instead of a single place. Clear the field and paste your own links to scrape only those.
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/2gis-places-scraper").call(run_input={"mode": "search", "query": ["кофейня"], "city": "Москва"})for place in client.dataset(run["defaultDatasetId"]).iterate_items():print(place["name"], place["phone"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/2gis-places-scraper').call({ mode: 'search', query: ['кофейня'], city: 'Москва' });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Result caps and the 2GIS ceiling
2GIS caps a single query near 3000 results. Max places is shared fairly across every query, category and URL job in the run. To collect more places for a city, split the search into several narrower queries, categories or map areas.
Resume and recurring updates
- Resume (
resumeFromRunId) continues one interrupted crawl: paste its run or dataset id and this run skips places already collected there (their reviews are not re-fetched either), so you do not pay twice. - Incremental mode (
incrementalMode) is for scheduling this actor on the same search again and again. The actor remembers the previous run itself, no run id to paste. The first run returns everything asNEW; later runs return onlyNEW,UPDATEDandREAPPEAREDplaces and reviews by default. Places and reviews are tracked separately, so a place getting a brand new review does not itself becomeUPDATED. Turn onemitUnchangedoremitExpiredto also return (and be billed for) unchanged or vanished rows. Every output field is compared except these place fields (they change on every fetch, or are derived or re-sent copies of compared fields; all still returned in the output):fullId,contactsRaw,adsRaw,scrapedAt,pageNumber,searchUrl,searchRubricId,searchRubricLabel,createdAt,updatedAt,mainPhotoUrl,brand,attributeGroups,scheduleSpecial,phoneText,phoneValue;ignoreFieldsForChangesexcludes more (a name matches at any depth, dotted paths likeaddress.citywork), and changing it never causes a wave of UPDATED rows.stateKeynames or shares a monitoring campaign; leave it blank and the actor derives one automatically from your search and filter setup.
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 record, 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.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you have not authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto 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 |
|---|---|---|---|
mode | string | search | search (query / category / city / coordinates / map area) or url (2GIS links or IDs). |
query | array | ["кофейня"] | WHAT to find, as free text. Each query runs separately. Optional. |
categoryQuery | array | [] | WHAT to find, as category names matched against the 2GIS category tree. Optional, combines with query. |
latitude | string | (none) | WHERE, center latitude. Set together with longitude. Overrides city. |
longitude | string | (none) | WHERE, center longitude. Set together with latitude. |
radiusMeters | integer | 1000 | Search radius in meters around the coordinates (max 40000). |
bbox | string | (none) | WHERE, map area as lon1,lat1,lon2,lat2 (south west then north east). Overrides city and coordinates. |
urls | array | (none) | 2GIS links (place, search, building, short link) or raw numeric IDs. Used only when mode is url. |
city | string | Москва | WHERE, by city name. Ignored if coordinates or bbox are set. |
language | string | ru | Response language for names and content. For a city or link on another 2GIS country site (for example 2gis.ae or 2gis.kz) the matching local locale is used automatically when this language is not offered there (Russian on 2gis.ae is served in English). |
sortBy | string | relevance | relevance, rating, or distance (coordinates only, otherwise falls back to relevance). |
minRating | string | (none) | Keep only places with rating at or above this value (0 to 5). |
minReviews | integer | (none) | Keep only places with at least this many reviews. |
onlyWithPhone | boolean | false | Skip places that have no phone number. |
onlyWithWebsite | boolean | false | Skip places that have no website. |
rubricIds | array | [] | Exact 2GIS category ids, one search per id (search mode). |
onlyWithPhotos | boolean | false | Search mode: only places with photos (2GIS-side filter). |
onlyWithGoods | boolean | false | Search mode: only places listing goods or a menu (2GIS-side filter). |
openNow | boolean | false | Search mode: only places open at run time (2GIS-side filter). |
skipAds | boolean | false | Skip advertising or promoted entries. |
maxReviews | integer | 0 | Reviews to fetch per place. 0 disables review fetching. Reviews are pushed as separate records. Capped at 1000 per place. |
reviewsSort | string | date_edited | Order of fetched reviews. |
reviewsProvider | string | all | Keep all sources, 2GIS only, or Flamp only. |
reviewsRating | string | all | Keep all reviews, only positive (4 to 5 stars), or only negative (1 to 3 stars). |
reviewsMinRating | string | (none) | Keep only reviews at or above this star rating (1 to 5). |
reviewsWithAnswer | boolean | false | Keep only reviews that have an official reply. |
reviewsStartDate | string | (none) | Keep only reviews created on or after this date (YYYY-MM-DD). |
reviewsKeyword | string | (none) | Keep only reviews whose text contains this word or phrase. |
includePhotos | boolean | true | Include photo URLs available in the place record. |
maxResults | integer | 10 | Maximum total places across all queries and URLs, shared fairly across them. 0 means unlimited (capped at the 2GIS per query ceiling of about 3000). |
proxy | object | Apify Proxy (datacenter) | Connection settings. |
mcpConnectors | array | (none) | Optional: send a summary of each record to apps you authorized under Integrations. |
notionParentPageUrl | string | (none) | Notion connector only: page under which item pages are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. Does not affect the dataset. |
resumeFromRunId | string | (none) | Continue one interrupted crawl by run or dataset id. |
incrementalMode | boolean | false | Recurring monitoring: classify places and reviews as new, updated, unchanged, reappeared, or (places only) expired, against the actor's own remembered state. |
stateKey | string | (none) | Name the incremental monitoring campaign. Auto derived from the search and filters when blank. |
emitUnchanged | boolean | false | Also return (and bill) unchanged places and reviews in incremental mode. |
emitExpired | boolean | false | Also return (and bill) places no longer found, in incremental mode (expired rows appear only after a run scans the full search). |
ignoreFieldsForChanges | string list | (none) | Incremental mode only: field names that never count as a change (still returned in the output). Always ignored on places: fullId, contactsRaw, adsRaw, scrapedAt, pageNumber, searchUrl, searchRubricId, searchRubricLabel, createdAt, updatedAt, mainPhotoUrl, brand, attributeGroups, scheduleSpecial, phoneText, phoneValue. |
Sort by also accepts opened_time (newest listings first) and name in search mode.
New place fields (additive): createdAt, updatedAt, mainPhotoUrl, brand, attributeGroups, scheduleSpecial (date-specific hours, when 2GIS lists them), phoneText, phoneValue, searchRubricId, searchRubricLabel, searchUrl, pageNumber, scrapedAt. They are excluded from incremental change detection (listed in full under Resume and incremental above), so existing monitored lists do not flag a one-time wave of updates. searchRubricLabel is the real category name of the searched rubric (null when the place does not list it). searchUrl is the public 2GIS search page for a text search in a city, on that city's own domain (2gis.ru, 2gis.kz, 2gis.ae and so on); it is null for coordinate, map-area and category-id searches, which have no public link. onlyWithWebsite is applied by this actor to the place's website field. Billing is unchanged.
Output Example
Sample shape: values are illustrative placeholders, not from a live listing.
{"recordType": "place","id": "70000001063551091","name": "Кофейня Сюрприз","url": "https://2gis.ru/moscow/firm/70000001063551091","type": "branch","rating": 4.6,"reviewCount": 128,"primaryRubric": "Кофейни","rubrics": ["Кофейни", "Кафе"],"phone": "+74951234567","phones": ["+74951234567"],"email": "info@example.com","website": "http://example.com","whatsapp": "https://wa.me/74951234567","telegram": "https://t.me/example","instagram": "https://instagram.com/example","vk": "https://vk.com/example","fullAddress": "Москва, Тверская улица, 5","country": "Россия","region": "Москва","city": "Москва","district": "Тверской","street": "Тверская улица","houseNumber": "5","postcode": "125009","latitude": 55.7558,"longitude": 37.6173,"is24x7": false,"hoursText": "Mon: 09:00-21:00; Tue: 09:00-21:00; Wed: 09:00-21:00; Thu: 09:00-21:00; Fri: 09:00-21:00; Sat: 10:00-20:00; Sun: closed","photos": ["https://cdn.example.com/0000.jpg"],"photoCount": 1,"orgName": "Sample Org","isPromoted": false,"attributesByTag": { "food_service_food_european": "Европейская кухня" }}
Output views
The dataset has four views in the Console: Places Overview, Contacts (Phones, Emails, Socials), Reviews and Changes (incremental mode). All records stay in one dataset; review rows carry recordType: review.
Plan Requirement
The default proxy setting (Apify Proxy, datacenter) works for this actor: the 2GIS data service it reads is not blocked from datacenter addresses, so no paid proxy group is required for normal runs. If a connection is refused, the actor rotates to the next available connection automatically. For large or frequent runs the residential proxy group gives more headroom and also rotates across nearby countries; pick it under Connection. Apify free plans do not include residential proxies.
What you see in the run log when the connection is a problem:
- If the selected connection is unavailable, the log says "The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable." Results keep flowing, with a later note "Served over the backup connection (the default connection was unavailable)."
- If the proxy refuses your account outright and nothing could be read, the run fails with "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required" (or check your own proxy URLs' credentials).
- If residential was chosen on a plan without it and the backup also fails: "No results: residential proxies are unavailable on this run ... and the backup connection could not load the requested 2GIS pages."
- If every request fails: "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search."
Note that the public 2gis.ru, 2gis.ae and 2gis.kz web pages redirect to an interstitial page for automated traffic. The actor does not scrape those pages: URL mode reads the place, search or building id from your link and fetches it from the data service, so link shapes are accepted but the page itself is never opened.
FAQ
How much does it cost?
You pay per record returned (the standard result event, one per place row and one per review row pushed to the dataset), plus a reviews-extraction charge once per place for which at least one review row was actually pushed in the run (a fetch that returns nothing, or whose rows are suppressed in incremental mode, is not charged). Reviews are off by default (maxReviews is 0). The Pricing tab shows the current rates. Use Max places to cap the cost of any run.
Is it legal to scrape 2GIS?
This actor collects only publicly available places data. You are responsible for how you use it: follow 2GIS's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Reviews and photos are contributed by third parties and may carry their own rights.
Why is there no separate "category" or "coordinates" mode?
Search mode already covers all of it. WHERE precedence is a map area (bbox) beats coordinates (latitude/longitude) beats city, the more specific one wins and the others are ignored. WHAT is query and/or categoryQuery; leave both empty to pull every place found in the area.
Can I get only new or changed places on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated and reappeared places and reviews by default, classified against the run before it, and unchanged rows are not billed unless you turn on Emit unchanged.
Why did my run fail instead of returning an empty dataset?
A run fails only in two situations: resumeFromRunId points to a run or dataset id that could not be read, or incrementalMode is combined with resumeFromRunId on a search that already has saved incremental state (remove one of the two, or use a different stateKey). Everything else, including a search or category that matches nothing, or review filters that keep zero reviews, finishes as a normal successful run with an empty or smaller dataset.
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 a summary of each place or review into Notion, Linear or Airtable.
🔗 Want more leads data?
Pair this actor with these related scrapers from the same team:
| 📇 Google Maps Scraper Extract business data from Google Maps at scale. Get names, addresses, phone numbers... | 📇 TrueLocal AU Directory Listings & Reviews Scraper Scrape TrueLocal.com.au business listings by keyword, location, or URL. Extract names... |
| ✈️ Naver Map Scraper From $1/1K. Scrape Naver Map places by keyword or URL: names, categories, ratings... | 📇 Herold.at Scraper From $0.80/1K. Scrape Herold.at business listings across Austria into clean JSON. Extract... |
| 📇 Yellow Pages NZ From $0.8/1K. Scrapes business listings from Yellow.co.nz (New Zealand Yellow Pages)... | 📇 Local.ch From $1/1K. Pull structured company data from local.ch, including name, address, GPS... |
💬 Support
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. 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.