# Daangn Scraper $1💰 Listings, Sellers, Regions & Categories (`abotapi/daangn-scraper`) Actor

From $1/1K. Scrape Daangn (당근) marketplace listings by keyword and region. Returns 35+ fields per item including price, status, condition, full image set, region, category and seller profile (nickname, score, reviews). Search and URL modes, category and on-sale filters, price range and sort.

- **URL**: https://apify.com/abotapi/daangn-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** E-commerce, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 6 total users, 3 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 listing scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Daangn Scraper: Local Marketplace Listings, Sellers & Regions

Daangn Scraper turns Daangn (당근), Korea's largest local secondhand marketplace, into a clean listings feed. Get the title, price, link and thumbnail of every listing, plus (with detail enrichment, on by default) sale status, condition, region, category, the description, full image set, view/chat/favorite counts and the complete seller profile. Search by keyword and region, or paste Daangn search and detail URLs directly, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.

### Why This Scraper?

- **Two ways to run.** Search by keyword plus region with server-side category, on-sale, price-range and sort filters, or paste any Daangn search or detail URL.
- **Predictable run size.** Max items caps the whole run and is shared evenly across your keyword, region and URL searches, so one busy search cannot crowd out the rest. Set it to `0` to collect everything.
- **Detail enrichment on demand.** Fetch full details (on by default) adds sale status, region, category, condition, the description, full image set, view/chat/favorite counts and the complete seller profile to every listing.
- **Built for monitoring.** Incremental mode tracks the same search across scheduled runs and returns only new, updated and reappeared listings, ignoring the counters that tick up on their own between runs.
- **Resume without re-paying.** Continue one interrupted run from its run or dataset id and already-collected listings are skipped instead of re-scraped and re-billed.
- **Honest about site hiccups.** A search that comes back empty on every retry is reported as incomplete, not as "nothing matched your filters", and incremental state is never corrupted by a run that could not actually see the listings.
- **Optional one-click export** into Notion, Linear, Airtable or Apify via MCP connectors, without ever changing what lands in the dataset.

### Use Cases

- **Resale and deal hunters:** track a keyword like a phone model or appliance across one or more neighborhoods for underpriced listings.
- **Local market researchers:** benchmark asking prices for a category or region and watch how they move over time.
- **Community and neighborhood apps:** mirror fresh local listings into your own feed, bot or alert channel.
- **Second-hand demand analysts:** measure how quickly listings move from on sale to reserved or sold across categories.
- **Personal shopping agents:** get notified only when a genuinely new or changed listing matches a saved search.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live listing.

| Field | Example |
| --- | --- |
| `id` / `nodeId` | `"0000000000"` / `"a0b0c0d0e0f0"` (`id` is Daangn's numeric listing id with detail enrichment; without it, both hold the id from the listing URL) |
| `url` | `"https://www.daangn.com/kr/buy-sell/sample-a0b0c0d0e0f0/"` |
| `title` | `"Sample Laptop 14in"` |
| `price` | `480000` |
| `priceText` | `"480,000원"` |
| `isFree` / `currency` | `false` / `"KRW"` |
| `status` | `"Ongoing"` |
| `condition` | `"used"` (also `"new"`, `"refurbished"`, `"damaged"`, detail enrichment only) |
| `description` | `"Lightly used, minor wear."` |
| `location` | `"Sample-dong"` |
| `region.id` / `region.name` | `"000"` / `"Sample-dong"` |
| `category.id` / `category.name` | `"1"` / `"Digital"` (detail enrichment only) |
| `sellerName` | `"Seller Nickname"` |
| `user.score` / `user.reviewCount` | `39.2` / `23` (detail enrichment only) |
| `watchesCount` / `chatRoomsCount` / `readsCount` | `12` / `6` / `733` (detail enrichment only; `favoriteCount` and `viewCount` repeat the first and third) |
| `createdAt` | `"2026-01-01T00:00:00.000+09:00"` (may be empty without detail enrichment) |
| `images` | full-size image URLs (detail enrichment only; otherwise only a thumbnail) |
| `scrapedAt` / `daysListed` | scan time (ISO) / whole days since `createdAt` (empty when `createdAt` is empty); `listingId`, `listingStatus` and `city` alias `nodeId`, `status` and `location` |
| `isNew` | `true` when the row is new to your tracked search (Incremental mode only) |
| `previousPrice` / `lastPrice` / `priceDropPct` | prior price, and the percentage fall when the price dropped (UPDATED rows in Incremental mode only) |
| `gonePresumedSold` / `soldConfirmed` | `true` / `false` on EXPIRED rows: the listing vanished from a full scan, which Daangn does not confirm as a sale |
| `changeType` | `"NEW"` (also `"UPDATED"`, `"UNCHANGED"`, `"REAPPEARED"`, `"EXPIRED"`; Incremental mode only) |

Without Fetch full details, expect only the basics Daangn shows on its search results page: title, price, listing URL and a thumbnail. Daangn's current results page does not show region, sale status, seller or posting date, so those fields can come back empty until Fetch full details fills them in from the listing page, along with the description, full image set, category, condition, counts and complete seller profile. Leave Fetch full details on (the default) if you need them.

### How to Use

1. Pick a **mode**: `search` (keyword plus region) or `url` (paste Daangn links).
2. In search mode, add your keywords and region ids, plus any category, price-range, on-sale or sort filters. In URL mode, paste Daangn search or detail URLs instead; the run-level filter fields (price range, on-sale, keyword include/exclude, neighbourhood, availability) are ignored and only the filters inside each pasted URL apply.
3. Keep **Fetch full details** on for status, region, category, condition, the description, full image set, counts and seller profile, or turn it off for faster, lighter listings (title, price, link and thumbnail).
4. Set **Max items** to control run size and cost, then click **Start**.

**Search by keyword in one region:**

```json
{
  "mode": "search",
  "searchQueries": ["노트북"],
  "locations": ["366"],
  "maxItems": 50,
  "fetchDetails": true
}
```

**Search several keywords across several regions with a price range:**

```json
{
  "mode": "search",
  "searchQueries": ["노트북", "의자"],
  "locations": ["366", "6187"],
  "priceMin": 50000,
  "priceMax": 300000,
  "sortBy": "price_asc",
  "maxItems": 100
}
```

**Paste Daangn URLs directly:**

```json
{
  "mode": "url",
  "urls": [
    "https://www.daangn.com/kr/buy-sell/s/?search=%EB%85%B8%ED%8A%B8%EB%B6%81&region_id=366",
    "https://www.daangn.com/kr/buy-sell/sample-a0b0c0d0e0f0/"
  ],
  "fetchDetails": true,
  "maxItems": 40
}
```

**Supported URL shapes (URL mode).** Leaving `urls` untouched now scrapes one example per shape below, so clear the list and paste your own links.

| Shape | Example |
| --- | --- |
| Search | `https://www.daangn.com/kr/search/buy-sell/?q=노트북` |
| Older search link | `https://www.daangn.com/kr/buy-sell/s/?search=노트북` (read as `q=`) |
| Search with region | `https://www.daangn.com/kr/search/buy-sell/?in=서초4동-366&q=노트북` |
| Region browse, no keyword | `https://www.daangn.com/kr/search/buy-sell/?in=서초4동-366` |
| Browse root, no keyword | `https://www.daangn.com/kr/buy-sell/` |
| Listing page | `https://www.daangn.com/kr/buy-sell/<slug>-<id>/` |
| Listing page, id only | `https://www.daangn.com/kr/buy-sell/<id>/` |

Filters inside a pasted search URL (`category_id`, `only_on_sale`, `price=min__max`) are applied (run-level filter fields do not apply in URL mode). A numeric `in=366` or the `name-id` form is read as the search region. `order` is not supported by the site; it is ignored with a warning in the log.

**Track a search over repeated scheduled runs (Incremental mode):**

```json
{
  "mode": "search",
  "searchQueries": ["노트북"],
  "locations": ["366"],
  "incrementalMode": true,
  "emitExpired": true,
  "maxItems": 0
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/daangn-scraper").call(run_input={"mode": "search", "searchQueries": ["노트북"], "locations": ["366"]})
for listing in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(listing["title"], listing["priceText"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/daangn-scraper').call({ mode: 'search', searchQueries: ['노트북'], locations: ['366'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### Max items and Max pages

**Max items** caps the whole run, and it is shared evenly across your searches: every keyword and region pair (and every pasted URL) gets up to Max items divided by the number of searches, rounded up. A search that finds fewer listings than its share does not hand the unused part to the others, so a multi-search run can finish below Max items. Set it to `0` for no limit, which is also the way to get every matching listing from every search.

A listing that turns up in more than one search in the same run is returned once, by the first search that finds it. One side effect to know about: when a search uses up its share partway through a batch of results, the rest of that batch is counted as already collected without being returned, so if a later search in the same run finds those same listings, it skips them too. With overlapping searches (for example the same keyword in neighboring regions) a capped run can therefore miss a few listings it could have returned. Set Max items to `0`, or run overlapping searches separately, when you need full coverage. This never causes a listing to be wrongly reported as `EXPIRED`.

**Max pages** is only an optional safety bound on how many 30-listing chunks of one search's already-fetched result set to walk through; leave it empty for unlimited.

#### Resume and recurring updates

Two separate features cover two separate needs:

- **`resumeFromRunId`** continues ONE specific interrupted run. Paste the run id or dataset id from a previous run that got cut off and this run skips every listing it already collected, so you don't pay to re-scrape and re-download what you already have. A bad id fails the run before anything new is collected or charged.
- **`incrementalMode`** tracks the SAME search across many scheduled runs on its own, no id to paste. Turn it on and schedule the actor; each run compares against a baseline it remembers itself (keyed by your search settings, or your own **State key**) and returns only `changeType: "NEW"`, `"UPDATED"` or `"REAPPEARED"` listings, plus `changedFields`, `firstSeenAt` and `lastSeenAt`. Unchanged listings are neither returned nor billed unless you turn on **Emit unchanged listings**. A listing that disappears is only reported as `"EXPIRED"` (and only if **Emit expired listings** is on) once a run completes a full, uncapped scan of every search in it; a run limited by Max items (the default is 20) never reports EXPIRED, since it never proved those listings are actually gone.
- The baseline is keyed on your search settings (mode, keywords, regions, category, on-sale, price range, sort, URLs, Fetch full details, and, when set, Include/Exclude keywords, Neighbourhood contains and Availability: changing any of these starts a new baseline whose listings are billed as NEW), never on the comparison settings (Fields to ignore, Change scope), never on Max items, Max pages, the residential budget or the connector export cap, so raising a limit keeps your existing baseline instead of starting over and re-billing everything.
- Live engagement counters (chat, favorite, view and read counts) and a re-boost timestamp change from other users' activity, independent of the listing itself. Incremental mode ignores these, along with seller reputation and the search keyword that found the listing, when deciding NEW, UPDATED or UNCHANGED, so a listing is not reported as changed every run just because someone viewed or bumped it. A real change to price, status, condition, title, description or images still always triggers `"UPDATED"`. Add more noisy fields with **Ignore fields when detecting changes** (dotted names such as `seller.score` reach nested fields; ignored fields stay in the output). Whether a stored listing is UNCHANGED is decided by re-checking the saved record against your current ignore list, so editing the list never re-bills the whole baseline.
- **`changeScope`** set to `priceAndStock` compares only price, price text, the free flag and status, so description, photo or location edits never create a row. **`compactUpdates`** makes UPDATED and EXPIRED rows slim (ids, url, title, current price and status, plus `priceChanges` with old and new values); NEW rows stay full, and the detail-enrichment charge is not applied to a compact row because it carries no detail fields. **`expireAfterMissedScans`** (default 1) waits for that many consecutive complete scans before a listing is marked EXPIRED. EXPIRED means the listing dropped out of the search, not that it was sold or deleted; read `status` for availability.
- If a search comes back with zero listings on every retry, the run treats that as incomplete rather than a real empty result: it never marks the tracked listings for that search EXPIRED, and it says so in the run's status message. Running it again shortly usually returns the full result set.

### Send results into your apps (MCP connectors)

You can optionally pipe each run's results into the apps you already use through Model Context Protocol (MCP) connectors. Authorize a connector under Apify -> Settings -> API & Integrations, then select it in the `mcpConnectors` field. Notion receives a rich page per item (set `notionParentPageUrl` to the parent page); Linear, Airtable and Apify receive a best-effort write or digest. This never changes the dataset output, and any connector error is logged and skipped without affecting the scrape.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` builds Daangn searches from your keywords, regions and filters; `url` uses the pasted Daangn URLs (the run-level filter fields are ignored in URL mode; only filters inside each pasted URL apply). |
| `searchQueries` | array | `["노트북"]` | Keywords to search Daangn for. Each query is scraped independently (search mode). |
| `locations` | array | (none), prefilled `["366"]` | Daangn region ids, or the `name-id` form such as `서초4동-366` (plain names without an id are skipped with a warning in the log and the query runs without that region, because the site has no name lookup) to pass to the site as the search region (e.g. 366 for Seocho-4-dong, 6187 for Sincheon-dong). The site decides how strongly a region narrows the results, so check the `region` field of the returned listings. Each query runs for each region. Empty resolves the region from the connection automatically. |
| `categoryId` | integer | (none) | Restrict results to one Daangn category id (e.g. 1 Digital, 8 Furniture, 9 Books). Empty means all categories. |
| `onlyOnSale` | boolean | `false` | Return only listings that are still on sale, excluding reserved and completed items. |
| `priceMin` | integer | (none) | Only return listings priced at or above this amount, in KRW. |
| `priceMax` | integer | (none) | Only return listings priced at or below this amount, in KRW. |
| `includeKeywords` | array | (none) | Keep only listings whose title contains any of these words. |
| `excludeKeywords` | array | (none) | Drop listings whose title contains any of these words. |
| `cities` | array | (none) | Keep only listings whose neighbourhood name contains any of these texts. The search results page does not show the neighbourhood, so this needs Fetch full details: it is checked on the listing page, and listings that fail it are neither returned nor charged for detail enrichment. With Fetch full details off, no listing can match and the run logs a warning. Search mode only. |
| `availability` | string | `all` | `available` asks the site for on-sale listings only and, with Fetch full details, also drops any listing whose page shows it reserved or completed (dropped listings are not charged for detail enrichment). `all` keeps everything. Search mode only. |
| `maxListingsPerSearch` | integer | (none) | Cap on listings taken from each search or URL. A capped search never reports EXPIRED listings in Incremental mode. |
| `sortBy` | string | `recommended` | Order results are returned in: `recommended`, `recent` (alias `newest`), `price_asc` or `price_desc`. `recent` sorts by posting date, which Daangn's current results page does not show, so it can keep Daangn's own order. |
| `urls` | array | one example per shape (7 URLs) | Daangn search or detail URLs (URL mode). Run-level filter fields (price range, on-sale, include/exclude keywords, neighbourhood, availability) are ignored, but filters inside a pasted URL (`in`, `category_id`, `only_on_sale`, `price=min__max`) are applied. Sort and Max listings per search still apply. |
| `fetchDetails` | boolean | `true` | Visit each listing page for the description, full image set, view/chat/favorite counts and the complete seller profile. Turn off for faster, lighter listings. |
| `maxItems` | integer | `20` | Cap on this run across every query, region and URL, shared evenly between searches (see Max items and Max pages above). `0` means unlimited. |
| `maxPages` | integer | (none) | Optional safety bound on how many 30-listing result chunks to walk per query. Empty means unlimited. |
| `resumeFromRunId` | string | (none) | Continue one specific interrupted run: paste a previous run id or dataset id and already-collected listings are skipped. |
| `incrementalMode` | boolean | `false` | Track this same search over repeated scheduled runs; returns only NEW, UPDATED and REAPPEARED (and, optionally, EXPIRED) listings. |
| `stateKey` | string | (none) | Optional name for the Incremental mode baseline. Empty auto-derives one from your search settings. |
| `ignoreFieldsForChanges` | array | `[]` | Incremental mode: extra fields (dotted names allowed) that never make a row UPDATED. |
| `changeScope` | string | `all` | `priceAndStock` compares only price and status. |
| `compactUpdates` | boolean | `false` | Slim UPDATED and EXPIRED rows with `priceChanges`. |
| `expireAfterMissedScans` | integer | `1` | Consecutive complete scans a listing must be missing before EXPIRED. |
| `emitUnchanged` | boolean | `false` | Incremental mode: also return, and bill, listings with no change since the last run. |
| `emitExpired` | boolean | `false` | Incremental mode: also return, and bill, listings no longer found, once a run completes a full scan. |
| `proxy` | object | Apify Proxy | Connection used for requests. |
| `maxResidentialMB` | integer | `0` | Residential traffic budget in MB. After the cap the run continues on the lower-cost datacenter tier, which returns the same Daangn data. `0` means unlimited. |
| `mcpConnectors` | array | (none) | Optional MCP connectors to export results into (Notion, Linear, Airtable, Apify). |
| `notionParentPageUrl` | string | (none) | Notion page under which item pages are created (Notion connector only). |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. Does not affect the dataset. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live listing.

```json
{
  "id": "0000000000",
  "nodeId": "a0b0c0d0e0f0",
  "url": "https://www.daangn.com/kr/buy-sell/sample-a0b0c0d0e0f0/",
  "title": "Sample Laptop 14in",
  "content": "Lightly used, minor wear.",
  "description": "Lightly used, minor wear.",
  "status": "Ongoing",
  "condition": "used",
  "listingType": "FleamarketArticle",
  "price": 480000,
  "priceText": "480,000원",
  "isFree": false,
  "currency": "KRW",
  "countryCode": "KR",
  "createdAt": "2026-01-01T00:00:00.000+09:00",
  "postedAt": "2026-01-01T00:00:00.000+09:00",
  "publishedAt": "2026-01-01T00:00:00.000+09:00",
  "imageUrl": "https://img.example.com/sample_0.webp",
  "images": ["https://img.example.com/sample_0.webp"],
  "location": "Sample-dong",
  "locationName": null,
  "regionSlug": "sample-dong-000",
  "searchQuery": "노트북",
  "region": { "id": "000", "name": "Sample-dong", "countryCode": "KR" },
  "category": { "id": "1", "name": "Digital" },
  "user": { "nickname": "Seller Nickname", "score": 39.2, "reviewCount": 23, "locationName": null },
  "tradingLocation": { "name": "Sample-dong", "isUserInput": null, "latitude": null, "longitude": null },
  "sellerName": "Seller Nickname",
  "sellerScore": 39.2,
  "sellerReviewCount": 23,
  "watchesCount": 12,
  "chatRoomsCount": 6,
  "readsCount": 733
}
```

#### Output tab views and run summary

The Output tab offers three views of the dataset: **Overview** (core listing columns), **Detail** (enriched description, images, category, region and seller) and **Changes** (incremental rows with change type, changed fields and price history). Each run also stores a per-search summary in the key-value store record `OUTPUT`: listing count, total available, emitted count, whether the search was truncated, and the new, updated and price-drop counts, plus the number of listings marked expired. The summary adds no dataset rows and no charges.

### Plan Requirement

The default (datacenter) connection works out of the box and is the lowest-cost option, and the actor rotates to a fresh connection automatically when one is refused. For the most reliable results, switch the proxy group to Residential with country KR under Proxy & connection, and set a Residential traffic budget to cap spend; once the budget is reached the run continues on the lower-cost tier with identical results.

### FAQ

#### How much does it cost?

You pay per listing returned, plus a per-run start fee and a small surcharge for each returned listing that was enriched from its detail page. In Incremental mode, a listing that is held back as unchanged is not charged, even if its detail page was fetched to check it. The **Pricing** tab shows the current rates. Use **Max items** to cap the cost of any run.

#### Is it legal to scrape Daangn?

This actor collects only publicly available marketplace listings. You are responsible for how you use the data: follow Daangn's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Listing prices and descriptions are user-submitted content, and seller profile fields and images may carry personal or third-party rights.

#### Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. Each run then returns only new, updated and reappeared listings, and unchanged ones are not billed unless you turn on **Emit unchanged listings**.

#### What is the difference between Resume and Incremental mode?

**Resume** (`resumeFromRunId`) continues one specific interrupted run using a pasted run or dataset id; it is a one-off. **Incremental mode** tracks the same search across many scheduled runs on its own, with no id to paste, and classifies each listing as new, updated, unchanged, reappeared or expired against a baseline it remembers itself. You can combine the two only on the very first Incremental run of a search, where the resumed listings seed the new baseline. Once that search (or your State key) already has a saved Incremental baseline, a run with both turned on fails immediately with a clear message, so you don't silently mix a one-off catch-up with an ongoing monitoring baseline.

#### Why did my run fail instead of returning an empty dataset?

If the site refuses every connection attempt for every search, the run fails with a clear message instead of quietly returning nothing, so a blocked run is never confused with a real empty search. If instead Daangn answers but keeps returning zero listings for a particular keyword and region, the run says so and asks you to try again shortly. Daangn does this intermittently for some keyword and region pairs, and a re-run usually returns the full result set.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the `mcpConnectors` field to push results into Notion, Linear or Airtable.

### 🔗 Want more classifieds data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🏷️ <a href="https://apify.com/abotapi/marktplaats-nl-scraper"><b>Marktplaats.nl Scraper</b></a><br>Scrape Marktplaats.nl listings by keyword or URL. Extract title, price, condition...</td><td>🏷️ <a href="https://apify.com/abotapi/vinted-fr-scraper"><b>Vinted.fr</b></a><br>Scrape Vinted.fr, France's C2C second-hand fashion marketplace: search with...</td></tr>
<tr><td>🏷️ <a href="https://apify.com/abotapi/gumtree-uk-scraper"><b>Gumtree.com Scraper</b></a><br>Scrape Gumtree.com classifieds across motors, property, jobs, services, pets and goods...</td><td>🏷️ <a href="https://apify.com/abotapi/2dehands-2ememain-scraper"><b>2dehands &amp; 2ememain</b></a><br>Scrape classifieds from 2dehands.be and 2ememain.be by keyword, filters, or URLs. Returns...</td></tr>
<tr><td>🏷️ <a href="https://apify.com/abotapi/bol-com-scraper"><b>bol.com Scraper</b></a><br>Scrape bol.com products: title, price, list price and discount, EAN, brand, images...</td><td>🏷️ <a href="https://apify.com/abotapi/vinted-marketplace-scraper"><b>Vinted Multi-Country Scraper</b></a><br>Scrape Vinted across 27 country marketplaces: keyword search with brand, price and...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/daangn-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

## `mode` (type: `string`):

How to start the scrape. 'search' builds Daangn searches from your keywords + regions + filters. 'url' uses the Daangn search or detail URLs you paste (the run-level filter fields below are ignored in URL mode; only filters inside each pasted URL apply).

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

One or more keywords to search Daangn for. Each query is scraped independently.

## `locations` (type: `array`):

Daangn region ids (e.g. '366' for Seocho-4-dong) or the site's 'name-id' form ('서초4동-366', as found in the `in=` part of a Daangn search URL). Plain names without an id are skipped with a warning and the query runs without that region, because the site has no name lookup. Each query is run for each region. Leave empty to use the region resolved from the connection automatically.

## `categoryId` (type: `integer`):

Restrict results to one Daangn category id. Examples: 1 Digital, 172 Appliances, 8 Furniture, 7 Living/Kitchen, 4 Baby/Kids, 5 Women's clothing, 14 Men's fashion, 6 Beauty, 3 Sports/Leisure, 2 Hobby/Game, 9 Books, 13 Other. Leave empty for all categories.

## `onlyOnSale` (type: `boolean`):

Return only listings that are still on sale (excludes reserved and completed items).

## `priceMin` (type: `integer`):

Only return listings priced at or above this amount.

## `priceMax` (type: `integer`):

Only return listings priced at or below this amount.

## `includeKeywords` (type: `array`):

Keep only listings whose title contains at least one of these words (case-insensitive).

## `excludeKeywords` (type: `array`):

Drop listings whose title contains any of these words (case-insensitive).

## `cities` (type: `array`):

Keep only listings whose neighbourhood name contains any of these texts (for example 서초). Checked on the listing page, so it needs Fetch full details (with it off no listing can match). Listings that fail it are not returned or charged. Search mode only.

## `availability` (type: `string`):

`available` asks the site for on-sale listings only and, with Fetch full details, also drops listings whose page shows them reserved or closed. Search mode only. `all` keeps everything the site returns.

## `maxListingsPerSearch` (type: `integer`):

Cap on listings taken from each search or URL. The site serves a few hundred per search. Empty means no per-search cap (Max items still applies).

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

Order results are returned in.

## `urls` (type: `array`):

Paste Daangn search URLs (current https://www.daangn.com/kr/search/buy-sell/?q=..., the older /kr/buy-sell/s/?search=... form, region-only and browse-root links) or item detail URLs (https://www.daangn.com/kr/buy-sell/<slug>-<id>/ or /kr/buy-sell/<id>/). Facets in a pasted URL (in, category_id, only_on_sale, price=min__max) apply, while the run-level filters do not apply in URL mode; order is not supported by the site and is ignored with a warning. Left untouched, URL mode scrapes one example per URL shape.

## `fetchDetails` (type: `boolean`):

Adds the description, full image set, category, view/chat/favorite counts and the complete seller profile (score, reviews, profile image) to each listing. Slower; turn off for fast basic listings.

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

THE cap on this run: stop after collecting this many listings (across all queries/URLs). This is the only finite default cap. Set 0 for unlimited.

## `maxPages` (type: `integer`):

Optional safety bound on how many result pages to walk per query. Defaults to unlimited (leave empty or 0) and does NOT cap the run: the run stops at Max items, never here. Use only to short-circuit a single query's pagination; it never imposes a separate cap and always defers to Max items.

## `proxy` (type: `object`):

Connection used for requests. Datacenter (the default) is the cheapest and works on every plan; Residential with country KR is the most reliable.

## `maxResidentialMB` (type: `integer`):

When using a Residential proxy group, cap residential traffic at this many MB; after the cap the run continues on the lower-cost datacenter proxy, which returns the same Daangn data. 0 = unlimited.

## `resumeFromRunId` (type: `string`):

Paste a previous run id or dataset id to continue an interrupted crawl: listings already collected there are skipped so this run returns only what's missing. A one-off continuation, distinct from Incremental mode below, which tracks a search across many scheduled runs on its own.

## `incrementalMode` (type: `boolean`):

For a scheduled/recurring run of the SAME search: remembers what was collected last time and returns only NEW, UPDATED, REAPPEARED and (optionally) EXPIRED listings. A listing is UPDATED when any of its returned fields changed, such as price, status, title, description, photos or location. These are excluded from the comparison (they still appear in the output): engagement counters (favorites, chats, views), the re-boost timestamp, seller score and review count, and the search query that found it; add more with 'Ignore fields when detecting changes'. Off by default (returns everything, like a one-off run). Distinct from 'Resume from run/dataset id' above, which continues one specific interrupted run instead of tracking a recurring search.

## `stateKey` (type: `string`):

Optional name for the saved baseline used by Incremental mode. Leave empty to auto-derive one from your search settings (queries, regions, category, filters, sort, URLs, fetch details) — two different filter setups never share a baseline. Set your own to explicitly separate or share monitoring campaigns.

## `emitUnchanged` (type: `boolean`):

When on, Incremental mode also returns listings with no change since the last run (changeType UNCHANGED). Off by default: unchanged listings are neither returned nor billed, only NEW/UPDATED/REAPPEARED/EXPIRED are. Turning this on returns — and bills — every listing every run.

## `emitExpired` (type: `boolean`):

When on, Incremental mode also returns listings that were tracked before but are no longer found (changeType EXPIRED), once a run completes a full scan of the search. Off by default. Turning this on returns — and bills — an extra row per listing that disappeared.

## `changeScope` (type: `string`):

'all' (default) reports a listing as UPDATED when any non-ignored field changed. 'priceAndStock' compares ONLY price, price text, free flag and sale status, so edits to the description, photos or location never create a billable row. Switching scope never re-bills the baseline, with an explicit or the automatic state key.

## `compactUpdates` (type: `boolean`):

When on, UPDATED and EXPIRED rows contain only ids, url, title, current price and status, plus priceChanges with the old and new value of each moved field. NEW rows stay full. The detail-enrichment charge is not applied to a compact row, since it carries no detail fields. Off by default.

## `expireAfterMissedScans` (type: `integer`):

With 'Emit expired listings', a listing is marked EXPIRED only after it was missing from this many CONSECUTIVE complete scans (default 1). A listing that drops out of the search is not necessarily sold or deleted; check the status field for availability.

## `ignoreFieldsForChanges` (type: `array`):

Optional. Field names to exclude from UPDATED change detection, in addition to the built-in handling (favorite, chat and view counters, the re-boost timestamp, seller score and review count, and the search query are already ignored). Use this for another field that changes without the listing itself changing, for example imageUrl if image links rotate. Nested fields use a dotted name such as seller.score. Excluded fields stay in the output; they just never make a row UPDATED.

## `mcpConnectors` (type: `array`):

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify -> Settings -> API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write/digest. Leave empty to skip; never changes the dataset output. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "searchQueries": [
    "노트북"
  ],
  "locations": [
    "366"
  ],
  "onlyOnSale": false,
  "availability": "all",
  "sortBy": "recommended",
  "urls": [
    "https://www.daangn.com/kr/search/buy-sell/?q=%EB%85%B8%ED%8A%B8%EB%B6%81",
    "https://www.daangn.com/kr/buy-sell/s/?search=%EB%85%B8%ED%8A%B8%EB%B6%81",
    "https://www.daangn.com/kr/search/buy-sell/?in=%EC%84%9C%EC%B4%884%EB%8F%99-366&q=%EB%85%B8%ED%8A%B8%EB%B6%81",
    "https://www.daangn.com/kr/search/buy-sell/?in=%EC%84%9C%EC%B4%884%EB%8F%99-366",
    "https://www.daangn.com/kr/buy-sell/",
    "https://www.daangn.com/kr/buy-sell/lg-%EA%B7%B8%EB%9E%A8-14%EC%9D%B8%EC%B9%98-i7-%EB%85%B8%ED%8A%B8%EB%B6%81-%ED%8C%90%EB%A7%A4%ED%95%A9%EB%8B%88%EB%8B%A4-%EC%B6%A9%EC%A0%84%EA%B8%B0-%ED%8F%AC%ED%95%A8-c8pus5du46jt/",
    "https://www.daangn.com/kr/buy-sell/c8pus5du46jt/",
    "https://www.daangn.com/kr/search/buy-sell/?q=%EB%85%B8%ED%8A%B8%EB%B6%81&category_id=1&in=%EC%84%9C%EC%B4%884%EB%8F%99-366",
    "https://www.daangn.com/kr/buy-sell/?in=%EC%84%9C%EC%B4%884%EB%8F%99-366&only_on_sale=true&price=10000__500000&search=%EB%85%B8%ED%8A%B8%EB%B6%81",
    "https://www.daangn.com/kr/search/buy-sell/?q=%EB%85%B8%ED%8A%B8%EB%B6%81&sort=recent",
    "https://www.daangn.com/buy-sell/?search=%EB%85%B8%ED%8A%B8%EB%B6%81"
  ],
  "fetchDetails": true,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "maxResidentialMB": 0,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "changeScope": "all",
  "compactUpdates": false,
  "expireAfterMissedScans": 1,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `detail` (type: `string`):

No description

## `changes` (type: `string`):

No description

## `summary` (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 = {
    "mode": "search",
    "searchQueries": [
        "노트북"
    ],
    "locations": [
        "366"
    ],
    "urls": [
        "https://www.daangn.com/kr/search/buy-sell/?q=%EB%85%B8%ED%8A%B8%EB%B6%81",
        "https://www.daangn.com/kr/buy-sell/s/?search=%EB%85%B8%ED%8A%B8%EB%B6%81",
        "https://www.daangn.com/kr/search/buy-sell/?in=%EC%84%9C%EC%B4%884%EB%8F%99-366&q=%EB%85%B8%ED%8A%B8%EB%B6%81",
        "https://www.daangn.com/kr/search/buy-sell/?in=%EC%84%9C%EC%B4%884%EB%8F%99-366",
        "https://www.daangn.com/kr/buy-sell/",
        "https://www.daangn.com/kr/buy-sell/lg-%EA%B7%B8%EB%9E%A8-14%EC%9D%B8%EC%B9%98-i7-%EB%85%B8%ED%8A%B8%EB%B6%81-%ED%8C%90%EB%A7%A4%ED%95%A9%EB%8B%88%EB%8B%A4-%EC%B6%A9%EC%A0%84%EA%B8%B0-%ED%8F%AC%ED%95%A8-c8pus5du46jt/",
        "https://www.daangn.com/kr/buy-sell/c8pus5du46jt/",
        "https://www.daangn.com/kr/search/buy-sell/?q=%EB%85%B8%ED%8A%B8%EB%B6%81&category_id=1&in=%EC%84%9C%EC%B4%884%EB%8F%99-366",
        "https://www.daangn.com/kr/buy-sell/?in=%EC%84%9C%EC%B4%884%EB%8F%99-366&only_on_sale=true&price=10000__500000&search=%EB%85%B8%ED%8A%B8%EB%B6%81",
        "https://www.daangn.com/kr/search/buy-sell/?q=%EB%85%B8%ED%8A%B8%EB%B6%81&sort=recent",
        "https://www.daangn.com/buy-sell/?search=%EB%85%B8%ED%8A%B8%EB%B6%81"
    ],
    "maxItems": 20,
    "proxy": {
        "useApifyProxy": true
    },
    "ignoreFieldsForChanges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/daangn-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 = {
    "mode": "search",
    "searchQueries": ["노트북"],
    "locations": ["366"],
    "urls": [
        "https://www.daangn.com/kr/search/buy-sell/?q=%EB%85%B8%ED%8A%B8%EB%B6%81",
        "https://www.daangn.com/kr/buy-sell/s/?search=%EB%85%B8%ED%8A%B8%EB%B6%81",
        "https://www.daangn.com/kr/search/buy-sell/?in=%EC%84%9C%EC%B4%884%EB%8F%99-366&q=%EB%85%B8%ED%8A%B8%EB%B6%81",
        "https://www.daangn.com/kr/search/buy-sell/?in=%EC%84%9C%EC%B4%884%EB%8F%99-366",
        "https://www.daangn.com/kr/buy-sell/",
        "https://www.daangn.com/kr/buy-sell/lg-%EA%B7%B8%EB%9E%A8-14%EC%9D%B8%EC%B9%98-i7-%EB%85%B8%ED%8A%B8%EB%B6%81-%ED%8C%90%EB%A7%A4%ED%95%A9%EB%8B%88%EB%8B%A4-%EC%B6%A9%EC%A0%84%EA%B8%B0-%ED%8F%AC%ED%95%A8-c8pus5du46jt/",
        "https://www.daangn.com/kr/buy-sell/c8pus5du46jt/",
        "https://www.daangn.com/kr/search/buy-sell/?q=%EB%85%B8%ED%8A%B8%EB%B6%81&category_id=1&in=%EC%84%9C%EC%B4%884%EB%8F%99-366",
        "https://www.daangn.com/kr/buy-sell/?in=%EC%84%9C%EC%B4%884%EB%8F%99-366&only_on_sale=true&price=10000__500000&search=%EB%85%B8%ED%8A%B8%EB%B6%81",
        "https://www.daangn.com/kr/search/buy-sell/?q=%EB%85%B8%ED%8A%B8%EB%B6%81&sort=recent",
        "https://www.daangn.com/buy-sell/?search=%EB%85%B8%ED%8A%B8%EB%B6%81",
    ],
    "maxItems": 20,
    "proxy": { "useApifyProxy": True },
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/daangn-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 '{
  "mode": "search",
  "searchQueries": [
    "노트북"
  ],
  "locations": [
    "366"
  ],
  "urls": [
    "https://www.daangn.com/kr/search/buy-sell/?q=%EB%85%B8%ED%8A%B8%EB%B6%81",
    "https://www.daangn.com/kr/buy-sell/s/?search=%EB%85%B8%ED%8A%B8%EB%B6%81",
    "https://www.daangn.com/kr/search/buy-sell/?in=%EC%84%9C%EC%B4%884%EB%8F%99-366&q=%EB%85%B8%ED%8A%B8%EB%B6%81",
    "https://www.daangn.com/kr/search/buy-sell/?in=%EC%84%9C%EC%B4%884%EB%8F%99-366",
    "https://www.daangn.com/kr/buy-sell/",
    "https://www.daangn.com/kr/buy-sell/lg-%EA%B7%B8%EB%9E%A8-14%EC%9D%B8%EC%B9%98-i7-%EB%85%B8%ED%8A%B8%EB%B6%81-%ED%8C%90%EB%A7%A4%ED%95%A9%EB%8B%88%EB%8B%A4-%EC%B6%A9%EC%A0%84%EA%B8%B0-%ED%8F%AC%ED%95%A8-c8pus5du46jt/",
    "https://www.daangn.com/kr/buy-sell/c8pus5du46jt/",
    "https://www.daangn.com/kr/search/buy-sell/?q=%EB%85%B8%ED%8A%B8%EB%B6%81&category_id=1&in=%EC%84%9C%EC%B4%884%EB%8F%99-366",
    "https://www.daangn.com/kr/buy-sell/?in=%EC%84%9C%EC%B4%884%EB%8F%99-366&only_on_sale=true&price=10000__500000&search=%EB%85%B8%ED%8A%B8%EB%B6%81",
    "https://www.daangn.com/kr/search/buy-sell/?q=%EB%85%B8%ED%8A%B8%EB%B6%81&sort=recent",
    "https://www.daangn.com/buy-sell/?search=%EB%85%B8%ED%8A%B8%EB%B6%81"
  ],
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/daangn-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/daangn-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/SnadC3qCLCYXZ8PSW/builds/m8hZt2ZImfrWR8JSJ/openapi.json
