# Kakao Map (카카오맵) Place & Review Scraper - Korea Local Data (`lanternlab318/kakao-map`) Actor

Search Kakao Map by Korean keyword or place link: name, category, road address, business phone, WGS84 lat/lng, rating, review count and URL, plus public reviews with rating, text and date. No login or cookies. Deduplicated per run; cut-short work is marked partial, never shown as empty.

- **URL**: https://apify.com/lanternlab318/kakao-map.md
- **Developed by:** [Lantern Lab](https://apify.com/lanternlab318) (community)
- **Categories:** Lead generation, Travel, Business
- **Security:** Limited permissions
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.79 / 1,000 place or review rows

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Kakao Map (카카오맵) Place & Review Scraper

A Lantern Lab Actor for Korean local data. Search Kakao Map by keyword — `강남 카페`, `부산 해운대 호텔` — or paste place links, and get the public place record back: place id, name, category, display / road-name / lot-number address, the business phone shown on the page, WGS84 coordinates, the Kakao Map star rating and review count, and the place page URL. With reviews on, every place also brings its public Kakao Map reviews: rating, text and publish time. No Kakao login, no cookies, no account of your own.

**Price: USD 0.79 per 1,000 rows. No run-start fee.** One price per row, the same for a place row and a review row. Status rows, empty results and the run summary are free.

### What it does

- Searches each term separately and labels every row with the term that produced it, so one run can cover many keywords and regions.
- Takes place links as well: `https://place.map.kakao.com/15376650`, `https://map.kakao.com/?itemId=15376650`, or the bare place id. Links and keywords can be mixed in one run.
- Returns WGS84 `lat` / `lng` and the road-name address, which the Kakao Map search list does not carry — each place is read from the place page's own data.
- Collects the public Kakao Map reviews per place, newest first, paged to the limit you set.
- Deduplicates across the whole run: a place or a review reached by two of your keywords is written once and charged once.
- Keeps the source identifier (`placeId`, `reviewId`), the parent relation (`placeId` on every review), the platform's own time (`publishedAt`, plus `publishedAtRaw` exactly as Kakao sent it) and our collection time (`collectedAt`) as separate fields.
- Says what happened per keyword and per place. A keyword Kakao Map answered with nothing is recorded as an empty result; anything cut short by a limit, a refusal or a dead link is marked `partial: true` with the reason. The two are different records and are never confused.
- Writes `null`, never a guess, for a field Kakao Map did not provide. A place with no review yet has `rating: null` and `reviewCount: null`, not `0`.
- Caps itself: `maxUpstreamRequests` is a hard ceiling on requests to Kakao Map for the whole run, derived from your input when you leave it empty, so a run is never unbounded.

### What it does not do

- No login-only, private or age-restricted data; public place pages only.
- No reviewer identity: a review's nickname, profile image and account id are not collected.
- No blog reviews, photos, menus, opening hours or visitor-footfall charts — `blogReviewCount` is reported, the blog posts themselves are not collected.
- No Naver Map, Google Maps or other map platform.
- No scheduling or monitoring built in; use Apify schedules.

### Input

| Field | Default | Meaning |
| --- | --- | --- |
| `searchQueries` | — | One Kakao Map search term per line, as you would type it on the Korean map. Korean terms return the most places. |
| `placeUrls` | — | Kakao Map place links or bare place ids, one per line. At least one of `searchQueries` / `placeUrls` is required. |
| `maxPlacesPerQuery` | `20` | Upper bound on places per search term. Kakao Map serves 15 per result page. |
| `includeReviews` | `true` | Also collect each place's public Kakao Map reviews as separate rows. |
| `maxReviewsPerPlace` | `20` | Upper bound on reviews per place, newest first. Kakao Map serves 20 per page. `0` collects none. |
| `maxUpstreamRequests` | derived | Hard ceiling on requests to Kakao Map for the whole run. Leave empty and the Actor works one out from your input. |
| `proxyConfiguration` | Apify Proxy | The proxy the requests go through. The datacenter default is what this Actor is measured on. |

```json
{
  "searchQueries": ["강남 카페", "부산 해운대 호텔"],
  "placeUrls": ["https://place.map.kakao.com/15376650"],
  "maxPlacesPerQuery": 20,
  "includeReviews": true,
  "maxReviewsPerPlace": 20
}
```

### Output

Four row kinds, told apart by `recordType`. `place` and `review` rows are charged; `query_status`, `place_status` and the final `RUN_SUMMARY` are free.

A `place` row:

```json
{
  "recordType": "place",
  "placeId": "15376650",
  "name": "스타벅스 본사",
  "url": "https://place.map.kakao.com/15376650",
  "category": "기업",
  "categoryGroup": "서비스,산업",
  "address": "서울 강남구 테헤란로 231 센터필드 EAST 20-22층 (역삼동)",
  "roadAddress": "서울 강남구 테헤란로 231 센터필드 EAST 20-22층",
  "jibunAddress": "역삼동 676",
  "postalCode": "06142",
  "phone": "1522-3232",
  "lat": 37.50365329924952,
  "lng": 127.04146067429498,
  "rating": 1.8,
  "reviewCount": 126,
  "blogReviewCount": 87,
  "homepageUrl": "https://www.istarbucks.co.kr",
  "source": "search",
  "query": "강남 카페",
  "rank": 1,
  "partial": false,
  "partialReason": null,
  "collectedAt": "2026-10-24T00:00:00.000Z"
}
```

A `review` row:

```json
{
  "recordType": "review",
  "reviewId": "15680924",
  "placeId": "15376650",
  "placeName": "스타벅스 본사",
  "placeUrl": "https://place.map.kakao.com/15376650",
  "rating": 5,
  "text": "…",
  "photoCount": 0,
  "likeCount": 6,
  "publishedAt": "2026-06-08T13:17:25.000Z",
  "publishedAtRaw": "2026-06-08 22:17:25",
  "partial": false,
  "partialReason": null,
  "collectedAt": "2026-10-24T00:00:00.000Z"
}
```

A free status row, for a search term that Kakao Map answered with nothing:

```json
{
  "recordType": "query_status",
  "query": "없는가게999",
  "placesReturned": 0,
  "placesAvailable": 0,
  "searchEndReached": true,
  "partial": false,
  "partialReason": null,
  "statusText": "Kakao Map returned no place for this search term. This is an empty result, not a failed one."
}
```

`partialReason` is one of `upstream_request_cap`, `charge_limit_reached`, `blocked`, `upstream_error`, `place_not_found` or `not_collected`.

### Limits

- Kakao Map serves **15 places per search page** and **20 reviews per page**. `maxPlacesPerQuery` and `maxReviewsPerPlace` are rounded up to whole pages' worth of requests.
- A keyword's result list is as deep as Kakao Map makes it. A term whose list ends sooner than your limit returns fewer places and reports `searchEndReached: true`.
- Reviews are the Kakao Map reviews of the place, newest first. Blog reviews are counted but not collected.
- `rating` and `reviewCount` are null for a place with no Kakao Map review yet.
- Kakao Map times are Korean standard time (UTC+9). `publishedAt` is the UTC instant; `publishedAtRaw` is Kakao's own string.
- `phone` is the business number published on the place page. Places with no published number have `phone: null`.
- Korean-language keywords return far more places than Latin-script ones for the same business.
- A dead or removed place link is reported on a free `place_status` row with `partialReason: place_not_found`; it is never reported as a place with empty fields.

# Actor input Schema

## `searchQueries` (type: `array`):

One Kakao Map search term per line, the way you would type it into the Korean map: "강남 카페", "부산 해운대 호텔", "제주 흑돼지". A term that names a region first ("서울 치과") searches that region. Korean terms return by far the most places, but a brand written in Latin letters also works. Every term is searched separately and its results are labelled with it; a place that matches several of your terms is returned once and charged once.

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

Kakao Map place links or bare place ids, one per line - for example https://place.map.kakao.com/15376650, https://map.kakao.com/?itemId=15376650, or just 15376650. Use this when you already know the places you want. Links and search terms can be used together in one run. A link with no place id in it stops the run before anything is spent, and a link Kakao Map says does not exist is reported on its own free status row.

## `maxPlacesPerQuery` (type: `integer`):

Upper bound on the places one search term may produce. Kakao Map serves 15 places per result page, so this is rounded up to whole pages' worth of requests. A term whose own result list ends sooner returns fewer and says so, which is not the same as being cut short by this limit.

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

With this on, every place also gets its public Kakao Map reviews as separate rows: rating, text, photo and like counts, and the publish time. Only what the review itself shows publicly is collected - the reviewer's nickname, profile and account id are not. Turn it off for a places-only run, which is one request per place.

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

Upper bound on the reviews one place may produce, newest first. Kakao Map serves 20 reviews per page, so each 20 here is one more request per place. 0 collects no review, the same as turning reviews off. A place with fewer reviews than this returns all of them; one cut short by this limit, by a request ceiling or by a refusal says so on its status row, with the total Kakao Map reports for the place.

## `maxUpstreamRequests` (type: `integer`):

Hard ceiling on the HTTP requests this run sends to Kakao Map: search pages, place details, review pages and retries together. At the ceiling collection stops - the search terms and places not reached are written with partialReason "upstream_request_cap" and the run then ends normally. Leave empty and the Actor works a ceiling out from your search terms, links and limits, so a run is never unbounded.

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

The proxy the requests to Kakao Map go through. The default (Apify Proxy, datacenter) is the cheapest and is what this Actor is measured on; Kakao Map serves these public endpoints over it without blocking. Switch to residential with a Korean exit only if you see refusals.

## Actor input object example

```json
{
  "searchQueries": [
    "강남 카페"
  ],
  "maxPlacesPerQuery": 20,
  "includeReviews": true,
  "maxReviewsPerPlace": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `runSummary` (type: `string`):

No description

# 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 = {
    "searchQueries": [
        "강남 카페"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lanternlab318/kakao-map").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 = { "searchQueries": ["강남 카페"] }

# Run the Actor and wait for it to finish
run = client.actor("lanternlab318/kakao-map").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 '{
  "searchQueries": [
    "강남 카페"
  ]
}' |
apify call lanternlab318/kakao-map --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lanternlab318/kakao-map"
        }
    }
}
```

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/1CahvWqbFbToeWPhy/builds/tUAlYWLM8aBtagqQO/openapi.json
