# Naver Place Reviews Scraper (`crawlerbros/naver-place-reviews-scraper`) Actor

Extract visitor reviews, ratings, keywords, photos and visit details from Naver Place, plus linked Naver Blog reviews. Supports place URL/ID and keyword search input. Korean sentiment analysis ready.

- **URL**: https://apify.com/crawlerbros/naver-place-reviews-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** SEO tools, Travel, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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 Reviews + Blog — Korean Review Scraper

Extract **visitor reviews** and **blog reviews** from [Naver Place](https://place.naver.com) — Korea's #1 local business platform. Get full review text (Korean), star ratings, reviewer profiles, visit details, voted keywords, photos, owner replies, linked Naver Blog posts, and aggregated review statistics. No login, no API key, no paid proxy required.

### What this actor does

- **Visitor reviews** — full review body, 1–5 star rating, reviewer nickname + profile URL + total review count, review/visit dates, visit count, voted keywords (음식이 맛있어요, 분위기가 좋아요…), photos, menu item mentioned, owner reply
- **Blog reviews** — Naver Blog posts linked to the place: title, contents, post URL, blogger name + home, thumbnail, rank
- **Review statistics** — average rating, total review count, star distribution (5★→1★), review themes, voted-keyword analysis
- **Two input modes** — direct Place URLs/IDs **or** keyword search to discover places first
- **Parallel place scraping** — configurable concurrency with per-place retries
- **Empty fields are omitted** — every record only contains fields Naver actually returned

### How it works

Naver Place's review page (`pcmap.place.naver.com/place/<id>/review/visitor`) fully **server-side renders** ~20 visitor reviews, linked blog reviews, and review statistics into its `window.__APOLLO_STATE__` blob. This actor parses that state directly with `curl_cffi` Chrome TLS impersonation — no browser, no login, no captcha, no proxy needed for moderate traffic.

> Note on pagination: Naver's cursor-pagination GraphQL API (`pcmap-api.place.naver.com/graphql`) is protected by an interactive captcha against automated requests, so this actor collects the reviews Naver embeds in the SSR page (≈20 per place). This matches the reliability-first design of this repo's other Naver actors (see `NaverMapScraper`).

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `placeUrls` | array | — | Naver Place URLs or bare Place IDs. Accepts `map.naver.com/p/entry/place/<id>`, `pcmap.place.naver.com/place/<id>/...`, `m.place.naver.com/...`, or just the numeric ID. |
| `searchKeywords` | array | — | Keywords to find places first (e.g. `강남 맛집`, `Seoul BBQ`). |
| `maxPlacesPerKeyword` | int | 3 | Max places scraped per keyword (1–50). |
| `maxReviews` | int | 20 | Max visitor reviews collected per place (SSR embeds ~20). |
| `includeBlogReviews` | bool | true | Also emit linked Naver Blog reviews. |
| `includeReviewPhotos` | bool | false | Include photo URLs on each visitor review. |
| `includeReviewStats` | bool | true | Emit one stats record per place. |
| `maxConcurrency` | int | 3 | Places scraped in parallel (1–10). |
| `maxItems` | int | 100 | Hard cap on total records (1–5000). |
| `proxyConfiguration` | object | AUTO | Optional proxy. |

#### Example: fetch reviews for specific places

```json
{
  "placeUrls": [
    "https://map.naver.com/p/entry/place/38239053",
    "1000750444"
  ],
  "includeReviewPhotos": true,
  "maxItems": 50
}
```

#### Example: discover places by keyword, then fetch reviews

```json
{
  "searchKeywords": ["강남 맛집", "홍대 카페"],
  "maxPlacesPerKeyword": 3,
  "includeBlogReviews": true,
  "includeReviewStats": true,
  "maxItems": 100
}
```

### Output

Each record has a `reviewType` field: `visitor`, `blog`, or `stats`.

#### Visitor review record

| Field | Description |
|---|---|
| `reviewType: "visitor"` | Record kind |
| `placeId`, `placeName`, `placeCategory`, `placeAddress`, `placeRoadAddress` | Place identity |
| `placeRating`, `placeTotalReviews` | Place-level rating & count |
| `placeUrl` | Canonical place URL |
| `searchKeyword` | Keyword that found this place (search mode only) |
| `reviewId` | Naver review ID |
| `reviewText` | Full review body (Korean) |
| `reviewRating` | 1–5 stars |
| `reviewerName`, `reviewerProfileUrl`, `reviewerReviewCount` | Reviewer identity |
| `reviewDate`, `visitDate` | Review creation & visit dates (YYYY-MM-DD) |
| `visitCount` | "n번째 방문" count |
| `votedKeywords` | e.g. `음식이 맛있어요`, `분위기가 좋아요` |
| `reviewPhotos` | Photo URLs (when `includeReviewPhotos`) |
| `reviewReplyText`, `reviewReplyDate` | Business owner's reply |
| `menuItem` | Menu item mentioned in the review |
| `originType` | e.g. 영수증 (receipt-verified) |
| `language`, `translatedText` | Review language + auto-translation when available |
| `scrapedAt` | ISO 8601 timestamp |

#### Blog review record

| Field | Description |
|---|---|
| `reviewType: "blog"` | Record kind |
| `placeId`…`placeUrl` | Place identity (same as above) |
| `blogTitle` | Blog post title |
| `blogContents` | Blog post excerpt/contents |
| `blogUrl` | Link to the full blog post |
| `bloggerName`, `bloggerHome` | Blogger identity |
| `blogThumbnailUrl` | Post thumbnail |
| `blogRank` | Position in Naver's blog review list |
| `scrapedAt` | ISO 8601 timestamp |

#### Stats record (one per place)

| Field | Description |
|---|---|
| `reviewType: "stats"` | Record kind |
| `averageRating` | Average visitor review score |
| `totalReviewCount` | Total visitor reviews |
| `starDistribution` | `{5: n, 4: n, 3: n, 2: n, 1: n}` |
| `reviewThemes` | `[{label, count}]` — theme analysis |
| `votedKeywordStats` | `[{keyword, count}]` — most-voted keywords |

### Use Cases

- **Korean market entry research** — what locals say about competitors
- **Restaurant/cafe competitive intelligence** — ratings, keywords, sentiment
- **Customer sentiment analysis** — NLP-ready structured Korean review data
- **Brand reputation monitoring** in Korea
- **Academic research** on Korean consumer behavior

### FAQs

**Is a Naver login or API key required?** No. The review page is public and server-side rendered.

**How many reviews can I get per place?** Naver embeds ~20 visitor reviews per SSR page. Naver's deeper pagination API is captcha-protected against automated requests, so this actor intentionally collects the SSR-embedded set (matching the reliability-first design of this repo's Naver actors).

**Why is `blogDate` missing?** Naver does not expose a publish date for blog reviews in the review SSR data, and the blog post ID in the URL is not a timestamp — emitting a wrong date would be worse than none.

**Can I get reviews for places I don't know yet?** Yes — use `searchKeywords` to discover places first (e.g. `강남 맛집`), then reviews are scraped automatically.

**What are the Korean fields?** `votedKeywords` are Naver's official review-vote tags (음식이 맛있어요 = "food was delicious", 분위기가 좋아요 = "nice atmosphere"); `originType: 영수증` marks receipt-verified reviews.

**Does this actor work with the existing NaverMapScraper?** Yes — use NaverMapScraper to build a place list (search/detail enrichment), then feed the place IDs into this actor's `placeUrls` for full review extraction.

### Data Source

All data comes from the public [Naver Place](https://place.naver.com) review pages (`pcmap.place.naver.com`) — a free, publicly accessible source requiring no login or API key.

# Actor input Schema

## `placeUrls` (type: `array`):

Naver Place URLs or Place IDs. Examples: 'https://map.naver.com/p/entry/place/38239053', 'https://pcmap.place.naver.com/place/38239053/home', or just '38239053'.

## `searchKeywords` (type: `array`):

Search keywords to find places, then scrape their reviews. Example: \['강남 맛집', 'Seoul BBQ']. Use this instead of placeUrls to discover places automatically.

## `maxPlacesPerKeyword` (type: `integer`):

Maximum number of places to scrape per keyword search (when searchKeywords is used).

## `maxReviews` (type: `integer`):

Maximum number of visitor reviews to collect per place (up to 1000). Each page of the SSR embeds ~20 reviews; deeper pages are fetched by cursor where available.

## `includeBlogReviews` (type: `boolean`):

Also scrape blog reviews (Naver Blog posts linked to the place) from the same review page.

## `includeReviewPhotos` (type: `boolean`):

Include photo URL lists attached to each visitor review.

## `includeReviewStats` (type: `boolean`):

Emit one aggregated stats record per place: average rating, total count, star distribution, voted-keyword analysis.

## `maxConcurrency` (type: `integer`):

How many places to scrape in parallel. Higher is faster but increases rate-limit risk without a proxy.

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

Hard cap on total records emitted across all places (1-5000).

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

Optional proxy. Naver Place works without a proxy for moderate traffic; use AUTO or residential for high concurrency.

## Actor input object example

```json
{
  "placeUrls": [
    "https://map.naver.com/p/entry/place/38239053"
  ],
  "searchKeywords": [
    "스타벅스 강남"
  ],
  "maxPlacesPerKeyword": 3,
  "maxReviews": 20,
  "includeBlogReviews": true,
  "includeReviewPhotos": false,
  "includeReviewStats": true,
  "maxConcurrency": 3,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `reviews` (type: `string`):

Dataset containing visitor reviews, blog reviews, and place review statistics.

# 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 = {
    "placeUrls": [
        "https://map.naver.com/p/entry/place/38239053"
    ],
    "searchKeywords": [
        "스타벅스 강남"
    ],
    "maxPlacesPerKeyword": 3,
    "maxReviews": 20,
    "includeBlogReviews": true,
    "includeReviewPhotos": false,
    "includeReviewStats": true,
    "maxConcurrency": 3,
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/naver-place-reviews-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 = {
    "placeUrls": ["https://map.naver.com/p/entry/place/38239053"],
    "searchKeywords": ["스타벅스 강남"],
    "maxPlacesPerKeyword": 3,
    "maxReviews": 20,
    "includeBlogReviews": True,
    "includeReviewPhotos": False,
    "includeReviewStats": True,
    "maxConcurrency": 3,
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/naver-place-reviews-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 '{
  "placeUrls": [
    "https://map.naver.com/p/entry/place/38239053"
  ],
  "searchKeywords": [
    "스타벅스 강남"
  ],
  "maxPlacesPerKeyword": 3,
  "maxReviews": 20,
  "includeBlogReviews": true,
  "includeReviewPhotos": false,
  "includeReviewStats": true,
  "maxConcurrency": 3,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call crawlerbros/naver-place-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/naver-place-reviews-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/OYxbCqdVC6sSo9jPy/builds/6aCs091fF9du79RGn/openapi.json
