{
  "data": {
    "id": "C7P2a9cthLY2sPU9H",
    "actId": "l8lB2zLDoXJ2xjpAe",
    "userId": "zq8lKbpLzTjGDayPC",
    "startedAt": "2026-10-18T04:58:24.633Z",
    "finishedAt": "2026-10-18T04:58:40.886Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "CLI"
    },
    "stats": {
      "durationMillis": 16186,
      "runTimeSecs": 16.186,
      "computeUnits": 0.017984444444444445,
      "imageSizeBytes": 354258944
    },
    "options": {
      "useCache": true,
      "betaPackages": false,
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "createdByOrganizationMemberUserId": "GK9YjZRyQZVzOdoH5",
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"Naver Map Scraper Input\",\n  \"description\": \"Search Naver Map by keyword (optionally around a map area) or fetch specific places by URL/ID. Get business details, full menus with prices, weekly hours with breaks, photos, and visitor reviews.\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"mode\": {\n      \"title\": \"Mode\",\n      \"type\": \"string\",\n      \"description\": \"What to fetch. `search` discovers places by keyword; `byUrls` fetches places you already know (URLs or place IDs).\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"search\",\n        \"byUrls\"\n      ],\n      \"enumTitles\": [\n        \"Search places by keyword\",\n        \"Fetch specific places by URL or ID\"\n      ],\n      \"default\": \"search\",\n      \"prefill\": \"search\"\n    },\n    \"searchKeywords\": {\n      \"title\": \"Search keywords (mode=search)\",\n      \"type\": \"array\",\n      \"description\": \"Keywords to search on Naver Map, e.g. `강남 맛집` (Gangnam restaurants) or `이태원 카페` (Itaewon cafes). Include a region name for local results. Naver returns up to 100 places per keyword from the first page and up to ~300 via deeper pages; add a map area (Search coordinates + Radius) or narrower keywords for more.\",\n      \"editor\": \"stringList\",\n      \"default\": [\n        \"강남 맛집\"\n      ],\n      \"prefill\": [\n        \"강남 맛집\"\n      ]\n    },\n    \"placeUrls\": {\n      \"title\": \"Place URLs or IDs (mode=byUrls)\",\n      \"type\": \"array\",\n      \"description\": \"Naver Map places to fetch directly. Accepts full links (pcmap.place.naver.com, m.place.naver.com, map.naver.com/p/entry/place/...), `naver.me` short links, and bare numeric place IDs.\",\n      \"editor\": \"stringList\",\n      \"default\": [],\n      \"prefill\": []\n    },\n    \"sortBy\": {\n      \"title\": \"Sort order (mode=search)\",\n      \"type\": \"string\",\n      \"description\": \"How Naver orders search results. `distance` sorting needs Search coordinates.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"relevance\",\n        \"popular\",\n        \"tv\",\n        \"reviews\",\n        \"saved\",\n        \"distance\"\n      ],\n      \"enumTitles\": [\n        \"Relevance (Naver default)\",\n        \"Popular (인기순)\",\n        \"TV featured first (방영순)\",\n        \"Most reviewed first\",\n        \"Most saved/bookmarked first\",\n        \"Nearest first (needs coordinates)\"\n      ],\n      \"default\": \"relevance\",\n      \"prefill\": \"relevance\"\n    },\n    \"searchCoordinates\": {\n      \"title\": \"Search coordinates (mode=search)\",\n      \"type\": \"string\",\n      \"description\": \"Map center as `latitude,longitude`, e.g. `37.4979,127.0276` for Gangnam Station. Used to rank results around a point, for distance sorting, and as the center of an area sweep.\",\n      \"editor\": \"textfield\"\n    },\n    \"searchRadiusKm\": {\n      \"title\": \"Area radius in km (mode=search)\",\n      \"type\": \"integer\",\n      \"description\": \"When set together with Search coordinates, the actor sweeps the whole circle (grid of map centers) instead of one center — this is how to collect more than Naver's ~300-per-keyword limit. Needs a broad keyword (e.g. `맛집`).\",\n      \"minimum\": 1,\n      \"maximum\": 20\n    },\n    \"category\": {\n      \"title\": \"Category filter\",\n      \"type\": \"string\",\n      \"description\": \"Only keep places whose category contains this text (e.g. `한식`, `카페`, `Cafe`). Leave blank for all categories.\",\n      \"editor\": \"textfield\"\n    },\n    \"menuKeyword\": {\n      \"title\": \"Menu keyword filter\",\n      \"type\": \"string\",\n      \"description\": \"Only keep places whose menu names or descriptions contain this text (e.g. `피자`). Requires Include place details to be on. Leave blank for all menus.\",\n      \"editor\": \"textfield\"\n    },\n    \"maxResultsPerKeyword\": {\n      \"title\": \"Max results per keyword\",\n      \"type\": \"integer\",\n      \"description\": \"Cap on places emitted per keyword (before filters). First page gives up to 100 places; deeper Naver pages add up to ~300 total per map center, and an area sweep multiplies that per center.\",\n      \"minimum\": 1,\n      \"maximum\": 5000,\n      \"default\": 20,\n      \"prefill\": 20\n    },\n    \"includeDetails\": {\n      \"title\": \"Include place details\",\n      \"type\": \"boolean\",\n      \"description\": \"Fetch each place's detail page for full weekly hours (breaks, last order, upcoming closures), full menus with prices, facilities, parking, photos, review breakdown and more. Slower but much richer data.\",\n      \"default\": true,\n      \"prefill\": true\n    },\n    \"includeReviews\": {\n      \"title\": \"Include visitor reviews\",\n      \"type\": \"boolean\",\n      \"description\": \"Emit real visitor reviews per place as separate `recordType: \\\"review\\\"` records (rating, text, dates, keywords, photos, owner replies). Uses Naver's cursor-paginated review API (50 per request) up to Max reviews per place; falls back to the ~20 reviews embedded on the public review page if that API is unavailable. Works in both modes.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"maxReviewsPerPlace\": {\n      \"title\": \"Max reviews per place\",\n      \"type\": \"integer\",\n      \"description\": \"Cap on review records emitted per place when Include visitor reviews is on. Naver serves 50 reviews per request and does not expose a hard cap, so this can go high (e.g. 500); each 50 reviews costs one extra request.\",\n      \"minimum\": 1,\n      \"maximum\": 3000,\n      \"default\": 10,\n      \"prefill\": 10\n    },\n    \"minVisitorReviewScore\": {\n      \"title\": \"Minimum visitor review score\",\n      \"type\": \"number\",\n      \"description\": \"Only keep places with a visitor review score at or above this value (0-5). Leave blank for no filter.\",\n      \"minimum\": 0,\n      \"maximum\": 5\n    },\n    \"minVisitorReviewCount\": {\n      \"title\": \"Minimum visitor review count\",\n      \"type\": \"integer\",\n      \"description\": \"Only keep places with at least this many visitor reviews. Leave blank for no filter.\",\n      \"minimum\": 0,\n      \"maximum\": 100000000\n    },\n    \"openNow\": {\n      \"title\": \"Open now only\",\n      \"type\": \"boolean\",\n      \"description\": \"Only keep places currently marked as open by Naver Map.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"hasBooking\": {\n      \"title\": \"Has online booking only\",\n      \"type\": \"boolean\",\n      \"description\": \"Only keep places that support online booking/reservations through Naver.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"hasNpay\": {\n      \"title\": \"Accepts Naver Pay only\",\n      \"type\": \"boolean\",\n      \"description\": \"Only keep places that accept Naver Pay.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"hasCoupon\": {\n      \"title\": \"Has coupon only\",\n      \"type\": \"boolean\",\n      \"description\": \"Only keep places with an active coupon or promotion.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"takeout\": {\n      \"title\": \"Offers takeout only\",\n      \"type\": \"boolean\",\n      \"description\": \"Only keep places marked as offering takeout (포장).\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"newlyOpened\": {\n      \"title\": \"Newly opened only\",\n      \"type\": \"boolean\",\n      \"description\": \"Only keep places Naver marks as newly opened.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"wheelchairAccessible\": {\n      \"title\": \"Wheelchair accessible only\",\n      \"type\": \"boolean\",\n      \"description\": \"Only keep places with a wheelchair-accessible entrance.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"maxItems\": {\n      \"title\": \"Max items\",\n      \"type\": \"integer\",\n      \"description\": \"Hard cap on total emitted place records across all keywords/URLs (review records are extra).\",\n      \"minimum\": 1,\n      \"maximum\": 10000,\n      \"default\": 100,\n      \"prefill\": 100\n    },\n    \"monitoringMode\": {\n      \"title\": \"Monitoring mode (only new/changed places)\",\n      \"type\": \"boolean\",\n      \"description\": \"Recurring-job mode: remembers each place between runs (in the Actor's key-value store) and emits only places that are new or whose name, category, address, phone, homepage, weekly hours, menus, or amenities changed. Adds `changeType` (NEW/UPDATED/UNCHANGED) and `changedFields` to each emitted place. Review counts and current open/closed status are ignored so runs are not billed for noise.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"monitoringStateKey\": {\n      \"title\": \"Monitoring state key\",\n      \"type\": \"string\",\n      \"description\": \"Optional name for the monitoring state (mode=monitoringMode). Leave blank to derive the key from the run inputs, so the same keywords/URLs always compare against the same memory.\",\n      \"editor\": \"textfield\"\n    },\n    \"emitUnchanged\": {\n      \"title\": \"Also emit unchanged places\",\n      \"type\": \"boolean\",\n      \"description\": \"In Monitoring mode, also emit places with `changeType: \\\"UNCHANGED\\\"` instead of skipping them.\",\n      \"default\": false,\n      \"prefill\": false\n    }\n  },\n  \"required\": [\n    \"mode\"\n  ]\n}",
    "readme": "# Naver Map Business Listings with Menu & Hours Data\n\nNaver Map is where Koreans actually look up local businesses, and Korean listings carry detail Google rarely has: full weekly schedules with break times and last orders, itemized menus with prices and photos, booking and coupon programs, transit exits, and review breakdowns. This actor reads those public pages and turns them into structured records — by keyword, by map area, or from place links/IDs you already have. No Naver account, no API key, no cookies.\n\n## What this actor does\n\n- **Keyword search** — search any Korean keyword (e.g. `강남 맛집`, `부산 해운대 맛집`), with six Naver sort orders (relevance, popular, TV-featured, most reviewed, most saved, nearest).\n- **Area sweep** — give a center (`37.4979,127.0276`) and a radius, and the actor sweeps a grid of map centers, deduplicating results. This is how you collect well past Naver's ~300-results-per-keyword ceiling.\n- **Deep pagination** — beyond the first 100 results, the actor pages through Naver's own internal search endpoint, up to ~300–400 per keyword/center.\n- **Direct place input** — paste desktop/mobile links, `naver.me` short links, `map.naver.com` entry links, or bare numeric place IDs. One extra lookup by the place's name recovers the search-listing fields (`businessCategory`, `commonAddress`, `dbType`, `categoryCodeList`) that the detail page does not carry.\n- **Full menus** — every menu item Naver lists: name, integer KRW price + original text, description, photo(s), badges, set-menu flag, and its menu section.\n- **Weekly hours** — per-day open/close, break windows, last order, next-day closing flags, upcoming irregular closures, regular days off, and a free-text note.\n- **Filters** — category text, minimum review score/count, open now, booking, Naver Pay, coupon, takeout, newly opened, wheelchair entrance, and menu keyword. Server-side where Naver honors it, always re-checked client-side.\n- **Visitor reviews (optional)** — real reviews as separate records: rating, text, visit date, voted keywords, photos, menu ordered, owner reply. Naver's review API is cursor-paginated (50 reviews per page) and has no hard cap, so `maxReviewsPerPlace` can go into the hundreds; if that API is ever unavailable the actor falls back to the ~20 reviews on the public review page.\n- **Monitoring mode (optional)** — recurring jobs remember each place between runs and emit only new or changed places (`changeType` + `changedFields`), ignoring review-count and open/closed noise.\n- **Empty fields are omitted** — a record only contains fields Naver actually returned for that place.\n\n## Output per place\n\nBusiness basics: `placeId`, `name`, `category`, `businessCategory`, `categoryCodeList`, `dbType`, `roadAddress`, `address`, `commonAddress`, `fullAddress`, `x`, `y`, `distance`, `distanceMeters`, `regionCode`, `placeUrl`, `sourceUrl` (URL mode), `searchKeyword`, `searchRank` (search mode).\n\nContact & links: `phone`, `virtualPhone`, `hasMobilePhoneNumber`, `talktalkUrl`, `chatBotUrl`, `routeUrl`, `homepageUrl`, `websites[]` (all published links with type + primary flag), `relatedLinks[]`.\n\nHours: `businessHoursStatus`, `businessHoursDescription`, `businessHoursEndsNextDay`, `businessHours[]` (day, start, end, `breakHours[]`, `lastOrderTime`, note, endsNextDay), `upcomingClosures[]`, `regularClosures`, `hoursFreeText`.\n\nMenus: `menus[]` (name, `price` integer KRW, `priceText`, `currency`, `priceType`, description, `imageUrl`, `images[]`, `badges[]`, `recommend`, `isSetMenu`, `type`, `menuCategory`), `menuCategories[]`, `menuCount`, `menuUpdatedAt`, `menuImageUrls[]` (photos of the printed menu).\n\nReviews: `visitorReviewCount`, `visitorReviewScore`, `blogCafeReviewCount`, `totalReviewCount`, `saveCount`, `mediaReviewCount`, `reviewStats` (average, total, star distribution, image/author counts), `reviewImageCount`, `reviewAuthorCount`, `reviewThemes[]`, `reviewMenus[]`, `reviewKeywords[]`.\n\nAmenities & programs: `conveniences[]`, `facilities[]`, `keywords[]`, `paymentInfo[]`, `parkingInfo`, `parking` (description/basic/valet), `petFriendly`, `noKidsZone`, `hasBooking`, `bookingUrl`, `bookingBusinessId`, `bookingReviewCount`, `bookingReviewScore`, `naverBookingCategory`, `hasNPay`, `hasCoupon`, `coupons[]`, `couponCount`, `naverOrder` (delivery/table-order/pre-order/pickup flags), `businessToolsUsing[]`, `promotionTitle`, `newOpening`, `hasWheelchairEntrance`, `michelinGuide` + `michelinGuideDetails` (year/star/comment/url/Bib flag), `broadcasts[]` + `tvAppearances[]` (program, channel, menu, date, episode).\n\nMedia & location extras: `imageUrl`, `imageUrls[]`, `imageCount`, `detailPhotos[]`, `visitorImages[]`, `totalImageCount`, `panoramaUrl`, `staticMapUrl`, `subwayStations[]`, `busStations[]`.\n\nPOS (where the business shares it): `posInsights`, `posSalesCount`, `posPopularDay`, `posAveragePrice`, `posPopularMenus[]`. Beauty listings may also carry `representativePrice`.\n\nEvery record ends with `recordType: \"place\"` and `scrapedAt`.\n\nReview records (`recordType: \"review\"`): `placeId`, `sourceUrl`, `reviewId`, `content`, `rating`, `createdDate`, `visitedDate`, `visitCount`, `reviewerName`, `reviewerProfileUrl`, `reviewerReviewCount`, `votedKeywords[]`, `photos[]`, `menuItem`, `replyText`, `replyDate`, `originType`, `language`, `translatedText`, `scrapedAt`.\n\nIn monitoring mode every place record also carries `changeType` (`NEW`/`UPDATED`/`UNCHANGED`) and, for updates, `changedFields` (e.g. `[\"phone\", \"menus\"]`).\n\n## Input\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `mode` | string | `search` | `search` or `byUrls` |\n| `searchKeywords` | array | `[\"강남 맛집\"]` | Keywords (mode=search). Region words narrow results. |\n| `placeUrls` | array | – | Links or bare numeric place IDs (mode=byUrls) |\n| `sortBy` | string | `relevance` | `relevance`, `popular`, `tv`, `reviews`, `saved`, `distance` |\n| `searchCoordinates` | string | – | `\"latitude,longitude\"` map center |\n| `searchRadiusKm` | int | – | With coordinates: area sweep radius (1–20 km) |\n| `category` | string | – | Keep places whose category contains this text |\n| `menuKeyword` | string | – | Keep places whose menus mention this text (needs details) |\n| `maxResultsPerKeyword` | int | `20` | Cap per keyword (1–5000) |\n| `includeDetails` | bool | `true` | Fetch each place's detail page (hours, menus, amenities, photos) |\n| `includeReviews` | bool | `false` | Emit visitor reviews per place (cursor API, 50/request) |\n| `maxReviewsPerPlace` | int | `10` | Review cap per place (1–3000; each 50 costs one request) |\n| `minVisitorReviewScore` | number | – | Keep places at/above this score (0–5) |\n| `minVisitorReviewCount` | int | – | Keep places with at least this many visitor reviews |\n| `openNow` | bool | `false` | Only places currently open |\n| `hasBooking` | bool | `false` | Only places with Naver booking |\n| `hasNpay` | bool | `false` | Only places accepting Naver Pay |\n| `hasCoupon` | bool | `false` | Only places with an active coupon |\n| `takeout` | bool | `false` | Only places offering takeout (포장) |\n| `newlyOpened` | bool | `false` | Only newly opened places |\n| `wheelchairAccessible` | bool | `false` | Only places with a wheelchair-accessible entrance |\n| `maxItems` | int | `100` | Cap on place records (reviews are extra) |\n| `monitoringMode` | bool | `false` | Emit only new/changed places vs the previous run |\n| `monitoringStateKey` | string | – | Optional name for the monitoring memory |\n| `emitUnchanged` | bool | `false` | Also emit `changeType: \"UNCHANGED\"` places |\n\n### Example: neighborhood restaurants with full menus\n\n```json\n{\n  \"mode\": \"search\",\n  \"searchKeywords\": [\"이태원 맛집\"],\n  \"maxResultsPerKeyword\": 30,\n  \"category\": \"한식\",\n  \"minVisitorReviewScore\": 4.3,\n  \"includeDetails\": true\n}\n```\n\n### Example: every cafe within 2 km of Gangnam Station\n\n```json\n{\n  \"mode\": \"search\",\n  \"searchKeywords\": [\"카페\"],\n  \"searchCoordinates\": \"37.4979,127.0276\",\n  \"searchRadiusKm\": 2,\n  \"maxResultsPerKeyword\": 800,\n  \"includeDetails\": false,\n  \"maxItems\": 800\n}\n```\n\n### Example: menu monitoring — who serves pizza in Gangnam\n\n```json\n{\n  \"mode\": \"search\",\n  \"searchKeywords\": [\"강남 맛집\"],\n  \"maxResultsPerKeyword\": 100,\n  \"menuKeyword\": \"피자\",\n  \"includeDetails\": true\n}\n```\n\n### Example: daily monitoring — only new or changed places\n\n```json\n{\n  \"mode\": \"search\",\n  \"searchKeywords\": [\"성수 카페\"],\n  \"maxResultsPerKeyword\": 100,\n  \"monitoringMode\": true,\n  \"monitoringStateKey\": \"seongsu-cafes\"\n}\n```\n\n### Example: known places with reviews\n\n```json\n{\n  \"mode\": \"byUrls\",\n  \"placeUrls\": [\n    \"https://pcmap.place.naver.com/restaurant/2020647783/home\",\n    \"https://naver.me/FqW0LLx9\",\n    \"1254234366\"\n  ],\n  \"includeReviews\": true,\n  \"maxReviewsPerPlace\": 20\n}\n```\n\n## Use cases\n\n- **Restaurant & retail intelligence** — menus with prices, hours with breaks, and amenities across a district, ready for comparison dashboards.\n- **Local SEO & listing audits** — check hours, phone, menus, and review scores for client locations and competitors.\n- **Lead generation** — filter by booking, Naver Pay, coupon, or takeout to build outreach lists for specific business types.\n- **Delivery/ordering analysis** — POS popularity, review menus, and order-program flags show what actually sells.\n- **Travel & guides** — build Korean neighborhood guides with real hours, prices, and transit exits.\n\n## FAQ\n\n**Do I need a Naver account or API key?**\nNo. The actor reads the same public pages a browser loads — no login, cookies, or key.\n\n**Why do some places have no `menus`?**\nNaver only serves menu data for businesses that published one. A clinic or convenience store may have none; the field is simply omitted.\n\n**How many results can one keyword return?**\nNaver's own search exposes up to 100 results on the first page and up to ~300–400 through deeper pages per map center. To collect more, add `searchCoordinates` + `searchRadiusKm` (area sweep) or use narrower keywords.\n\n**How does `sortBy: \"distance\"` work?**\nIt needs `searchCoordinates`; Naver then orders results nearest-first from that point.\n\n**How many reviews does `includeReviews` return?**\nAs many as you ask for, up to the place's total: the actor pages Naver's review API with the same cursor the website uses (50 reviews per page, no hard cap observed). If that API is ever blocked, it falls back to the ~20 reviews embedded on the public review page and says so in the log.\n\n**Are prices numbers or text?**\nBoth: `price` is an integer KRW amount when Naver publishes a fixed price, and `priceText` keeps Naver's original string (useful for \"시가\"/market price, which has no number).\n\n**How does monitoring mode work?**\nTurn on `monitoringMode` and (optionally) name the memory with `monitoringStateKey`. The actor stores a per-place fingerprint in its key-value store and, on later runs with the same key/inputs, emits only `NEW` or `UPDATED` places, listing what changed. Review counts, review scores and current open/closed status are ignored so runs aren't billed for noise. The search itself still runs in full — you pay for the scrape, not per change.\n\n**Is a proxy required?**\nNo. Direct requests work; if Naver starts rate-limiting, the actor automatically retries through an Apify proxy.\n\n**Is this affiliated with Naver?**\nNo. This is an independent third-party actor reading public Naver Map pages. It is not affiliated with or endorsed by Naver Corporation.\n\n## Scope / Limitations\n\n- **~300–400 results per keyword per map center** is Naver's own search ceiling; the area sweep multiplies it per center.\n- **Review depth follows Naver's own cursor API** (50 reviews per page). If Naver ever blocks it, the actor falls back to ~20 reviews per place from the public review page and logs a warning.\n- **Monitoring mode compares stable fields only** (name, category, address, phone, homepage, weekly hours, menus, amenities). Review counts/scores and live open status are deliberately ignored; pass `emitUnchanged` to also emit unchanged places.\n- **Hours are taken from the first published schedule** — 0/44 probed places carried multiple schedule variants.\n- **English translations are not available** — Naver's English name/category/address are not served on any cookieless page; Korean values are kept verbatim.\n- **`includeDetails=false` (fast mode)** returns search-level fields only (name, category, address, coordinates, review counts, hours status, coupons, flags) — menus, full hours, and amenities need details.\n- **Some fields are vertical-specific** — POS insights, menus, or representative prices appear only where Naver publishes them for that business type.\n- **`saveCount`** (how many users bookmarked the place) is only served by Naver's category/region listing pages; in URL mode it is omitted. Other search-listing fields (`businessCategory`, `commonAddress`, `dbType`, `categoryCodeList`) are recovered in URL mode with one extra name lookup.\n- **English name/category/address are not available** — Naver does not serve them on any cookieless page (verified against `lang=en`/`locale=en` variants and the internal APIs), so Korean values are kept verbatim.\n",
    "actorDefinition": {
      "actorSpecification": 1,
      "name": "naver-map-business-listings-with-menu-and-hours",
      "title": "Naver Map Business Listings with Menu & Hours Data",
      "description": "Search Naver Map by keyword or place URL and get address, phone, full weekly hours with breaks, menus with prices and photos, amenities, transit access, booking links, and review analysis for each business.",
      "version": "2.0",
      "buildTag": "latest",
      "dockerfile": "./Dockerfile",
      "readme": "# Naver Map Business Listings with Menu & Hours Data\n\nNaver Map is where Koreans actually look up local businesses, and Korean listings carry detail Google rarely has: full weekly schedules with break times and last orders, itemized menus with prices and photos, booking and coupon programs, transit exits, and review breakdowns. This actor reads those public pages and turns them into structured records — by keyword, by map area, or from place links/IDs you already have. No Naver account, no API key, no cookies.\n\n## What this actor does\n\n- **Keyword search** — search any Korean keyword (e.g. `강남 맛집`, `부산 해운대 맛집`), with six Naver sort orders (relevance, popular, TV-featured, most reviewed, most saved, nearest).\n- **Area sweep** — give a center (`37.4979,127.0276`) and a radius, and the actor sweeps a grid of map centers, deduplicating results. This is how you collect well past Naver's ~300-results-per-keyword ceiling.\n- **Deep pagination** — beyond the first 100 results, the actor pages through Naver's own internal search endpoint, up to ~300–400 per keyword/center.\n- **Direct place input** — paste desktop/mobile links, `naver.me` short links, `map.naver.com` entry links, or bare numeric place IDs. One extra lookup by the place's name recovers the search-listing fields (`businessCategory`, `commonAddress`, `dbType`, `categoryCodeList`) that the detail page does not carry.\n- **Full menus** — every menu item Naver lists: name, integer KRW price + original text, description, photo(s), badges, set-menu flag, and its menu section.\n- **Weekly hours** — per-day open/close, break windows, last order, next-day closing flags, upcoming irregular closures, regular days off, and a free-text note.\n- **Filters** — category text, minimum review score/count, open now, booking, Naver Pay, coupon, takeout, newly opened, wheelchair entrance, and menu keyword. Server-side where Naver honors it, always re-checked client-side.\n- **Visitor reviews (optional)** — real reviews as separate records: rating, text, visit date, voted keywords, photos, menu ordered, owner reply. Naver's review API is cursor-paginated (50 reviews per page) and has no hard cap, so `maxReviewsPerPlace` can go into the hundreds; if that API is ever unavailable the actor falls back to the ~20 reviews on the public review page.\n- **Monitoring mode (optional)** — recurring jobs remember each place between runs and emit only new or changed places (`changeType` + `changedFields`), ignoring review-count and open/closed noise.\n- **Empty fields are omitted** — a record only contains fields Naver actually returned for that place.\n\n## Output per place\n\nBusiness basics: `placeId`, `name`, `category`, `businessCategory`, `categoryCodeList`, `dbType`, `roadAddress`, `address`, `commonAddress`, `fullAddress`, `x`, `y`, `distance`, `distanceMeters`, `regionCode`, `placeUrl`, `sourceUrl` (URL mode), `searchKeyword`, `searchRank` (search mode).\n\nContact & links: `phone`, `virtualPhone`, `hasMobilePhoneNumber`, `talktalkUrl`, `chatBotUrl`, `routeUrl`, `homepageUrl`, `websites[]` (all published links with type + primary flag), `relatedLinks[]`.\n\nHours: `businessHoursStatus`, `businessHoursDescription`, `businessHoursEndsNextDay`, `businessHours[]` (day, start, end, `breakHours[]`, `lastOrderTime`, note, endsNextDay), `upcomingClosures[]`, `regularClosures`, `hoursFreeText`.\n\nMenus: `menus[]` (name, `price` integer KRW, `priceText`, `currency`, `priceType`, description, `imageUrl`, `images[]`, `badges[]`, `recommend`, `isSetMenu`, `type`, `menuCategory`), `menuCategories[]`, `menuCount`, `menuUpdatedAt`, `menuImageUrls[]` (photos of the printed menu).\n\nReviews: `visitorReviewCount`, `visitorReviewScore`, `blogCafeReviewCount`, `totalReviewCount`, `saveCount`, `mediaReviewCount`, `reviewStats` (average, total, star distribution, image/author counts), `reviewImageCount`, `reviewAuthorCount`, `reviewThemes[]`, `reviewMenus[]`, `reviewKeywords[]`.\n\nAmenities & programs: `conveniences[]`, `facilities[]`, `keywords[]`, `paymentInfo[]`, `parkingInfo`, `parking` (description/basic/valet), `petFriendly`, `noKidsZone`, `hasBooking`, `bookingUrl`, `bookingBusinessId`, `bookingReviewCount`, `bookingReviewScore`, `naverBookingCategory`, `hasNPay`, `hasCoupon`, `coupons[]`, `couponCount`, `naverOrder` (delivery/table-order/pre-order/pickup flags), `businessToolsUsing[]`, `promotionTitle`, `newOpening`, `hasWheelchairEntrance`, `michelinGuide` + `michelinGuideDetails` (year/star/comment/url/Bib flag), `broadcasts[]` + `tvAppearances[]` (program, channel, menu, date, episode).\n\nMedia & location extras: `imageUrl`, `imageUrls[]`, `imageCount`, `detailPhotos[]`, `visitorImages[]`, `totalImageCount`, `panoramaUrl`, `staticMapUrl`, `subwayStations[]`, `busStations[]`.\n\nPOS (where the business shares it): `posInsights`, `posSalesCount`, `posPopularDay`, `posAveragePrice`, `posPopularMenus[]`. Beauty listings may also carry `representativePrice`.\n\nEvery record ends with `recordType: \"place\"` and `scrapedAt`.\n\nReview records (`recordType: \"review\"`): `placeId`, `sourceUrl`, `reviewId`, `content`, `rating`, `createdDate`, `visitedDate`, `visitCount`, `reviewerName`, `reviewerProfileUrl`, `reviewerReviewCount`, `votedKeywords[]`, `photos[]`, `menuItem`, `replyText`, `replyDate`, `originType`, `language`, `translatedText`, `scrapedAt`.\n\nIn monitoring mode every place record also carries `changeType` (`NEW`/`UPDATED`/`UNCHANGED`) and, for updates, `changedFields` (e.g. `[\"phone\", \"menus\"]`).\n\n## Input\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `mode` | string | `search` | `search` or `byUrls` |\n| `searchKeywords` | array | `[\"강남 맛집\"]` | Keywords (mode=search). Region words narrow results. |\n| `placeUrls` | array | – | Links or bare numeric place IDs (mode=byUrls) |\n| `sortBy` | string | `relevance` | `relevance`, `popular`, `tv`, `reviews`, `saved`, `distance` |\n| `searchCoordinates` | string | – | `\"latitude,longitude\"` map center |\n| `searchRadiusKm` | int | – | With coordinates: area sweep radius (1–20 km) |\n| `category` | string | – | Keep places whose category contains this text |\n| `menuKeyword` | string | – | Keep places whose menus mention this text (needs details) |\n| `maxResultsPerKeyword` | int | `20` | Cap per keyword (1–5000) |\n| `includeDetails` | bool | `true` | Fetch each place's detail page (hours, menus, amenities, photos) |\n| `includeReviews` | bool | `false` | Emit visitor reviews per place (cursor API, 50/request) |\n| `maxReviewsPerPlace` | int | `10` | Review cap per place (1–3000; each 50 costs one request) |\n| `minVisitorReviewScore` | number | – | Keep places at/above this score (0–5) |\n| `minVisitorReviewCount` | int | – | Keep places with at least this many visitor reviews |\n| `openNow` | bool | `false` | Only places currently open |\n| `hasBooking` | bool | `false` | Only places with Naver booking |\n| `hasNpay` | bool | `false` | Only places accepting Naver Pay |\n| `hasCoupon` | bool | `false` | Only places with an active coupon |\n| `takeout` | bool | `false` | Only places offering takeout (포장) |\n| `newlyOpened` | bool | `false` | Only newly opened places |\n| `wheelchairAccessible` | bool | `false` | Only places with a wheelchair-accessible entrance |\n| `maxItems` | int | `100` | Cap on place records (reviews are extra) |\n| `monitoringMode` | bool | `false` | Emit only new/changed places vs the previous run |\n| `monitoringStateKey` | string | – | Optional name for the monitoring memory |\n| `emitUnchanged` | bool | `false` | Also emit `changeType: \"UNCHANGED\"` places |\n\n### Example: neighborhood restaurants with full menus\n\n```json\n{\n  \"mode\": \"search\",\n  \"searchKeywords\": [\"이태원 맛집\"],\n  \"maxResultsPerKeyword\": 30,\n  \"category\": \"한식\",\n  \"minVisitorReviewScore\": 4.3,\n  \"includeDetails\": true\n}\n```\n\n### Example: every cafe within 2 km of Gangnam Station\n\n```json\n{\n  \"mode\": \"search\",\n  \"searchKeywords\": [\"카페\"],\n  \"searchCoordinates\": \"37.4979,127.0276\",\n  \"searchRadiusKm\": 2,\n  \"maxResultsPerKeyword\": 800,\n  \"includeDetails\": false,\n  \"maxItems\": 800\n}\n```\n\n### Example: menu monitoring — who serves pizza in Gangnam\n\n```json\n{\n  \"mode\": \"search\",\n  \"searchKeywords\": [\"강남 맛집\"],\n  \"maxResultsPerKeyword\": 100,\n  \"menuKeyword\": \"피자\",\n  \"includeDetails\": true\n}\n```\n\n### Example: daily monitoring — only new or changed places\n\n```json\n{\n  \"mode\": \"search\",\n  \"searchKeywords\": [\"성수 카페\"],\n  \"maxResultsPerKeyword\": 100,\n  \"monitoringMode\": true,\n  \"monitoringStateKey\": \"seongsu-cafes\"\n}\n```\n\n### Example: known places with reviews\n\n```json\n{\n  \"mode\": \"byUrls\",\n  \"placeUrls\": [\n    \"https://pcmap.place.naver.com/restaurant/2020647783/home\",\n    \"https://naver.me/FqW0LLx9\",\n    \"1254234366\"\n  ],\n  \"includeReviews\": true,\n  \"maxReviewsPerPlace\": 20\n}\n```\n\n## Use cases\n\n- **Restaurant & retail intelligence** — menus with prices, hours with breaks, and amenities across a district, ready for comparison dashboards.\n- **Local SEO & listing audits** — check hours, phone, menus, and review scores for client locations and competitors.\n- **Lead generation** — filter by booking, Naver Pay, coupon, or takeout to build outreach lists for specific business types.\n- **Delivery/ordering analysis** — POS popularity, review menus, and order-program flags show what actually sells.\n- **Travel & guides** — build Korean neighborhood guides with real hours, prices, and transit exits.\n\n## FAQ\n\n**Do I need a Naver account or API key?**\nNo. The actor reads the same public pages a browser loads — no login, cookies, or key.\n\n**Why do some places have no `menus`?**\nNaver only serves menu data for businesses that published one. A clinic or convenience store may have none; the field is simply omitted.\n\n**How many results can one keyword return?**\nNaver's own search exposes up to 100 results on the first page and up to ~300–400 through deeper pages per map center. To collect more, add `searchCoordinates` + `searchRadiusKm` (area sweep) or use narrower keywords.\n\n**How does `sortBy: \"distance\"` work?**\nIt needs `searchCoordinates`; Naver then orders results nearest-first from that point.\n\n**How many reviews does `includeReviews` return?**\nAs many as you ask for, up to the place's total: the actor pages Naver's review API with the same cursor the website uses (50 reviews per page, no hard cap observed). If that API is ever blocked, it falls back to the ~20 reviews embedded on the public review page and says so in the log.\n\n**Are prices numbers or text?**\nBoth: `price` is an integer KRW amount when Naver publishes a fixed price, and `priceText` keeps Naver's original string (useful for \"시가\"/market price, which has no number).\n\n**How does monitoring mode work?**\nTurn on `monitoringMode` and (optionally) name the memory with `monitoringStateKey`. The actor stores a per-place fingerprint in its key-value store and, on later runs with the same key/inputs, emits only `NEW` or `UPDATED` places, listing what changed. Review counts, review scores and current open/closed status are ignored so runs aren't billed for noise. The search itself still runs in full — you pay for the scrape, not per change.\n\n**Is a proxy required?**\nNo. Direct requests work; if Naver starts rate-limiting, the actor automatically retries through an Apify proxy.\n\n**Is this affiliated with Naver?**\nNo. This is an independent third-party actor reading public Naver Map pages. It is not affiliated with or endorsed by Naver Corporation.\n\n## Scope / Limitations\n\n- **~300–400 results per keyword per map center** is Naver's own search ceiling; the area sweep multiplies it per center.\n- **Review depth follows Naver's own cursor API** (50 reviews per page). If Naver ever blocks it, the actor falls back to ~20 reviews per place from the public review page and logs a warning.\n- **Monitoring mode compares stable fields only** (name, category, address, phone, homepage, weekly hours, menus, amenities). Review counts/scores and live open status are deliberately ignored; pass `emitUnchanged` to also emit unchanged places.\n- **Hours are taken from the first published schedule** — 0/44 probed places carried multiple schedule variants.\n- **English translations are not available** — Naver's English name/category/address are not served on any cookieless page; Korean values are kept verbatim.\n- **`includeDetails=false` (fast mode)** returns search-level fields only (name, category, address, coordinates, review counts, hours status, coupons, flags) — menus, full hours, and amenities need details.\n- **Some fields are vertical-specific** — POS insights, menus, or representative prices appear only where Naver publishes them for that business type.\n- **`saveCount`** (how many users bookmarked the place) is only served by Naver's category/region listing pages; in URL mode it is omitted. Other search-listing fields (`businessCategory`, `commonAddress`, `dbType`, `categoryCodeList`) are recovered in URL mode with one extra name lookup.\n- **English name/category/address are not available** — Naver does not serve them on any cookieless page (verified against `lang=en`/`locale=en` variants and the internal APIs), so Korean values are kept verbatim.\n",
      "input": {
        "title": "Naver Map Scraper Input",
        "description": "Search Naver Map by keyword (optionally around a map area) or fetch specific places by URL/ID. Get business details, full menus with prices, weekly hours with breaks, photos, and visitor reviews.",
        "type": "object",
        "schemaVersion": 1,
        "properties": {
          "mode": {
            "title": "Mode",
            "type": "string",
            "description": "What to fetch. `search` discovers places by keyword; `byUrls` fetches places you already know (URLs or place IDs).",
            "editor": "select",
            "enum": [
              "search",
              "byUrls"
            ],
            "enumTitles": [
              "Search places by keyword",
              "Fetch specific places by URL or ID"
            ],
            "default": "search",
            "prefill": "search"
          },
          "searchKeywords": {
            "title": "Search keywords (mode=search)",
            "type": "array",
            "description": "Keywords to search on Naver Map, e.g. `강남 맛집` (Gangnam restaurants) or `이태원 카페` (Itaewon cafes). Include a region name for local results. Naver returns up to 100 places per keyword from the first page and up to ~300 via deeper pages; add a map area (Search coordinates + Radius) or narrower keywords for more.",
            "editor": "stringList",
            "default": [
              "강남 맛집"
            ],
            "prefill": [
              "강남 맛집"
            ]
          },
          "placeUrls": {
            "title": "Place URLs or IDs (mode=byUrls)",
            "type": "array",
            "description": "Naver Map places to fetch directly. Accepts full links (pcmap.place.naver.com, m.place.naver.com, map.naver.com/p/entry/place/...), `naver.me` short links, and bare numeric place IDs.",
            "editor": "stringList",
            "default": [],
            "prefill": []
          },
          "sortBy": {
            "title": "Sort order (mode=search)",
            "type": "string",
            "description": "How Naver orders search results. `distance` sorting needs Search coordinates.",
            "editor": "select",
            "enum": [
              "relevance",
              "popular",
              "tv",
              "reviews",
              "saved",
              "distance"
            ],
            "enumTitles": [
              "Relevance (Naver default)",
              "Popular (인기순)",
              "TV featured first (방영순)",
              "Most reviewed first",
              "Most saved/bookmarked first",
              "Nearest first (needs coordinates)"
            ],
            "default": "relevance",
            "prefill": "relevance"
          },
          "searchCoordinates": {
            "title": "Search coordinates (mode=search)",
            "type": "string",
            "description": "Map center as `latitude,longitude`, e.g. `37.4979,127.0276` for Gangnam Station. Used to rank results around a point, for distance sorting, and as the center of an area sweep.",
            "editor": "textfield"
          },
          "searchRadiusKm": {
            "title": "Area radius in km (mode=search)",
            "type": "integer",
            "description": "When set together with Search coordinates, the actor sweeps the whole circle (grid of map centers) instead of one center — this is how to collect more than Naver's ~300-per-keyword limit. Needs a broad keyword (e.g. `맛집`).",
            "minimum": 1,
            "maximum": 20
          },
          "category": {
            "title": "Category filter",
            "type": "string",
            "description": "Only keep places whose category contains this text (e.g. `한식`, `카페`, `Cafe`). Leave blank for all categories.",
            "editor": "textfield"
          },
          "menuKeyword": {
            "title": "Menu keyword filter",
            "type": "string",
            "description": "Only keep places whose menu names or descriptions contain this text (e.g. `피자`). Requires Include place details to be on. Leave blank for all menus.",
            "editor": "textfield"
          },
          "maxResultsPerKeyword": {
            "title": "Max results per keyword",
            "type": "integer",
            "description": "Cap on places emitted per keyword (before filters). First page gives up to 100 places; deeper Naver pages add up to ~300 total per map center, and an area sweep multiplies that per center.",
            "minimum": 1,
            "maximum": 5000,
            "default": 20,
            "prefill": 20
          },
          "includeDetails": {
            "title": "Include place details",
            "type": "boolean",
            "description": "Fetch each place's detail page for full weekly hours (breaks, last order, upcoming closures), full menus with prices, facilities, parking, photos, review breakdown and more. Slower but much richer data.",
            "default": true,
            "prefill": true
          },
          "includeReviews": {
            "title": "Include visitor reviews",
            "type": "boolean",
            "description": "Emit real visitor reviews per place as separate `recordType: \"review\"` records (rating, text, dates, keywords, photos, owner replies). Uses Naver's cursor-paginated review API (50 per request) up to Max reviews per place; falls back to the ~20 reviews embedded on the public review page if that API is unavailable. Works in both modes.",
            "default": false,
            "prefill": false
          },
          "maxReviewsPerPlace": {
            "title": "Max reviews per place",
            "type": "integer",
            "description": "Cap on review records emitted per place when Include visitor reviews is on. Naver serves 50 reviews per request and does not expose a hard cap, so this can go high (e.g. 500); each 50 reviews costs one extra request.",
            "minimum": 1,
            "maximum": 3000,
            "default": 10,
            "prefill": 10
          },
          "minVisitorReviewScore": {
            "title": "Minimum visitor review score",
            "type": "number",
            "description": "Only keep places with a visitor review score at or above this value (0-5). Leave blank for no filter.",
            "minimum": 0,
            "maximum": 5
          },
          "minVisitorReviewCount": {
            "title": "Minimum visitor review count",
            "type": "integer",
            "description": "Only keep places with at least this many visitor reviews. Leave blank for no filter.",
            "minimum": 0,
            "maximum": 100000000
          },
          "openNow": {
            "title": "Open now only",
            "type": "boolean",
            "description": "Only keep places currently marked as open by Naver Map.",
            "default": false,
            "prefill": false
          },
          "hasBooking": {
            "title": "Has online booking only",
            "type": "boolean",
            "description": "Only keep places that support online booking/reservations through Naver.",
            "default": false,
            "prefill": false
          },
          "hasNpay": {
            "title": "Accepts Naver Pay only",
            "type": "boolean",
            "description": "Only keep places that accept Naver Pay.",
            "default": false,
            "prefill": false
          },
          "hasCoupon": {
            "title": "Has coupon only",
            "type": "boolean",
            "description": "Only keep places with an active coupon or promotion.",
            "default": false,
            "prefill": false
          },
          "takeout": {
            "title": "Offers takeout only",
            "type": "boolean",
            "description": "Only keep places marked as offering takeout (포장).",
            "default": false,
            "prefill": false
          },
          "newlyOpened": {
            "title": "Newly opened only",
            "type": "boolean",
            "description": "Only keep places Naver marks as newly opened.",
            "default": false,
            "prefill": false
          },
          "wheelchairAccessible": {
            "title": "Wheelchair accessible only",
            "type": "boolean",
            "description": "Only keep places with a wheelchair-accessible entrance.",
            "default": false,
            "prefill": false
          },
          "maxItems": {
            "title": "Max items",
            "type": "integer",
            "description": "Hard cap on total emitted place records across all keywords/URLs (review records are extra).",
            "minimum": 1,
            "maximum": 10000,
            "default": 100,
            "prefill": 100
          },
          "monitoringMode": {
            "title": "Monitoring mode (only new/changed places)",
            "type": "boolean",
            "description": "Recurring-job mode: remembers each place between runs (in the Actor's key-value store) and emits only places that are new or whose name, category, address, phone, homepage, weekly hours, menus, or amenities changed. Adds `changeType` (NEW/UPDATED/UNCHANGED) and `changedFields` to each emitted place. Review counts and current open/closed status are ignored so runs are not billed for noise.",
            "default": false,
            "prefill": false
          },
          "monitoringStateKey": {
            "title": "Monitoring state key",
            "type": "string",
            "description": "Optional name for the monitoring state (mode=monitoringMode). Leave blank to derive the key from the run inputs, so the same keywords/URLs always compare against the same memory.",
            "editor": "textfield"
          },
          "emitUnchanged": {
            "title": "Also emit unchanged places",
            "type": "boolean",
            "description": "In Monitoring mode, also emit places with `changeType: \"UNCHANGED\"` instead of skipping them.",
            "default": false,
            "prefill": false
          }
        },
        "required": [
          "mode"
        ]
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "Naver Map Business Listings with Menu & Hours Data Output",
        "description": "Naver Map business records with full menus and prices, weekly hours with breaks and closures, address, phone, amenities, transit, booking, Michelin/TV mentions, and review analysis (plus optional visitor-review records).",
        "properties": {
          "places": {
            "type": "string",
            "title": "Naver Map places",
            "description": "Dataset containing all scraped Naver Map places and (optionally) their visitor reviews.",
            "template": "{{links.apiDefaultDatasetUrl}}/items"
          }
        }
      },
      "storages": {
        "dataset": {
          "actorSpecification": 1,
          "views": {
            "overview": {
              "title": "Places",
              "transformation": {
                "fields": [
                  "name",
                  "category",
                  "roadAddress",
                  "businessHoursStatus",
                  "phone",
                  "visitorReviewScore",
                  "visitorReviewCount",
                  "placeUrl"
                ]
              },
              "display": {
                "component": "table",
                "properties": {}
              }
            }
          }
        }
      },
      "environmentVariables": {}
    },
    "buildNumber": "2.0.1",
    "imageDigest": "af1173144aa26eb2fc4d01ecd93b40a2b9faed282bcb58e1cb41554a2e747981",
    "actVersion": {
      "sourceType": "SOURCE_FILES",
      "buildTag": "latest",
      "versionNumber": "2.0"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.017984444444444445
    }
  }
}