# Zigbang Scraper: Korean Rentals, Jeonse, Sales & Agents (`oswaldocarabano/zigbang-scraper`) Actor

Scrape Zigbang (직방), South Korea's rental app: one-room, villa and officetel listings for monthly rent, jeonse and sale in Seoul, Busan, Gyeonggi and all of Korea, with KRW prices, area, floor, GPS, address, photos, subway access and the licensed agent's contacts. No login.

- **URL**: https://apify.com/oswaldocarabano/zigbang-scraper.md
- **Developed by:** [Oswaldo Carabano](https://apify.com/oswaldocarabano) (community)
- **Categories:** Real estate, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.90 / 1,000 listings

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

## Zigbang Scraper: Korean rentals, jeonse, sales and agents

Export property listings from **Zigbang (직방)**, South Korea's rental listings app, as clean JSON, CSV or Excel: one-room studios (원룸), villas (빌라) and officetels (오피스텔) for **monthly rent (월세)**, **jeonse (전세)** and **sale (매매)**, searched by place name or by coordinates anywhere in Korea: Seoul, Busan, Gyeonggi-do, Incheon, Daegu, Daejeon and every other city on Zigbang.

A Zigbang data API without an API key: every row comes with the price already converted to **KRW** (and in 만원, the way Koreans read it), area in m² and pyeong, floor, map coordinates, full address down to the lot number, registration date and the listing agent's id. Turn on **detail pages** and each listing also carries the full description, every photo, furnishing options, bathrooms, orientation, parking, elevator, building approval date, the **parcel number (PNU)**, nearby subway stations, walking time to amenities, the apartment or officetel complex, and the **licensed agent's office, phones, email and broker registration number**.

- **120 fields per listing.** A typical listing fills **36** data fields from the search results alone, and **87** with the detail page.
- **A second row type: licensed agents (공인중개사).** One row per real-estate agent publishing in your area, ranked by how many listings they have there, with contacts, registration numbers, listing counts by type and deal, response rates and languages.
- **Search the way Koreans do**: `마포구`, `역삼동`, `강남역`, or English names such as `Seoul`, `Busan`, `Gyeonggi`, `Gangnam-gu`, `Mapo-gu`, `Hongdae`, `Haeundae`, `Jamsil`. Or give latitude, longitude and a radius.
- **Clean, typed data**: Korean labels become stable English keys (`monthly_rent`, `open_studio`, `air_conditioner`, `near_subway`) and the original Korean text is kept next to them in `*_raw`.
- **No login, no cookies, no browser.** Public listing data only. The default run delivers 100 listings in about 10 seconds; 1,000 listings took 18 seconds in our tests.

### Use cases

- **Rent and jeonse price research**: Seoul officetel rent, jeonse deposits by district, jeonse vs wolse comparisons, rent maps by subway station.
- **Relocation and expat housing**: short lists of studios near a campus or office, with photos, options and the agent to call.
- **Real estate investment screening**: villas and officetels for sale with price per m², building age and parcel number to join with land registry data.
- **PropTech and market dashboards**: a repeatable feed of Korean rental listings with stable ids for deduplication across runs.
- **Agent lead lists**: licensed brokers active in an area, with office, phones and listing counts.

### What you get

| Group | Fields |
|---|---|
| Price | `deal_type`, `deposit_krw`, `monthly_rent_krw`, `sale_price_krw` (and the same in 만원: `*_10k_krw`), `maintenance_fee_krw`, `currency`, `is_short_term` |
| Property | `property_type`, `room_layout`, `size_exclusive_m2`, `size_supply_m2`, `size_contract_m2` (and pyeong), `floor`, `floor_label`, `building_floors`, `title` |
| Location | `latitude`, `longitude`, `province`, `province_en`, `district`, `neighborhood`, `lot_number`, `address`, `distance_km` |
| Listing | `listing_id`, `url`, `registered_at`, `is_new`, `move_in_date`, `tags`, `badges`, `is_verified`, `favorites_count`, `thumbnail_url`, `agent_user_no`, `building_id` |
| Detail page | `description`, `image_urls`, `options`, `bathroom_count`, `direction`, `residence_type`, `building_approval_date`, `has_parking`, `parking_spaces`, `has_elevator`, `household_count`, maintenance fee breakdown, `view_count`, `status_checked_at` |
| Land registry keys | `jibun_address`, `legal_dong_code` (법정동코드), `parcel_number` (PNU, 19 digits) |
| Neighbourhood | `nearby_subways` (with lines), `nearby_places` (distance and walking time to subway, bus, convenience store, supermarket, cafe, pharmacy…), `neighborhood_tags`, `delivery_services` |
| Complex | `complex_id`, `complex_name`, `complex_households`, `complex_completion`, `complex_category` |
| Agent | `agent_name`, `agent_office_name`, `agent_office_phone`, `agent_phone`, `agent_email`, `agent_office_registration_number`, `agent_business_registration_number`, `agent_office_address`, office coordinates, `agent_inquiry_answer_rate`, `agent_languages`, `agent_badges` |

### Measured fill rates

Measured on Apify on 1 Oct 2026 over **718 listings with their detail page** from Seoul (Gangnam, Mapo, Hongdae, central Seoul), Busan (Haeundae), Gyeonggi-do (Suwon), Incheon, Daegu and Daejeon, plus 1,000 search-only listings around central Seoul. Percentages are the share of listings where the field has a value.

| Field | All | One-room | Villa | Officetel |
|---|---|---|---|---|
| Price for the deal type, area, building floors, coordinates, address, photo, registration date, agent id | 100% | 100% | 100% | 100% |
| Maintenance fee | 100% | 100% | 100% | 100% |
| Floor number (the rest publish only low / middle / high) | 72.8% | 89.4% | 91.4% | 44.1% |
| Contract area | 37.9% | 0% | 0% | 100% |
| Move-in date | 40.9% | 26.3% | 37.1% | 56.6% |
| **Detail page:** description, photos, room layout, bathrooms, orientation, building type, parking yes/no, elevator, PNU, legal-dong code | 100% | 100% | 100% | 100% |
| Furnishing options | 96.8% | 100% | 90.5% | 98.9% |
| Building approval date (normalised) | 93.7% | 90.7% | 95.2% | 95.2% |
| Nearby subway stations | 94.7% | 94.1% | 97.1% | 93.4% |
| Walking time to amenities | 99.9% | 99.6% | 100% | 100% |
| Parking spaces | 75.3% | 64.0% | 64.8% | 93.4% |
| Households in the building | 42.5% | 22.9% | 25.2% | 72.8% |
| Apartment / officetel complex | 37.9% | 0% | 0% | 100% |
| Agent office, mobile, office phone, email, broker registration number | 100% | 100% | 100% | 100% |
| Agent speaks a language other than Korean | 34.1% | 41.1% | 37.6% | 25.4% |

Agent rows (`outputType = agents`, 60 agents around Jamsil and Bundang): office, mobile, email, registration number and office address 100%, call response rate 96.7%.

Fields that do not apply to a listing are delivered as `null`, never left out. How many listings an area has depends on Zigbang's inventory: one-rooms and officetels dominate; villas for sale or jeonse are scarce in some cities (for example 1 villa on jeonse within 3 km of Busan city hall on 1 Oct 2026).

### Pricing

Pay per result. You never pay for a failed request, an error row or a duplicate within a run.

| Event | Price |
|---|---|
| Listing | **$0.0019** |
| Listing detail page (only with `includeDetails`) | $0.00075, so a listing with its detail page costs **$0.00265** |
| Agent profile (only with `outputType = agents`) | $0.0019 |
| Actor start | $0.00001 |

1,000 listings cost $1.90; 1,000 listings with detail pages cost $2.65. If you set a maximum cost per run, the run stops cleanly when it is reached and tells you so: nothing is delivered without being charged, and nothing is charged without being delivered.

### Input

| Field | Default | What it does |
|---|---|---|
| `outputType` | `listings` | `listings` or `agents` (one row per licensed agent in the area). |
| `location` | empty = `Gangnam-gu` | A Korean district, neighbourhood or subway station, or an English district name. |
| `radiusKm` | `1.5` | Listings within this distance of the location's centre (0.2 to 20 km). |
| `latitude`, `longitude` | — | Search around exact coordinates instead of a place name. |
| `propertyTypes` | all three | `oneroom`, `villa`, `officetel`. |
| `dealTypes` | all three | `monthly_rent`, `jeonse`, `sale` (sale exists for villas and officetels only). |
| `maxItems` | `100` | Maximum rows. |
| `sortBy` | `newest` | `newest` or `nearest`. |
| `includeDetails` | `false` | Add the detail page to each listing (extra event). |
| `minDeposit` … `maxSalePrice` | — | Price filters in 만원 (10,000 KRW): `1000` = 10,000,000 KRW. |
| `minSizeM2`, `maxSizeM2` | — | Exclusive area filter. |
| `maxConcurrency` | `4` | Parallel requests (1 to 8). |

Example — officetels for monthly rent near Hongik University station, with detail pages:

```json
{
  "location": "Hongdae",
  "radiusKm": 1,
  "propertyTypes": ["officetel"],
  "dealTypes": ["monthly_rent"],
  "maxMonthlyRent": 80,
  "includeDetails": true,
  "maxItems": 200
}
```

Example — the agents with the most listings around Jamsil:

```json
{ "outputType": "agents", "location": "잠실역", "radiusKm": 2, "maxItems": 50 }
```

### Output sample

A listing with its detail page (shortened; the phone and email here are placeholders):

```json
{
  "record_type": "listing",
  "listing_id": 50484295,
  "url": "https://www.zigbang.com/home/officetel/items/50484295",
  "property_type": "officetel",
  "deal_type": "monthly_rent",
  "deposit_krw": 139000000,
  "monthly_rent_krw": 200000,
  "maintenance_fee_krw": 90000,
  "currency": "KRW",
  "size_exclusive_m2": 19.17,
  "size_supply_m2": 37.92,
  "floor": null,
  "floor_label": "low",
  "building_floors": 15,
  "room_layout": "open_studio",
  "province_en": "Seoul",
  "district": "마포구",
  "neighborhood": "성산동",
  "options": ["air_conditioner", "refrigerator", "washing_machine", "induction_cooktop"],
  "building_approval_date": "2017-11-03",
  "parcel_number": "1144012500105930001",
  "nearby_subways": [{ "id": 371, "name": "마포구청역", "lines": "6호선" }],
  "complex_name": "벽산상암스마트큐브",
  "agent_office_name": "OO공인중개사사무소",
  "agent_phone": "01000000000",
  "agent_email": "agent@example.com",
  "agent_office_registration_number": "11440-2020-00000",
  "detail_scraped": true
}
```

### Good to know

- **Jeonse (전세)** is a Korean lease with a large lump-sum deposit and no monthly rent: `monthly_rent_krw` is `null` for it, not 0.
- **Hidden floors**: 27% of listings publish only `low`, `middle` or `high` instead of a floor number (56% of officetels, measured on 718). You get `floor_label` and the original in `floor_raw`.
- **Two spellings of the same province** (서울시 and 서울특별시) appear in the source. Group by `province_en`.
- **Coordinates** are the point Zigbang shows on its map, which may be offset from the exact building.
- **Apartments (아파트)** are not included in this version: Zigbang lists them through a different complex-based system.
- The run delivers rows page by page and always writes a **run summary** and an **errors** record, so you can see what was collected and why anything was skipped.

### FAQ

**Is there an official Zigbang API?** Zigbang does not offer a public data API for listings. This actor reads the same public listing data the Zigbang website shows, without logging in, and returns it as a dataset you can download or call through the Apify API.

**Can I search in English?** Yes for the common names (Seoul, Busan, Gyeonggi, Incheon, Daegu, the 25 Seoul districts, Hongdae, Gangnam station, Jamsil, Haeundae…). Anything else works best in Korean, exactly as you would type it on Zigbang: a district (`마포구`), a neighbourhood (`역삼동`) or a subway station (`강남역`).

**What is jeonse?** A Korean lease where the tenant pays a large lump-sum deposit and no monthly rent; the deposit is returned at the end. Jeonse rows have `deposit_krw` and `monthly_rent_krw: null`.

**Are apartments (아파트) included?** No. Zigbang lists apartments through a separate complex-based system; this actor covers one-rooms, villas and officetels.

**How fresh is the data?** Every run reads Zigbang live; nothing is cached. `registered_at` is when the listing was posted and `status_checked_at` (detail page) when Zigbang last confirmed it.

**How do I get only new listings every day?** Schedule the actor with `sortBy: newest` and deduplicate on `listing_id`, which is stable across runs.

**What if my place name is not found or nothing matches my filters?** The run ends green with a clear message and an error row, and nothing is charged.

**Do I need a proxy?** No. Zigbang answers without one, and the actor switches connection by itself if requests are ever refused.

### Privacy

Listings on Zigbang are published by licensed real-estate agents: **718 of 718** detail pages measured on 1 Oct 2026 (and 301 of 301 on 23 Sep) carried a brokerage office registration number. Their office phone, business mobile and email are published on Zigbang for customer calls and are delivered as business contact data. If an advertiser without a broker registration number ever appears, their phones and email are removed (and phone numbers written in their free text are masked) unless you enable `includePrivateSellerContact`, which you should only do if you have a lawful basis to process that data. Make sure your use of the data complies with the laws that apply to you, including Korea's Personal Information Protection Act.

# Actor input Schema

## `outputType` (type: `string`):

Listings = one row per property listing (default). Agents = one row per licensed real-estate agent publishing in the area, ranked by how many listings they have there, with office, phones, email and registration numbers. One row type per run.

## `location` (type: `string`):

Where to search, resolved with Zigbang's own place search. Korean names work best: a district (마포구), neighbourhood (역삼동) or subway station (강남역). Common English names are translated for you: Seoul, Busan, Gyeonggi, Haeundae, Gangnam-gu, Mapo-gu, Hongdae, Jamsil and the other Seoul districts. Empty = Gangnam-gu. Ignored when latitude and longitude are set.

## `radiusKm` (type: `number`):

Listings within this distance of the location's centre. Measured 23 Sep 2026 with all three property types: 310 listings within 1.5 km of the Gangnam-gu centre, 475 within 1.5 km of Hongik University station (Hongdae).

## `latitude` (type: `number`):

Search around exact coordinates instead of a place name. Set both latitude and longitude, inside South Korea.

## `longitude` (type: `number`):

Longitude of the search centre. Used only together with latitude.

## `propertyTypes` (type: `array`):

One-room = studios and small flats (원룸, rentals only). Villa = low-rise multi-unit houses (빌라/투룸+). Officetel = studio-office buildings (오피스텔). Apartments (아파트) are not included. Leave empty for all three.

## `dealTypes` (type: `array`):

Monthly rent (월세) = deposit plus monthly rent. Jeonse (전세) = a large lump-sum deposit and no monthly rent. Sale (매매) = purchase price (villas and officetels only). Leave empty for all three.

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

Stop after this many rows (listings, or agents with outputType = agents).

## `sortBy` (type: `string`):

Newest = highest listing id first (ids follow the registration date in 90% of pairs, measured). Nearest = closest to the location's centre first.

## `includeDetails` (type: `boolean`):

Also fetch each listing's detail page: full description, every photo, furnishing options, bathrooms, orientation, parking, elevator, building type and approval date, parcel number (PNU), nearby subway stations and amenities, apartment complex, and the licensed agent's name, office, phones, email and registration numbers. One extra request per listing, charged as a separate event.

## `minDeposit` (type: `integer`):

In units of 10,000 KRW, the way Zigbang shows prices: 1000 = 10,000,000 KRW. Applies to monthly-rent and jeonse listings.

## `maxDeposit` (type: `integer`):

In units of 10,000 KRW: 5000 = 50,000,000 KRW.

## `minMonthlyRent` (type: `integer`):

In units of 10,000 KRW: 50 = 500,000 KRW per month.

## `maxMonthlyRent` (type: `integer`):

In units of 10,000 KRW: 80 = 800,000 KRW per month.

## `minSalePrice` (type: `integer`):

In units of 10,000 KRW: 30000 = 300,000,000 KRW.

## `maxSalePrice` (type: `integer`):

In units of 10,000 KRW: 60000 = 600,000,000 KRW.

## `minSizeM2` (type: `number`):

Exclusive (net) area in square metres.

## `maxSizeM2` (type: `number`):

Exclusive (net) area in square metres.

## `includePrivateSellerContact` (type: `boolean`):

Licensed agents' business phones and email are always included. Every advertiser measured was a registered broker (301 of 301 detail pages, 23 Sep 2026); if an advertiser without a broker registration number ever appears, their phones and email are removed unless you enable this. Enable only if you have a lawful basis to process private individuals' contact data.

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

How many requests run at once. 4 finished every test run cleanly; 6 in parallel were measured without a single refusal. Higher is faster but more likely to be slowed down by the site.

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

Not needed: Zigbang answers without a proxy, and the actor switches to a Korean residential connection by itself if requests are ever refused. Set your own proxy only if you must; if it does not work, the run ends with an explanation and nothing is charged.

## Actor input object example

```json
{
  "outputType": "listings",
  "location": "Hongdae",
  "radiusKm": 1,
  "propertyTypes": [
    "oneroom",
    "officetel"
  ],
  "dealTypes": [
    "monthly_rent",
    "jeonse"
  ],
  "maxItems": 30,
  "sortBy": "newest",
  "includeDetails": true,
  "includePrivateSellerContact": false,
  "maxConcurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `listings` (type: `string`):

Listings with price in KRW, area, floor, location, address and, with includeDetails, photos, options, amenities and the agent's contact.

## `agents` (type: `string`):

Licensed agents (outputType = agents) with office, phones, email, registration numbers and listing counts.

## `datasetUrl` (type: `string`):

Download all fields as JSON, CSV or Excel.

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

Counts of delivered and charged rows, requests and errors for this run.

## `errors` (type: `string`):

Anything that could not be collected, and why. Never charged. Always present, empty when all went well.

# 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 = {
    "location": "Hongdae",
    "radiusKm": 1,
    "propertyTypes": [
        "oneroom",
        "officetel"
    ],
    "dealTypes": [
        "monthly_rent",
        "jeonse"
    ],
    "maxItems": 30,
    "includeDetails": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("oswaldocarabano/zigbang-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 = {
    "location": "Hongdae",
    "radiusKm": 1,
    "propertyTypes": [
        "oneroom",
        "officetel",
    ],
    "dealTypes": [
        "monthly_rent",
        "jeonse",
    ],
    "maxItems": 30,
    "includeDetails": True,
}

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

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

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

```

## CLI example

```bash
echo '{
  "location": "Hongdae",
  "radiusKm": 1,
  "propertyTypes": [
    "oneroom",
    "officetel"
  ],
  "dealTypes": [
    "monthly_rent",
    "jeonse"
  ],
  "maxItems": 30,
  "includeDetails": true
}' |
apify call oswaldocarabano/zigbang-scraper --silent --output-dataset

```

## MCP server setup

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

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/PCQQH5lShXbAlW4YG/builds/J6Qei0VmSz9d4J57w/openapi.json
