# KKday Product Details Scraper (`boncross/kkday-product-details`) Actor

Scrape KKday product pages. Just add product URLs and get the title, subtitle, highlights, description, every package, images and video clips, rating with its star distribution, booking and wishlist counts, price range, destination chain, category and sale window. $3.00 per 1,000 products.

- **URL**: https://apify.com/boncross/kkday-product-details.md
- **Developed by:** [BonCross API](https://apify.com/boncross) (community)
- **Categories:** Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.10 / 1,000 product-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

## KKday Product Details Scraper

### What is KKday Product Details Scraper?

How many people have booked Seoul's NANTA show through KKday? 39,489, with 16,594 more who've saved it, a 4.85 rating from 5,638 reviews, five packages and a price range of $23.17 to $40.37. KKday Product Details Scraper gives you that record for any product: paste a link, or type a keyword and let it find the products first.

One row per product, and it's the full record, not a listing card:

- **Demand you can count.** Booking count and wishlist count on each product, plus the rating broken down star by star (NANTA: 4,992 fives, 30 ones).
- **Every package, with ids.** Names, package ids and item ids, ready to hand to the availability actor when you need dated prices.
- **What reviewers say, already summarised.** KKday's written review summary and its sentiment topics come with the record at no extra charge.
- **Search built in.** Keywords return KKday's listing rows in four orders, and one switch reads the full record for each hit.
- **$3.00 per 1,000 products** on the Free plan, $2.10 on Business. Forty products took 73 seconds.

**BonCross Verified** means we tested this actor against the live site before release and kept the record:

- 25 of 25 live checks on its inputs and filters passed on 8 October 2026
- 13 products run on 7 October 2026, tickets, tours, a show and an eSIM: 12 records, 1 row for an unknown product
- Charges matched the rows: 12 scraped, 1 checked
- An unknown product pays the checked fee only

### Which KKday actor do you need?

| You want | Use |
|---|---|
| The description, packages, price range, rating and booking count of a product | This actor |
| The price and availability of each date and time slot | KKday Product Availability & Prices |
| The reviews themselves | KKday Product Reviews Scraper |
| Everything KKday sells for a keyword, with KKday's own filters | KKday Search Scraper |

### What data can you extract?

| | |
|---|---|
| Product title | Section headings |
| 📝 Subtitle and description | 🖼️ Gallery images |
| 🎬 Video clips | ⭐ Rating and scale |
| Review count | 📊 Star distribution |
| 🛒 Booking count | ❤️ Wishlist count |
| 💵 Lowest price | Highest price |
| List price | 📦 Packages with ids |
| 🌏 Country and city | Destination chain |
| Category | Sentiment tags and review summary |
| Supplier id, on marketplace products | 📅 Sale window |
| On sale and sold-out flags | ⚡ Instant confirmation |
| Product id | 🔗 Product link |
| Keyword search rows | Result rank and total |

### How to scrape KKday product details

1. [Sign up for a free Apify account](https://console.apify.com/sign-up).
2. Open [KKday Product Details Scraper](https://apify.com/boncross/kkday-product-details).
3. Paste product links under "Products", or type keywords under "Search keywords". You can use both.
4. Set the currency, and switch on "Include related products" if you want the products KKday shows alongside.
5. Press Start and download the records as JSON, Excel or CSV.

### ⬇️ Input

You give it products, keywords, or both. A product can be a full link, a slug or a bare product number.

Keywords behave differently from links, and it matters for your bill. A keyword returns search rows, which are listing cards: name, price range, rating, booking count, images, destinations and tags. If you also want the full record for each hit, switch on "Read full details for search hits". You then get two rows per hit, a search row and a product row, each at its own price.

"Max results per keyword" (default 60) applies to each keyword separately, so ten keywords at 50 each returns 500. "Maximum results for the whole run" caps search rows and product rows together, and nothing past it is fetched or charged for. More links than you'd want to paste go in "Start URLs", loaded from a file, a Google Sheet or a remote list.

#### One product

```json
{
  "products": ["https://www.kkday.com/en/product/2358-nanta-show-tickets-in-seoul"],
  "currency": "USD"
}
```

#### What sells best in a destination

```json
{
  "searchQueries": ["bangkok"],
  "searchSort": "most_booked",
  "maxResultsPerQuery": 100,
  "currency": "USD"
}
```

#### A keyword, with the full record for each hit

```json
{
  "searchQueries": ["jeju private tour"],
  "maxResultsPerQuery": 20,
  "detailSearchResults": true
}
```

#### Two products and what KKday shows beside them

```json
{
  "products": [
    "https://www.kkday.com/en/product/8332-taipei-101-observatory-ticket",
    "https://www.kkday.com/en/product/152911-floating-market-day-tour-from-bangkok-thailand"
  ],
  "includeRelated": true,
  "currency": "TWD"
}
```

#### A lean record, without the supplier or category lookups

```json
{
  "products": ["2358"],
  "includeSupplier": false,
  "includeCategories": false
}
```

| Field | Notes |
|---|---|
| `products`, `startUrls` | Product links, slugs or bare product numbers. |
| `searchQueries` | Keywords or destinations. Empty by default. |
| `maxResultsPerQuery`, `maxItems` | Per keyword (default 60, up to 5,000, 0 for all hits) and for the whole run (default 0, no cap). |
| `searchSort` | `relevance` (default), `most_booked`, `rating_desc` or `price_asc`. |
| `detailSearchResults` | Read the full record for each search hit. Off by default. |
| `includeSummary` | Rating, review count, sentiment tags and the written review summary. On by default. |
| `includeSupplier` | The supplier id, on marketplace products. On by default. |
| `includeCategories` | Destination name and the categories the product is listed under. On by default. |
| `includeRelated` | One extra row per product listing the related products. Off by default. |
| `currency` | ISO code for prices. Default `USD`. |
| `includeRawData` | Attach KKday's unprocessed product record. Off by default. |
| `delayMs`, `maxConcurrency` | Pacing, 900 and 4 by default. |

#### For developers

- `maxItems` counts search rows and product rows together. Rows that report an input the actor couldn't resolve aren't counted.
- With `detailSearchResults` on, a hit is charged `search-result` and then `product-scraped`.
- Keyword search returns 100 results a page.
- `rating_desc` is KKday's own order. It weighs the review count along with the score: a 4.94 with 583 reviews came before a 4.99 with 108.
- `maxConcurrency` (default 4, from 1 to 8) is requests in flight, and `delayMs` (default 900, up to 10,000) the pause before each. Both are the fastest values that ran clean. Lower the first or raise the second only if a run reports errors.
- A run that Apify restarts part-way continues from where it stopped, and rows already delivered aren't written or charged again.
- `includeRawData` makes each row much larger. We'd leave it off unless you need a field that isn't mapped yet.

### ⬆️ Output

Here's the NANTA record from the opening, as it came back on 7 October 2026. Long text and lists (`subtitle`, `reviewSummary`, `images`, `categories`, `sentimentTags`) are cut short with "…" here. In your dataset they're complete.

```json
{
  "input": "https://www.kkday.com/en/product/2358-nanta-show-tickets-in-seoul",
  "id": "2358",
  "url": "https://www.kkday.com/en/product/2358-nanta-show-tickets-in-seoul",
  "dataType": "product",
  "productId": "2358",
  "slug": "2358-nanta-show-tickets-in-seoul",
  "title": "Seoul NANTA Show Ticket | Myeongdong & Hongdae",
  "metaTitle": "Seoul NANTA Show Tickets | Myeongdong & Hongdae Performances",
  "subtitle": "Enjoy a world-famous non-verbal Korean performance suitable for international audiences Immerse in a unique 90-min musical journey inspired by Korea's rich culinary heritage …",
  "highlights": ["What You Can Expect", "NANTA Show"],
  "description": "Catch a NANTA show, one of Korea's most popular slapstick comedy! Book a ticket on KKday now for a fun night of all ages and nationalities.",
  "descriptionHtml": "Catch a NANTA show, one of Korea's most popular slapstick comedy! Book a ticket on KKday now for a fun night of all ages and nationalities.",
  "rating": 4.85,
  "ratingScale": 5,
  "reviewCount": 5638,
  "ratingDistribution": { "1": 30, "2": 14, "3": 91, "4": 516, "5": 4992 },
  "orderCount": 39489,
  "wishlistCount": 16594,
  "sentimentTags": [{ "name": "Location", "sentiment": "positive" }, { "name": "Seat", "sentiment": "positive" }, "…"],
  "reviewSummary": "Overall, users are extremely satisfied with this experience. Most visitors highly praise the captivating and seamless performance, highlighting its high interactivity, joyful atmosphere, and family-friendly nature. …",
  "priceFrom": 23.17,
  "priceTo": 40.37,
  "priceListed": 37.38,
  "packages": [
    { "packageId": "1843428", "name": "Early Bird Promotion_NANTA Show in Myeongdong", "itemIds": ["1589205"] },
    { "packageId": "1843429", "name": "Early Bird Promotion_NANTA Show in Hongdae", "itemIds": ["1589206"] },
    { "packageId": "1843430", "name": "NANTA Show in Myeongdong", "itemIds": ["1589207"] },
    { "packageId": "1843431", "name": "NANTA Show in Hongdae", "itemIds": ["1589208"] },
    { "packageId": "1985724", "name": "20% Off and Up - Hongdae Theater", "itemIds": ["1731501"] }
  ],
  "packageCount": 5,
  "images": ["https://image.kkday.com/v2/image/get/https://image.kkday.com/v2/image/get/s1.kkday.com/product_2358/20260209092936_Hnobu/jpg", "…"],
  "imageCount": 8,
  "coverImage": "https://image.kkday.com/v2/image/get/https://image.kkday.com/v2/image/get/s1.kkday.com/product_2358/20260209092936_Hnobu/jpg",
  "videos": [],
  "videoCount": 0,
  "country": "South Korea",
  "countryCode": "KR",
  "region": null,
  "city": "Seoul",
  "area": "Jung-gu",
  "destinations": ["South Korea", "Seoul", "Jung-gu", "Myeongdong"],
  "destinationName": "Seoul",
  "destinationCode": "D-KR-4507",
  "categoryName": "Performances & Musicals",
  "categories": ["Seoul·Attraction Tickets", "Seoul·Tours & Experiences", "Seoul·Performances & Musicals", "…"],
  "categoryCode": "CATEGORY_014",
  "tags": ["TAG_2_6"],
  "labels": [],
  "timezone": "Asia/Seoul",
  "supplier": null,
  "saleFrom": "2026-10-08",
  "saleTo": "2026-12-31",
  "isSoldOut": false,
  "isMarketplace": false,
  "isInstantConfirmation": false,
  "isInstantUse": false,
  "hasPriorityBooking": false,
  "isOnSale": true,
  "isActive": true,
  "isTourismProduct": true,
  "allowPayOnSite": false,
  "firstListedAt": "2015-03-23",
  "vertical": "TICKET",
  "currency": "USD",
  "scrapedAt": "2026-10-07T18:39:29.298Z"
}
```

Reading the record:

- `title` is the product's name and `metaTitle` the page title. `highlights` holds the section headings of the product page, as KKday writes them.
- `priceFrom` and `priceTo` span all the packages. `priceListed` is KKday's own list price. Many products have none, and where there is one it can equal the lowest price.
- `sentimentTags` and `reviewSummary` come with "Include the rating summary". `destinationName`, `destinationCode` and `categories` come with "Include destination and categories". `supplier` comes with "Include the supplier", on marketplace products only.
- `descriptionHtml` keeps KKday's HTML where it uses any. On many products it's identical to `description`. Sometimes the description is a short summary and the longer text is in `subtitle`, as it is here.

Two more row types exist. A related-products row (`dataType: "related"`, id `<productId>-related`) has `relatedCount` and a `related` list, where each entry gives the product id, name, link, rating, review count, booking wording, image and tags. A search row (`dataType: "searchResult"`) uses the same names where they overlap and adds `query`, `rank`, `totalResults`, `sort`, `discountPct`, `supplierName`, `orderCountText` and `recommendTags`, together with these:

| Search-row column | Meaning |
|---|---|
| `productOid` | KKday's second, internal product number |
| `discountType` | KKday's code for the kind of discount, null when none |
| `isPriceShown`, `isFree` | False when KKday hides the price on the listing. True for a zero-price product |
| `destinationCodes`, `subCategoryCodes` | KKday's codes behind `destinations` and the sub-categories |
| `supplierLogo`, `supplierBadge` | Marketplace sellers only, else null |
| `isBestRoute`, `purchaseType` | KKday's "best route" mark and its purchase-type code |
| `saleStatus` | KKday's numeric sale status. 1 means on sale, which is what `isOnSale` reports |

### How much does it cost, and how long does it take?

| Event | Free plan | Starter | Scale | Business |
|---|---|---|---|---|
| `actor-start`, per run | $0.002 | $0.002 | $0.002 | $0.002 |
| `product-checked`, per product KKday answered as not existing (the row says so), instead of `product-scraped` | $0.0005 | $0.0005 | $0.0005 | $0.0005 |
| `product-scraped`, per product | $0.003 | $0.0027 | $0.0024 | $0.0021 |
| `search-result`, per search row | $0.002 | $0.0018 | $0.0016 | $0.0014 |
| `product-related`, per product whose related list is returned (one row holding the whole list), only when that option is on | $0.002 | $0.0018 | $0.0016 | $0.0014 |

Enterprise plans pay the Business price.

**$3.00 per 1,000 products** on the Free plan, $2.10 on Business. You don't pay for proxy usage or platform usage separately. A product KKday says doesn't exist costs $0.0005, and one that couldn't be reached is free.

- Fifty products: $0.002 + 50 × $0.003 = **$0.152** ($0.107 on Business).
- The same fifty with related products: $0.002 + 50 × $0.003 + 50 × $0.002 = **$0.252** ($0.177 on Business).

With the $5 of credits Apify's Free plan gives you each month, that's about 1,640 products.

Timing, for whole runs on Apify measured on 2 and 3 October 2026:

| Run | Rows | Time | Price on the Free plan |
|---|---|---|---|
| One product | 1 | 7.2 s | $0.005 |
| Five products with supplier, categories and related products | 5 + 4 related | 12.1 to 17.4 s | $0.025 |
| Forty products, default options | 40 | 73 s | $0.122 |

That works out at about 33 products a minute, or roughly 2,000 in a one-hour run. Rows are saved as they arrive, so a run that reaches its time limit keeps what it collected. For a longer list, raise the timeout or split it.

### FAQ

#### Do I need proxies or a KKday account?

There's nothing to bring. The actor reads public product data, and proxy usage is part of the per-product price.

#### Should I search here or use KKday Search Scraper?

Search here when you want full records for a handful of keywords in one run. Use the search actor when the list itself is the product: it has KKday's own filters (categories, dates, price, instant confirmation), nine languages and an only-new mode. The listing rows cost the same in both.

#### How do I get the price for a particular date?

You don't get it from this actor. `priceFrom` and `priceTo` are the range across packages. Take the `packageId` and `itemIds` from the record and pass them to KKday Product Availability & Prices, which returns each date and time slot with its own price.

#### Why is `supplier` empty?

KKday sells most products itself, and those have no supplier. On marketplace products the block has come back with the supplier id only: name, rating and product count were empty on every run we've measured. If you need the seller's name, search rows carry it as `supplierName`.

#### Can I track bookings over time?

`orderCount` is KKday's running total for the product. Schedule the same list weekly and the difference between two runs is a fair demand signal. `wishlistCount` moves the same way.

#### What happens with a link to a product that's gone?

You get a row that says KKday has nothing at that address and what to check. It's billed the $0.0005 `product-checked` fee where a full record would cost $0.003. If KKday simply didn't answer, the row says so and costs nothing.

#### What isn't in the record?

- Dated prices and time slots. Packages come with names and ids only.
- The reviews themselves. You get the count, the star spread and KKday's summary.
- A supplier name on the product row (see above).
- A list price on many products. KKday publishes one for some only.
- The full record on search rows, unless "Read full details for search hits" is on.

#### Is it legal to scrape KKday?

The actor reads only what KKday serves to any visitor without logging in, and product records hold no personal data. Scraping public data is generally lawful. How you use it, and KKday's terms, are yours to respect.

### Keep a catalogue current

Most people who run this keep a product list fresh: a weekly schedule over a fixed set of links, with the records written to a database or a Google Sheet through Apify's integrations. From code, `POST https://api.apify.com/v2/acts/boncross~kkday-product-details/run-sync-get-dataset-items` with the input as the body returns the records in the response. An AI agent can call it as the tool `boncross/kkday-product-details` through the Apify MCP server at `mcp.apify.com`, which is handy for questions like "which Seoul shows on KKday have more than 5,000 reviews?".

### More from BonCross

- [KKday Product Availability & Prices](https://apify.com/boncross/kkday-availability): KKday availability and prices for any product.
- [KKday Product Reviews Scraper](https://apify.com/boncross/kkday-reviews): KKday reviews for any product.
- [Klook Activity Details Scraper](https://apify.com/boncross/klook-activity-details): Full Klook activity records.
- [Klook Activity Availability & Prices](https://apify.com/boncross/klook-availability): Klook availability and prices.
- [Klook Activity Reviews Scraper](https://apify.com/boncross/klook-reviews): Every review Klook shows for an activity.
- [Trip.com Attraction Reviews Scraper](https://apify.com/boncross/tripcom-reviews): Trip.com reviews for any attraction.

### Your feedback

If a record is missing something you can see on the KKday page, we'd like to know. Post it on the Issues tab in Apify Console with the product link, and we'll reply there.

# Changelog

This Actor's version history is a separate document: https://apify.com/boncross/kkday-product-details/changelog.md

# Actor input Schema

## `products` (type: `array`):

KKday product URLs such as https://www.kkday.com/en/product/2358-... , product slugs, or bare product numbers. Leave empty if you are searching by keyword instead.

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

Search KKday by keyword or destination, for example "bangkok" or "seoul day tour". Each hit is returned as a product row. Use this instead of, or as well as, product links.

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

KKday page addresses, with the option to load them in bulk from a file, a Google Sheet or a remote list. Use this when you have more links than you want to paste. Combined with anything in the list above.

## `maxResultsPerQuery` (type: `integer`):

Stop after this many hits for each keyword. 0 means every hit KKday returns.

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

A run-wide ceiling across every target. The per-target limit above applies to each one separately, so ten targets at 50 each returns 500; set this to cap the total. Zero means no run-wide limit. Rows that report an input the actor could not resolve are not counted here and are never charged for.

## `searchSort` (type: `string`):

Order the search hits come back in.

## `detailSearchResults` (type: `boolean`):

Also run the full product read on every search hit. Costs one product charge per hit on top of the search charge.

## `includeSummary` (type: `boolean`):

Add the rating, review count, sentiment tags and the written summary of what reviewers say.

## `includeSupplier` (type: `boolean`):

Add the supplier block on marketplace products. So far it has carried the supplier id only: name, rating and product count have come back empty.

## `includeCategories` (type: `boolean`):

Add the destination name and the categories the product is listed under.

## `includeRelated` (type: `boolean`):

Add a row per product listing the products KKday shows alongside it, with their ratings and prices. Charged separately.

## `currency` (type: `string`):

ISO currency code. Prices come back quoted in it. Default USD.

## `includeRawData` (type: `boolean`):

Attach the unparsed product record to each row.

## `delayMs` (type: `integer`):

Pause between calls.

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

How many requests run at once, each one paced by the delay above. The default is the fastest level measured clean; lower it only if a run reports refusals or errors.

## Actor input object example

```json
{
  "products": [
    "https://www.kkday.com/en/product/2358-nanta-show-tickets-in-seoul"
  ],
  "searchQueries": [],
  "startUrls": [],
  "maxResultsPerQuery": 60,
  "maxItems": 0,
  "searchSort": "relevance",
  "detailSearchResults": false,
  "includeSummary": true,
  "includeSupplier": true,
  "includeCategories": true,
  "includeRelated": false,
  "currency": "USD",
  "includeRawData": false,
  "delayMs": 900,
  "maxConcurrency": 4
}
```

# Actor output Schema

## `dataset` (type: `string`):

KKday product details: every row the run returned.

## `stats` (type: `string`):

Counts for the run: what was resolved, fetched, filtered and returned.

# 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 = {
    "products": [
        "https://www.kkday.com/en/product/2358-nanta-show-tickets-in-seoul"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("boncross/kkday-product-details").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 = { "products": ["https://www.kkday.com/en/product/2358-nanta-show-tickets-in-seoul"] }

# Run the Actor and wait for it to finish
run = client.actor("boncross/kkday-product-details").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 '{
  "products": [
    "https://www.kkday.com/en/product/2358-nanta-show-tickets-in-seoul"
  ]
}' |
apify call boncross/kkday-product-details --silent --output-dataset

```

## MCP server setup

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

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/s3InrdvNimZhUVR7w/builds/pxucC2gFNvWTTy1OV/openapi.json
