Naver Place Multi-Location Review Monitor
Pricing
from $2.00 / 1,000 location checks
Naver Place Multi-Location Review Monitor
Enter Naver Place locations (ID + your label) and get change rows - new reviews, owner replies added or edited - plus one free summary row per location: unanswered reviews, oldest unanswered age, reply rate, rating, top keywords. For franchises and agencies. No reviewer personal data.
Pricing
from $2.00 / 1,000 location checks
Rating
0.0
(0)
Developer
SUNGHWAN CHO
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
8 hours ago
Last modified
Categories
Share
Enter a list of Naver Place locations (place ID + your own label and group) and get, on every run, what changed since the last run — new reviews, owner replies added, owner replies edited — plus one status row per location: how many reviews are still unanswered, how old the oldest unanswered review is, reply rate, average rating and top keywords. Built for franchise head offices and agencies that manage many stores on Naver Map (Naver Place), South Korea's main map and local review service. Reviewer identity is never collected.
No login, no API key and no browser needed.
Which Actor do I need?
| Multi-Location Review Monitor (this Actor) | Naver Place Reviews Scraper | |
|---|---|---|
| Purpose | A recurring status report across many locations: what changed and what is still unanswered | A raw review export: every review of a place as a row |
| Typical user | Franchise HQ, multi-store brand, marketing or operations agency | Analyst, researcher, data pipeline, LLM input |
| Input | Locations with your label and group tags | Place IDs or URLs |
| Rows you get | Only changes (newReview, ownerReplyAdded, ownerReplyChanged) + one summary row per location | All reviews up to your limit (photos, visit context, reactions, verification type) |
| Owner replies | Detects replies added or edited after the review was first seen | Reply text as it is at scrape time |
| Unanswered backlog | Count, oldest age in days and reply rate per location | Not calculated |
| Scheduled run with nothing new | Location summary rows with the current unanswered status | Place summary rows only |
Use this Actor for a daily or weekly check of your stores. Use the Reviews Scraper when you need the full review history or fields such as photos. Need place IDs first? Naver Place Search Scraper returns them in its id field.
What you get
Every row has a type field.
Change rows ("type": "change") — one per detected change, with the full review:
eventType:newReview(a review not seen in earlier runs),ownerReplyAdded(a known review got its first owner reply) orownerReplyChanged(the reply text was edited)- Your
labelandgroup,placeId,placeName rating, reviewtext,visitedAt,createdAt(when the review was written), keyword tags in Korean and as English codes,menuItemhasOwnerReply,ownerReply,ownerReplyDateLabelneedsAttention:truewhen the star rating is 2 or lower, or the text contains one of these Korean complaint terms: 불친절, 불만, 실망, 불결, 불쾌, 최악, 환불, 위생…문제. A simple, fixed rule — not an AI judgment- E-mail addresses and phone numbers written inside the review or the reply are replaced with
[email]/[phone]
Location summary rows ("type": "locationSummary", free) — one per location on every run, also when nothing changed:
statusandstopReason, so a blocked or failed location is never mistaken for "no new reviews"newReviewCount,ownerReplyAddedCount,ownerReplyChangedCountsincepreviousCheckedAt, andavgRatingOfNewReviewsunansweredCountInSample,oldestUnansweredDaysInSample(+ the review ID and visit date),replyRateInSample,needsAttentionUnansweredCountInSamplereviewsInSample,avgRatingInSample,lowRatingCountInSample,topKeywordsInSample(top 5 keyword tags)placeAvgRating,placeTotalReviewCount(Naver's headline numbers for the whole place)
Fields ending in InSample are calculated over the reviews read in this run — reviews visited within the observation window (windowDays, default 30), up to maxReviewsPerLocation. They are not statistics of the place's whole history.
One run summary row ("type": "runSummary", free): locations by status, total change rows, total unanswered reviews, requests sent and retried. The same report with a per-location list is saved in the run's key-value store as RUN_SUMMARY.
Missing values are null; keys are never left out. Numbers are numbers.
Not collected: reviewer nicknames, profile pictures, profile links, user IDs and receipt links are never requested from Naver.
Use cases
- Agency reporting — one scheduled run for all client stores; group rows by
group(client) andlabel(store) for the weekly report - Reply follow-up — list locations where
unansweredCountInSampleis above 0 oroldestUnansweredDaysInSampleis over your target, and check that replies were actually posted (ownerReplyAdded) - Reply audit —
ownerReplyChangedshows when a store edited a reply after you first saw it - Alerts — send
changerows withneedsAttention: trueto Slack, e-mail or a sheet through Apify integrations - AI agents — a short list in, flat rows out;
RUN_SUMMARYgives the result without reading the log
Input
| Field | Description |
|---|---|
locations | Required. List of objects: placeId (Naver Place ID or Naver Map place URL), optional label and group (your own text, copied to every row). A plain ID or URL string also works. |
windowDays | Observation window in days, by visit date. Default 30. Changes are detected and summary numbers are calculated for reviews inside this window. |
maxReviewsPerLocation | Upper limit of reviews read per location inside the window. Default 200, maximum 500. |
emitExistingOnFirstRun | Default false. The first run for a location only sets the starting point (summary row, no change rows). Set true to also receive the reviews currently in the window as newReview rows with isBaseline: true. |
historyStoreName | Key-value store that remembers what was already reported. Default multi-location-review-monitor-history. Use one name per client or schedule. |
proxyConfiguration | Keep the default Apify Proxy. |
{"locations": [{ "placeId": "1922651675", "label": "Seongsu store", "group": "Client A" },{ "placeId": "https://map.naver.com/p/entry/place/1559904682", "label": "Seoul Forest store", "group": "Client A" }],"windowDays": 30}
Output
A change row from a test run:
{"type": "change","eventType": "newReview","source": "naver","schemaVersion": 1,"placeId": "1922651675","label": "Demo store 1","group": "Demo client","placeName": "노틀던","reviewId": "6abf33448f9dd532461b9928","rating": 5,"text": "디저트도 예쁘고 맛있어요!! 다른메뉴도 먹으러 또오고싶어요","visitedAt": "2026-10-02T04:23:12.000Z","createdAt": "2026-10-02T04:29:56.000Z","visitedLabel": "10.2.금","createdLabel": "10.2.금","keywords": ["커피가 맛있어요", "디저트가 맛있어요", "아늑해요", "음악이 좋아요"],"keywordCodes": ["coffee_good", "dessert_good", "cozy", "music_good"],"menuItem": "노틀던 누아","hasOwnerReply": false,"ownerReply": null,"ownerReplyDateLabel": null,"needsAttention": false,"isBaseline": false,"previousCheckedAt": "2026-09-30T00:00:00.000Z","url": "https://map.naver.com/p/entry/place/1922651675?placePath=/review","scrapedAt": "2026-10-02T06:45:24.139Z"}
A location summary row from a first run with "windowDays": 14:
{"type": "locationSummary","source": "naver","schemaVersion": 1,"placeId": "1922651675","label": "Demo store 1","group": "Demo client","placeName": "노틀던","status": "completed","stopReason": "windowCovered","errorMessage": null,"isFirstCheck": true,"previousCheckedAt": null,"windowDays": 14,"windowStart": "2026-09-18T06:45:03.688Z","windowFullyScanned": true,"newReviewCount": null,"ownerReplyAddedCount": null,"ownerReplyChangedCount": null,"changeRowsSaved": 0,"avgRatingOfNewReviews": null,"reviewsInSample": 34,"ratedReviewsInSample": 34,"avgRatingInSample": 5,"lowRatingCountInSample": 0,"repliedCountInSample": 0,"unansweredCountInSample": 34,"replyRateInSample": 0,"oldestUnansweredDaysInSample": 13,"oldestUnansweredReviewId": "6aacf2418c8d40a9626925ac","oldestUnansweredVisitedAt": "2026-09-18T08:05:40.000Z","needsAttentionUnansweredCountInSample": 0,"topKeywordsInSample": [{ "code": "dessert_good", "keyword": "디저트가 맛있어요", "count": 31 },{ "code": "special_menu", "keyword": "특별한 메뉴가 있어요", "count": 20 },{ "code": "coffee_good", "keyword": "커피가 맛있어요", "count": 19 },{ "code": "drink_good", "keyword": "음료가 맛있어요", "count": 12 },{ "code": "kind", "keyword": "친절해요", "count": 10 }],"placeAvgRating": 4.97,"placeTotalReviewCount": 1160,"pagesFetched": 1,"locationCheckCharged": false,"input": null,"url": "https://map.naver.com/p/entry/place/1922651675?placePath=/review","scrapedAt": "2026-10-02T06:45:04.152Z"}
Export the dataset as JSON, CSV or Excel, or read it through the Apify API. Filter by type to separate changes from summaries.
How change detection works
- First run for a location reads the observation window and stores a fingerprint of each review's owner reply in the key-value store
historyStoreNamein your Apify account. It returns the summary row only (isFirstCheck: true, change countsnull), unlessemitExistingOnFirstRunis on. - Later runs read the window again and compare:
- a review that is not in history →
newReview. Naver lists reviews by visit date, and people often write days after the visit; such late reviews are found as long as the visit is inside the window. A review that is not in history but was written before the previous check (it was outside that run's scan) is recorded silently and not reported as new. - a known review that now has a reply and had none →
ownerReplyAdded - a known review whose reply text differs (ignoring whitespace) →
ownerReplyChanged
- a review that is not in history →
- Only change rows that were actually stored are recorded in history. Rows cut off by your max cost per run, or lost to an error, are reported again on the next run.
Status values
status | Meaning |
|---|---|
completed | The window was read and all changes were stored. stopReason is windowCovered, endOfList or maxReviewsReached (window larger than maxReviewsPerLocation; see windowFullyScanned). |
partial | A later page failed after retries. Changes found so far are reported; the location check is not charged. |
budgetLimited | Your max cost per run was reached at this location. |
notStarted | Not requested and not charged (costLimitReached or runTimeoutApproaching). |
failed | blocked (Naver kept answering HTTP 429/403), requestFailed, placeNotFound, invalidInput or datasetWriteFailed. Counts are null, not 0. Not charged. |
If every location fails, the run itself fails. Otherwise the run succeeds and the rows tell you what to re-check.
What is charged
Pay per event (prices are on the Pricing tab):
location-check— once per location whose observation window was read successfully. Charged also when nothing changed, because the summary row (unanswered count, reply rate, …) is produced on every run. Not charged forfailed,partial,notStartedandbudgetLimited-before-check locations.change— once per change row stored in the dataset.
locationSummary and runSummary rows are free. If the run reaches your max cost per run, the Actor stops cleanly: the number of change rows stored equals the number charged and the number reported in changeRowsSaved; remaining locations are notStarted and not requested. locationCheckCharged on each summary row and locationChecksCharged on the run summary show the checks charged.
Example: 50 locations checked daily with 40 changes a day = 50 location checks + 40 change events per run.
Limits
- Changes outside the window are not seen. A reply added to a review visited 45 days ago is not reported with
windowDays: 30. Use a longer window if stores answer late; reading more reviews does not add change charges. - Review text edits and deleted reviews are not reported. A removed owner reply is not reported as an event; the summary row always shows the current unanswered count.
- Newest visit first only, as listed by Naver.
InSamplenumbers describe the window, not the place's lifetime. - Hospitals and clinics: Naver hides star ratings for medical businesses, so
rating,avgRatingInSampleandplaceAvgRatingarenullthere. createdAtcomes from the timestamp inside Naver's review ID and is returned only when its Korea-time date matches Naver's own "written" label; otherwisenull.- Owner reply dates have no year on Naver (e.g.
9.30.수), so they are kept as the original label. - Masking is pattern based (e-mail addresses, Korean mobile and landline numbers). Review text is written by users and may still contain personal details they chose to share; handle it accordingly.
- One run at a time per history name. Two runs sharing a
historyStoreNameat the same moment can report the same change twice. - Timestamps are UTC (
Z); Naver's labels are Korea time (KST, UTC+9). - The Actor only reads public pages. It does not log in and does not post replies.
Implementation notes
- Requests go through Apify Proxy with a new proxy session for every attempt, up to 6 attempts with increasing waits. Naver rate-limits repeated requests from one IP (HTTP 429). The first private version of this Actor (0.1) used a shared no-proxy, no-retry request layer and was blocked with HTTP 429 on Apify; version 0.2 replaces that layer, for this Actor only, with the one already used by Naver Place Reviews Scraper.
- Up to 5 locations are read in parallel; charging, storing and history updates happen one location at a time, in input order. The time of the last completed check of all locations is kept in one
checkpointsrecord, so a location with no changes needs no storage write of its own. - Tests:
npm testruns the offline regression suite (429 retries, cost limit, reply change detection, masking, history).