# Kakao Map Scraper (`huggable_quote/kakao-map-scraper`) Actor

Extract Kakao Map place listings via official map JSON endpoints; optional Kakao Local API search and place-api reviews with proxy.

- **URL**: https://apify.com/huggable\_quote/kakao-map-scraper.md
- **Developed by:** [OrbitData Labs](https://apify.com/huggable_quote) (community)
- **Categories:** Travel, Lead generation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

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

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

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

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

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

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

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

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

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

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


# README

## Kakao Map Scraper

Extract place details, reviews, photos, and contact information from **Kakao Map** — South Korea's most popular mapping service alongside Naver Map.

Search by keywords or provide direct place URLs to collect structured JSON data from Kakao Map listings.

> **Need Naver Map data too?** Use both scrapers together for complete coverage of South Korean local business data.

---

### Features

- **Keyword Search** — Bulk-collect places by keywords like "강남 맛집" (Gangnam restaurants) or "홍대 카페" (Hongdae cafés)
- **Direct URL Input** — Provide `https://place.map.kakao.com/{placeId}` URLs for targeted scraping
- **Place Details** — Name, category, address (legacy & road), phone, website, coordinates
- **Ratings & Review Stats** — Average rating, total review count, blog review count
- **Review Collection** (optional) — Review text, rating, author, date, photo URLs
- **Photo Collection** (optional) — Featured photo URLs from the place listing
- **Keyword & Facility Tags** — Extracted from search metadata (parking, WiFi, delivery, etc.)
- **Anti-blocking** — User-Agent rotation, request jitter, Apify Proxy support

---

### Input Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchKeywords` | string[] | `["강남 맛집"]` | List of search keywords |
| `startUrls` | object[] | — | Direct Kakao Map place URLs |
| `maxResultsPerKeyword` | integer | `5` | Max places to collect per keyword (1–10,000) |
| `includeReviews` | boolean | `false` | Whether to collect reviews (adds $0.001/page) |
| `maxReviewPages` | integer | `50` | Max review pages per place (~10–20 reviews/page, 0 = unlimited) |
| `includePhotos` | boolean | `false` | Include featured photo URLs |
| `searchLocation` | object | — | Search center coordinates `{ latitude, longitude }` (with API key only) |
| `searchRadius` | integer | `5000` | Search radius in meters (100–20,000) |
| `kakaoRestApiKey` | string | — | Kakao REST API key (optional, falls back to web search) |
| `proxyConfiguration` | object | `{useApifyProxy: true}` | Proxy settings |

> At least one of `searchKeywords` or `startUrls` is required.

---

### Output Data

#### Successful result

```json
{
    "placeId": "26338954",
    "placeName": "Starbucks Gangnam-daero",
    "category": "Restaurant > Cafe > Coffee Shop",
    "address": "1305-7 Seocho-dong, Seocho-gu, Seoul",
    "roadAddress": "399 Gangnam-daero, Seocho-gu, Seoul",
    "phone": "1522-3232",
    "website": "https://www.starbucks.co.kr",
    "latitude": 37.4967,
    "longitude": 127.0276,
    "placeUrl": "https://place.map.kakao.com/26338954",
    "rating": 3.8,
    "reviewCount": 152,
    "blogReviewCount": 87,
    "openingHours": null,
    "openNow": null,
    "facilities": ["Parking", "WiFi"],
    "keywords": ["Coffee", "Dessert"],
    "menu": null,
    "photos": ["https://img1.kakaocdn.net/..."],
    "reviews": [
        {
            "reviewText": "Great coffee!",
            "rating": 5,
            "reviewerName": "KakaoUser",
            "reviewDate": "2025-03-15",
            "photos": []
        }
    ],
    "scrapedAt": "2025-06-01T12:00:00.000Z"
}
````

#### Failed result

```json
{
    "placeId": "12345678",
    "error": "Failed to fetch detail"
}
```

***

### Pricing

This Actor uses a **Pay-Per-Event (PPE)** pricing model. No subscriptions — you only pay for what you use.

| Event | Price | Per 1,000 |
|-------|-------|-----------|
| `place-scraped` | $0.003 | $3.00 |
| `review-page` | $0.001 | $1.00 |

#### Cost Examples

| Scenario | Estimated Cost |
|----------|----------------|
| 100 places (no reviews) | ~$0.30 |
| 1,000 places (no reviews) | ~$3.00 |
| 100 places + reviews (avg 5 pages/place) | ~$0.80 |
| 1,000 places + reviews (avg 5 pages/place) | ~$8.00 |

With Apify's free tier ($5/month credit), you can scrape approximately **1,600 places**.

***

### Usage Tips

#### Kakao REST API Key (Optional)

For better keyword search quality and speed, get a REST API key from [Kakao Developers](https://developers.kakao.com/) and enter it in the input. The scraper works without a key by falling back to the web search endpoint.

#### Proxy Settings

Apify Proxy (`useApifyProxy: true`) is enabled by default. Using a proxy is strongly recommended, especially for review collection.

#### Review Collection

Reviews are collected using a real Chromium browser (Playwright). The Actor navigates to the Kakao Map place page, clicks the review tab, and extracts review data directly from the rendered DOM. This bypasses the anti-bot protections on `place-api.map.kakao.com` that block all HTTP-based approaches.

When `includeReviews` is enabled, the Actor:

1. Launches a headless Chromium browser for each place
2. Navigates to the place page and waits for full render
3. Clicks the review tab and loads additional pages via "more" button
4. Extracts review text, rating, author, date, and photos from the DOM

> **Note:** Review collection uses more memory and compute time than place-only scraping. Apify allocates sufficient memory automatically.

***

### Local Development

```bash
cd kakao-map-scraper
npm install
echo '{"searchKeywords":["강남 맛집"],"maxResultsPerKeyword":3}' > INPUT.json
APIFY_TOKEN=your_token npm run start:dev
```

***

### Limitations

- **Business hours** — Not available from the public API; returned as `null`
- **Menu** — Not available from the public API; returned as `null` (planned for future update)
- **Reviews** — Requires headless browser (Playwright); slower than HTTP-only scraping but reliable

***

### Changelog

#### v1.0

- Initial public release
- PPE pricing model (`place-scraped`, `review-page`)
- Keyword search (Kakao Local API / web mapsearch fallback)
- Place details, reviews, and photo collection
- Spending limit / review charge limit support
- Error rows on individual place failures (no full run abort)

# Actor input Schema

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

검색 키워드 목록. 예: \['강남 맛집', '홍대 카페']. API 키가 없으면 mapsearch 웹 엔드포인트를 사용합니다.

## `startUrls` (type: `array`):

카카오맵 장소 URL. 예: https://place.map.kakao.com/26338954

## `maxResultsPerKeyword` (type: `integer`):

키워드당 최대 수집 장소 수 (1 ~ 10,000)

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

Collect reviews using headless browser (Playwright). Adds ~$0.001 per review page loaded.

## `maxReviewPages` (type: `integer`):

장소당 최대 리뷰 페이지 수 (1페이지 ≈ 10~20개 리뷰). 0 = 전체 수집

## `includePhotos` (type: `boolean`):

공개 장소 API에 포함된 추천 사진 URL 포함

## `searchLocation` (type: `object`):

dapi 키워드 검색 시에만 사용: 중심 위경도

## `searchRadius` (type: `integer`):

dapi 검색 반경 (미터)

## `kakaoRestApiKey` (type: `string`):

KakaoAK 로컬 검색용. 비우면 웹 mapsearch 로 폴백합니다. 환경변수 KAKAO\_REST\_API\_KEY 도 지원합니다.

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

Apify 프록시 설정. 리뷰·검색에서 차단을 줄여 줍니다.

## Actor input object example

```json
{
  "searchKeywords": [
    "강남 맛집"
  ],
  "startUrls": [
    {
      "url": "https://place.map.kakao.com/26338954"
    }
  ],
  "maxResultsPerKeyword": 5,
  "includeReviews": false,
  "maxReviewPages": 50,
  "includePhotos": false,
  "searchRadius": 5000,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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 = {
    "searchKeywords": [
        "강남 맛집"
    ],
    "startUrls": [
        {
            "url": "https://place.map.kakao.com/26338954"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("huggable_quote/kakao-map-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 = {
    "searchKeywords": ["강남 맛집"],
    "startUrls": [{ "url": "https://place.map.kakao.com/26338954" }],
}

# Run the Actor and wait for it to finish
run = client.actor("huggable_quote/kakao-map-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "searchKeywords": [
    "강남 맛집"
  ],
  "startUrls": [
    {
      "url": "https://place.map.kakao.com/26338954"
    }
  ]
}' |
apify call huggable_quote/kakao-map-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Kakao Map Scraper",
        "description": "Extract Kakao Map place listings via official map JSON endpoints; optional Kakao Local API search and place-api reviews with proxy.",
        "version": "1.0",
        "x-build-id": "5nTsAUA97ZQvZDRzS"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/huggable_quote~kakao-map-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-huggable_quote-kakao-map-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/huggable_quote~kakao-map-scraper/runs": {
            "post": {
                "operationId": "runs-sync-huggable_quote-kakao-map-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/huggable_quote~kakao-map-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-huggable_quote-kakao-map-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "searchKeywords": {
                        "title": "Search Keywords",
                        "type": "array",
                        "description": "검색 키워드 목록. 예: ['강남 맛집', '홍대 카페']. API 키가 없으면 mapsearch 웹 엔드포인트를 사용합니다.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "startUrls": {
                        "title": "Place URLs",
                        "type": "array",
                        "description": "카카오맵 장소 URL. 예: https://place.map.kakao.com/26338954",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "maxResultsPerKeyword": {
                        "title": "Max results per keyword",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "키워드당 최대 수집 장소 수 (1 ~ 10,000)",
                        "default": 5
                    },
                    "includeReviews": {
                        "title": "Include reviews",
                        "type": "boolean",
                        "description": "Collect reviews using headless browser (Playwright). Adds ~$0.001 per review page loaded.",
                        "default": false
                    },
                    "maxReviewPages": {
                        "title": "Max review pages per place",
                        "minimum": 0,
                        "maximum": 500,
                        "type": "integer",
                        "description": "장소당 최대 리뷰 페이지 수 (1페이지 ≈ 10~20개 리뷰). 0 = 전체 수집",
                        "default": 50
                    },
                    "includePhotos": {
                        "title": "Include photos",
                        "type": "boolean",
                        "description": "공개 장소 API에 포함된 추천 사진 URL 포함",
                        "default": false
                    },
                    "searchLocation": {
                        "title": "Search center location",
                        "type": "object",
                        "description": "dapi 키워드 검색 시에만 사용: 중심 위경도",
                        "properties": {
                            "latitude": {
                                "title": "Latitude",
                                "type": "number",
                                "description": "검색 중심 위도 (WGS84)"
                            },
                            "longitude": {
                                "title": "Longitude",
                                "type": "number",
                                "description": "검색 중심 경도 (WGS84)"
                            }
                        }
                    },
                    "searchRadius": {
                        "title": "Search radius (meters)",
                        "minimum": 100,
                        "maximum": 20000,
                        "type": "integer",
                        "description": "dapi 검색 반경 (미터)",
                        "default": 5000
                    },
                    "kakaoRestApiKey": {
                        "title": "Kakao REST API key (optional)",
                        "type": "string",
                        "description": "KakaoAK 로컬 검색용. 비우면 웹 mapsearch 로 폴백합니다. 환경변수 KAKAO_REST_API_KEY 도 지원합니다."
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Apify 프록시 설정. 리뷰·검색에서 차단을 줄여 줍니다.",
                        "default": {
                            "useApifyProxy": true
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
