# Naver Place Scraper (Korean Maps: Businesses + Reviews) (`kdatafactory/naver-place-scraper`) Actor

Scrape Korean business listings and reviews from Naver Place / Naver Maps by search query. Returns place details (name, category, address, phone, rating, review count) plus review text, rating and keywords. Privacy-safe: no reviewer names/IDs collected.

- **URL**: https://apify.com/kdatafactory/naver-place-scraper.md
- **Developed by:** [Seok June Park](https://apify.com/kdatafactory) (community)
- **Categories:** E-commerce, Automation, Other
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Naver Place Scraper — Korean Business Listings & Reviews

Scrape **business listings and reviews from [Naver Place](https://map.naver.com) / Naver Maps** — Korea's dominant local-search and maps platform — by keyword. Give it a Korean search query like `강남역 카페` ("Gangnam Station cafe") and get back clean, structured JSON for every business: name, category, address, phone, rating, review count, plus the review text, rating, date and keywords.

Naver is where Korean consumers actually find and review local businesses (Google Maps has minimal coverage in Korea). If you need Korean local-business data, this is the source.

> **Privacy-first.** This actor **never collects reviewer names, IDs, or profile links.** Reviews contain only `text`, `rating`, `date`, and `keywords`. Business phone numbers and addresses are public business-registration information and are included.

---

### What it does

- Takes a Naver Maps search query (location + category works best).
- Pages through Naver's public, server-rendered search results.
- Extracts each business and its attached visitor reviews.
- Emits one record per business, with a nested `reviews` array, matching a stable schema.

### Input

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `searchQuery` | string | — (required) | Naver Maps query, e.g. `강남역 카페`, `홍대 맛집`, `제주 흑돼지`. |
| `maxPlaces` | integer | `20` | Max businesses to scrape. |
| `includeReviews` | boolean | `true` | Attach visitor reviews to each business. |
| `maxReviewsPerPlace` | integer | `20` | Max reviews per business. |
| `proxyConfiguration` | object | RESIDENTIAL / KR | Proxy settings (see *Proxy & rate limits*). |

#### Input example

```json
{
  "searchQuery": "강남역 카페",
  "maxPlaces": 20,
  "includeReviews": true,
  "maxReviewsPerPlace": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "KR"
  }
}
````

### Output

One dataset item per business. Reviews are nested under `reviews`. This is **real output** from a live run for `강남역 카페` (see `samples/sample-output.json` for 27 full records):

```json
{
  "source": "naver_place",
  "place_id": "1668757640",
  "name": "퍼스트커피랩 강남점",
  "category": "카페,디저트",
  "address": "서울 강남구 역삼동",
  "road_address": "봉은사로6길 39 1층",
  "phone": "0507-1315-7680",
  "rating": null,
  "review_count": 2792,
  "url": "https://m.place.naver.com/place/1668757640/home",
  "scraped_at": "2026-07-07T12:00:00+09:00",
  "reviews": [
    {
      "place_id": "1668757640",
      "rating": null,
      "text": "디저트들이 다양하고 커피가 맛있어요 :) 베이커리부터 구움과자 마들렌하고 휘낭시에까지 라인업 완벽!",
      "date": null,
      "keywords": ["디저트", "커피", "베이커리", "구움과자", "마들렌", "휘낭시에"]
    }
  ]
}
```

#### Field notes

- `place_id` — Naver's stable business identifier; use it to build the URL or re-fetch.
- `phone` — the business's public number (Naver's public safe-number is used when a raw landline is not exposed). Public business info.
- `rating` — Naver has deprecated the visible 1–5 star average for many businesses, so this is frequently `null`. `review_count` is the reliable popularity signal.
- `keywords` — salient tokens Naver highlights in each review snippet; a ready-made signal for sentiment/topic analysis.
- `date` — populated when the review source exposes a visit date; `null` for search-embedded snippets.

### Use cases

- **Local SEO monitoring** — track how your (or a client's) business ranks for target queries on Naver, and monitor review volume/velocity over time.
- **Review sentiment analysis for Korean market entry** — pull thousands of real Korean-language reviews and keywords for a category or district before launching, and feed them straight into an LLM or NLP pipeline. No PII to scrub — reviewer identity is never collected.
- **Competitor research** — snapshot every competitor in a district (address, phone, category, review counts) in one run.
- **AI agents & lead lists** — structured Korean local-business data for RAG, enrichment, or outreach.

### Proxy & rate limits

Naver aggressively **rate-limits and CAPTCHA-gates datacenter IPs.** This actor uses two paths:

1. **Search-page path (primary).** Reads Naver's public server-rendered search results. This works from many IPs and returns the businesses plus a few embedded reviews each — this is what produced the samples in this repo, with **no proxy**.
2. **Per-place GraphQL path (deep reviews).** `pcmap-api.place.naver.com/graphql`, used when you request more reviews than the search page embeds. This endpoint **returns a CAPTCHA challenge for datacenter IPs** (`HTTP 405` + `title="captcha"`; evidence in `samples/graphql-block-evidence.html`). The actor detects this and **gracefully falls back** to the search-embedded reviews.

**For reliable, high-volume runs and deep per-place review pagination, use Apify Proxy with the `RESIDENTIAL` group and country `KR`** (the default in the input schema). The actor honours `proxyConfiguration` throughout. Without a residential IP you will still get businesses and a handful of reviews each, but review depth and total place coverage are limited by Naver's anti-bot.

The actor runs politely: effectively concurrency 1 with ≥600 ms between requests.

### Legality & data ethics

- Only **public** data is collected — no login, no private endpoints.
- **No personal data.** Reviewer names, IDs, and profiles are never read or stored. Reviews carry only text, rating, date, and keywords. Business phone/address are public business-registration details.
- You are responsible for using the output in compliance with Naver's terms and applicable law (e.g. PIPA, GDPR). Because no personal data is emitted, output is safe to feed directly into analytics and LLM pipelines.

### Local development

```bash
npm install
## put input in ./storage/key_value_stores/default/INPUT.json, then:
npm start   # results land in ./storage/datasets/default
```

# Actor input Schema

## `searchQuery` (type: `string`):

A Naver Place / Naver Maps search query, exactly as you would type it into Korean Naver Maps. Combine a location and a category for best results, e.g. "강남역 카페" (Gangnam Station cafe), "홍대 맛집" (Hongdae restaurants), "제주 흑돼지" (Jeju black pork).

## `maxPlaces` (type: `integer`):

Maximum number of businesses to scrape for the query.

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

If enabled, each place record is enriched with visitor reviews (text, rating, date, keywords). Reviewer identity is never collected.

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

Maximum number of reviews to collect per place (only used when Include reviews is on).

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

Naver aggressively rate-limits and CAPTCHA-gates datacenter IPs. RESIDENTIAL proxies (Apify Proxy, group RESIDENTIAL, country KR) are strongly recommended for reliable runs and for deep per-place review pagination.

## Actor input object example

```json
{
  "searchQuery": "강남역 카페",
  "maxPlaces": 20,
  "includeReviews": true,
  "maxReviewsPerPlace": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "KR"
  }
}
```

# 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 = {
    "searchQuery": "강남역 카페"
};

// Run the Actor and wait for it to finish
const run = await client.actor("kdatafactory/naver-place-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 = { "searchQuery": "강남역 카페" }

# Run the Actor and wait for it to finish
run = client.actor("kdatafactory/naver-place-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQuery": "강남역 카페"
}' |
apify call kdatafactory/naver-place-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=kdatafactory/naver-place-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Naver Place Scraper (Korean Maps: Businesses + Reviews)",
        "description": "Scrape Korean business listings and reviews from Naver Place / Naver Maps by search query. Returns place details (name, category, address, phone, rating, review count) plus review text, rating and keywords. Privacy-safe: no reviewer names/IDs collected.",
        "version": "0.1",
        "x-build-id": "QkRDuoV8L0BQgMDBf"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/kdatafactory~naver-place-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-kdatafactory-naver-place-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/kdatafactory~naver-place-scraper/runs": {
            "post": {
                "operationId": "runs-sync-kdatafactory-naver-place-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/kdatafactory~naver-place-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-kdatafactory-naver-place-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "searchQuery"
                ],
                "properties": {
                    "searchQuery": {
                        "title": "Search query",
                        "type": "string",
                        "description": "A Naver Place / Naver Maps search query, exactly as you would type it into Korean Naver Maps. Combine a location and a category for best results, e.g. \"강남역 카페\" (Gangnam Station cafe), \"홍대 맛집\" (Hongdae restaurants), \"제주 흑돼지\" (Jeju black pork)."
                    },
                    "maxPlaces": {
                        "title": "Max places",
                        "minimum": 1,
                        "maximum": 300,
                        "type": "integer",
                        "description": "Maximum number of businesses to scrape for the query.",
                        "default": 20
                    },
                    "includeReviews": {
                        "title": "Include reviews",
                        "type": "boolean",
                        "description": "If enabled, each place record is enriched with visitor reviews (text, rating, date, keywords). Reviewer identity is never collected.",
                        "default": true
                    },
                    "maxReviewsPerPlace": {
                        "title": "Max reviews per place",
                        "minimum": 0,
                        "maximum": 200,
                        "type": "integer",
                        "description": "Maximum number of reviews to collect per place (only used when Include reviews is on).",
                        "default": 20
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Naver aggressively rate-limits and CAPTCHA-gates datacenter IPs. RESIDENTIAL proxies (Apify Proxy, group RESIDENTIAL, country KR) are strongly recommended for reliable runs and for deep per-place review pagination.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ],
                            "apifyProxyCountry": "KR"
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
