# KKday Reviews Scraper (`solidcode/kkday-reviews-scraper`) Actor

\[💰 $2.50 / 1K] Extract KKday reviews at scale — star ratings, full review text, reviewer details, travel and post dates, review photos, and translation into 15+ languages. Paste product URLs to collect structured review data for market research, sentiment analysis, and competitor monitoring.

- **URL**: https://apify.com/solidcode/kkday-reviews-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** Travel, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 results

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

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

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

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

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

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

# README

## KKday Reviews Scraper

Pull customer reviews from KKday product pages at scale — star ratings, full review text, machine translations, traveller-type tags, trip photos, helpful-vote counts, and two separate dates per review. Built for travel operators, OTA analysts, and experience marketplaces who need structured guest feedback from tours, attraction tickets, and day trips without copying reviews off product pages one page at a time.

### Why This Scraper?

- **Up to ~750 unique reviews per product** — KKday shows at most 150 reviews in any one ordering. This actor sweeps up to five orderings and de-duplicates on review ID to lift that ceiling to roughly 750 unique reviews per product. Measured at 407 unique reviews with zero duplicates on a single product.
- **Original text *and* translation in 16 locales** — English (US, Australia, Singapore, Malaysia, Philippines, New Zealand, Indonesia, Hong Kong), Chinese (Traditional, Simplified, Hong Kong, Malaysia), Japanese, Korean, Thai, and Vietnamese. The original wording is always kept alongside the translated version, so nothing is lost.
- **Two distinct dates on every review** — `travelDate` (when the trip actually happened) and `postDate` (when the review was written). Analyse seasonality by trip month and review lag separately instead of guessing from a single timestamp.
- **Five traveller-type segments** — every review is tagged Couple, Family, Friend, Solo traveler, or Business traveler, decoded into readable labels rather than raw internal codes.
- **Four sort orders, including the 1-star tail** — newest first, most helpful, highest rating, or lowest rating. Pull negative reviews directly for complaint triage instead of paging past hundreds of 5-star entries.
- **Customer trip photos as direct image URLs** — roughly 4 in 10 reviews on a busy product carry at least one guest-uploaded photo, delivered as a ready-to-use URL list.
- **Helpful-vote counts on every row** — see which reviews other travellers actually endorsed, so you can weight sentiment by community signal instead of treating all reviews equally.
- **Date-bounded incremental collection** — set `reviewsStartDate` to a YYYY-MM-DD day and only reviews posted on or after it are collected, with older pages skipped early. Perfect for a daily or weekly top-up run.
- **Product URLs or bare product IDs** — paste a full `kkday.com/en-us/product/...` link or just `2312`. Repeated products inside one run are collapsed automatically, so you never pay twice for the same review.

### Use Cases

**Market & Competitor Research**

- Benchmark rating distributions across competing tours in the same city
- Track how a competitor's average rating moves after a price or itinerary change
- Compare the same attraction sold by different operators
- Size demand by counting review volume per travel month

**Sentiment & Voice-of-Customer Analysis**

- Feed review text into sentiment or topic models with the original language preserved
- Isolate 1- and 2-star reviews to build a ranked complaint taxonomy
- Compare sentiment between Couple, Family, Solo, Friend, and Business travellers
- Weight themes by helpful-vote count to find the complaints that resonate

**Product & Operations**

- Spot recurring issues with meeting points, wait times, or ticket redemption
- Correlate `travelDate` with rating to find weak seasons or specific bad weeks
- Track whether a fix to an itinerary shows up in reviews written afterward
- Audit guide or venue performance from named, dated guest feedback

**Content & Marketing**

- Source authentic testimonials with reviewer name, rating, and trip date
- Pull guest photo URLs for user-generated-content campaigns
- Build "what travellers say" modules for landing pages
- Localise social proof using the translated text for each target market

**Data Integration & Monitoring**

- Run daily with a start date to append only new reviews to your warehouse
- Push review rows into BI dashboards for rolling rating trends
- Trigger alerts when a product starts collecting low ratings
- Enrich an internal product catalogue with live guest feedback

### Getting Started

#### Simplest run — one product

```json
{
  "startUrls": ["https://www.kkday.com/en-us/product/2312-universal-studios-singapore-ticket"]
}
```

#### Several products by ID, capped

```json
{
  "startUrls": ["2312", "3158", "30000"],
  "maxReviewsPerProduct": 50
}
```

#### Deep sweep with translation into Japanese

```json
{
  "startUrls": ["https://www.kkday.com/en-us/product/2312-universal-studios-singapore-ticket"],
  "maxReviewsPerProduct": 0,
  "language": "ja"
}
```

#### Complaint triage, incremental since a date

```json
{
  "startUrls": [
    "https://www.kkday.com/en-us/product/2312-universal-studios-singapore-ticket",
    "https://www.kkday.com/en-us/product/3158-tokyo-disneyland-ticket"
  ],
  "maxReviewsPerProduct": 300,
  "sortBy": "RATING_ASC",
  "language": "en-us",
  "reviewsStartDate": "2026-01-01"
}
```

### Input Reference

#### Products

| Parameter | Type | Prefilled with | Description |
|-----------|------|----------------|-------------|
| `startUrls` | array | `["https://www.kkday.com/en-us/product/2312-universal-studios-singapore-ticket"]` | KKday product page URLs to collect reviews from. Add as many products as you like. A bare product ID (like `2312`) also works. |

#### Options

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxReviewsPerProduct` | integer | `100` | Maximum reviews per product, applied on every run including date-filtered ones. Set to `0` to collect as many as possible. KKday serves at most 150 reviews per sort order; above 150 several sort orders are combined and only unique reviews are kept, reaching up to about 750 per product. |
| `sortBy` | string | `"POSTDATE_DESC"` | The order reviews are collected in: `POSTDATE_DESC` (Newest first), `HELPFUL_DESC` (Most helpful), `RATING_DESC` (Highest rating), `RATING_ASC` (Lowest rating). |
| `language` | string | `"en-us"` | Reviews are translated into this language when the original is written in another one. The original text is always kept too. Choose from `en-us`, `en-au`, `en-sg`, `en-my`, `en-ph`, `en-nz`, `en-id`, `en-hk`, `zh-tw`, `zh-hk`, `zh-cn`, `zh-my`, `ja`, `ko`, `th`, `vi`. |
| `reviewsStartDate` | string | *(empty)* | Only collect reviews posted on or after this date, in `YYYY-MM-DD` form (for example `2024-01-15`). Dates follow KKday's own local time. Reviews are collected newest-first so older ones are skipped early, and if more than 150 fall inside your range several sort orders are combined to reach further back. Your maximum per product still applies. Leave empty to go back through the full review history. |

### Output

One row per review, with the product context attached to every row.

```json
{
  "productUrl": "https://www.kkday.com/en-us/product/2312-universal-studios-singapore-ticket",
  "productId": "2312",
  "productName": "Universal Studios Singapore Ticket",
  "reviewId": "4341740",
  "rating": 5,
  "title": "最高の一日でした",
  "translatedTitle": "It was the best day",
  "text": "スタッフの対応がとても丁寧で、チケットの引き換えもスムーズでした。子ども連れでも安心して回れました。",
  "translatedText": "The staff were very polite and ticket redemption was smooth. It was easy to get around even with children.",
  "needTranslate": true,
  "reviewerName": "Yuki T.",
  "travellerType": "Family",
  "reviewerAvatar": "https://image.kkday.com/image/get/member/avatar_9f21c4.jpg",
  "helpfulCount": 3,
  "images": [
    "https://image.kkday.com/image/get/comment/4341740_01.jpg",
    "https://image.kkday.com/image/get/comment/4341740_02.jpg"
  ],
  "travelDate": "2026-07-28",
  "postDate": "2026-08-06 21:23:03"
}
```

#### Product Context

| Field | Type | Description |
|-------|------|-------------|
| `productUrl` | string | Canonical KKday product page the review belongs to |
| `productId` | string | KKday product ID, taken from the URL or your bare-ID input |
| `productName` | string | Product title, derived from the product URL. Absent when the input was a bare ID |

#### Review Content

| Field | Type | Description |
|-------|------|-------------|
| `reviewId` | string | Unique KKday review ID — use it as your de-duplication key across runs |
| `rating` | number | Star rating the traveller gave, 1 to 5 |
| `title` | string | Review headline in the language the traveller wrote it |
| `text` | string | Full review body in the original language |
| `translatedTitle` | string | Headline translated into your chosen language |
| `translatedText` | string | Review body translated into your chosen language |
| `needTranslate` | boolean | `true` when the original differs from your chosen language and a translation was produced |
| `images` | array | URLs of photos the traveller attached to the review. Absent when no photos were uploaded |

#### Reviewer

| Field | Type | Description |
|-------|------|-------------|
| `reviewerName` | string | Display name the traveller posts under |
| `travellerType` | string | Who they travelled with: `Couple`, `Family`, `Friend`, `Solo traveler`, or `Business traveler` |
| `reviewerAvatar` | string | URL of the reviewer's profile picture |

#### Dates & Engagement

| Field | Type | Description |
|-------|------|-------------|
| `travelDate` | string | Date the traveller actually took the trip (`YYYY-MM-DD`) |
| `postDate` | string | Date and time the review was published (`YYYY-MM-DD HH:MM:SS`) |
| `helpfulCount` | number | How many other travellers marked this review as helpful |

Empty fields are removed before the row is saved, so your dataset stays clean.

### Tips for Best Results

- **Start with 20–50 reviews per product** on your first run to confirm the shape of the data, then raise the cap once you're happy.
- **Go above 150 to unlock the deep sweep** — KKday caps any single ordering at 150 reviews. Set `maxReviewsPerProduct` to `200`+ (or `0` for everything available) and several orderings are combined and de-duplicated, reaching roughly 750 unique reviews. Staying at 150 or below keeps runs fastest and cheapest.
- **Use `reviewsStartDate` for daily top-ups** — set it to the date of your last run and you'll collect only what's new, instead of re-downloading and re-paying for reviews you already have. Keep `maxReviewsPerProduct` set as a safety net: it is enforced on date-filtered runs too, so a product with an unexpectedly busy week can never quietly multiply your bill.
- **Translate a mixed-language review base** — KKday's reviews are heavily Chinese, Japanese, and Korean. Set `language` to `en-us` and every non-English review comes back with an English version next to the original, ready for sentiment analysis in one language.
- **Sort by `RATING_ASC` for complaint work** — it puts the 1-star reviews first, so a 50-review run captures the entire negative tail instead of a random sample of praise.
- **Paste full product URLs when you want `productName`** — the product title comes from the URL. Bare IDs still work and return every review, they just arrive without the product name attached.
- **Pair `travelDate` with `rating`** to find seasonal weak spots — a tour that averages 4.8 in spring and 4.1 in peak summer usually has a crowding or heat problem, which the review text will confirm.

### Pricing

**From $2.50 per 1,000 results** — pay only for the reviews you actually collect. Bronze, Silver, and Gold subscribers pay progressively less; the table below shows the total cost at each discount tier.

| Results | No discount | Bronze | Silver | Gold |
|---------|-------------|--------|--------|------|
| 100 | $0.30 | $0.29 | $0.27 | $0.25 |
| 1,000 | $3.00 | $2.85 | $2.65 | $2.50 |
| 10,000 | $30.00 | $28.50 | $26.50 | $25.00 |
| 100,000 | $300.00 | $285.00 | $265.00 | $250.00 |

A "result" is one review row in the output dataset. No compute or time-based charges — you pay per result, plus a small fixed per-run start fee.

### Integrations

Export data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

- **Zapier** / **Make** / **n8n** — Workflow automation
- **Google Sheets** — Direct spreadsheet export
- **Slack** / **Email** — Notifications on new results
- **Webhooks** — Trigger your own services when a run finishes
- **Apify API** — Full programmatic access

### Legal & Ethical Use

This actor is intended for legitimate travel market research, product quality analysis, and voice-of-customer work on publicly visible KKday review content. You are responsible for complying with applicable laws, including data protection rules such as GDPR, and with KKday's Terms of Service. Reviewer display names and avatars are personal data — store them only as long as you need them, and never use collected data for spam, harassment, profiling of individuals, or any unlawful purpose.

# Actor input Schema

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

KKday product page URLs to collect reviews from, for example https://www.kkday.com/en-us/product/2312-universal-studios-singapore-ticket. You can add as many products as you like. A bare product ID (like 2312) also works.

## `maxReviewsPerProduct` (type: `integer`):

Maximum number of reviews to collect for each product. Set to 0 to collect as many as possible. This limit always applies, including when a start date is set. KKday serves at most 150 reviews per sort order; to go beyond 150 we automatically combine several sort orders and keep only unique reviews, reaching up to about 750 per product. A lower limit keeps runs fast and affordable.

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

The order in which reviews are collected.

## `language` (type: `string`):

Reviews are translated into this language when the original is written in a different one. The original review text is always kept as well.

## `reviewsStartDate` (type: `string`):

Only collect reviews posted on or after this date, using the format YYYY-MM-DD (for example 2024-01-15). Dates follow KKday's own local time. When set, reviews are collected newest-first so older ones are skipped early; if more than 150 reviews fall inside your date range, several sort orders are automatically combined to reach further back. Your maximum per product still applies. Leave empty to collect all reviews.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.kkday.com/en-us/product/2312-universal-studios-singapore-ticket"
  ],
  "maxReviewsPerProduct": 100,
  "sortBy": "POSTDATE_DESC",
  "language": "en-us"
}
```

# Actor output Schema

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

All collected reviews with the key fields — product, rating, text, translation, and dates.

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

Every field on every review — original and translated text, reviewer profile, photo URLs, helpful votes, and both dates.

# 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 = {
    "startUrls": [
        "https://www.kkday.com/en-us/product/2312-universal-studios-singapore-ticket"
    ],
    "maxReviewsPerProduct": 100,
    "sortBy": "POSTDATE_DESC",
    "language": "en-us"
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/kkday-reviews-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 = {
    "startUrls": ["https://www.kkday.com/en-us/product/2312-universal-studios-singapore-ticket"],
    "maxReviewsPerProduct": 100,
    "sortBy": "POSTDATE_DESC",
    "language": "en-us",
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/kkday-reviews-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 '{
  "startUrls": [
    "https://www.kkday.com/en-us/product/2312-universal-studios-singapore-ticket"
  ],
  "maxReviewsPerProduct": 100,
  "sortBy": "POSTDATE_DESC",
  "language": "en-us"
}' |
apify call solidcode/kkday-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,solidcode/kkday-reviews-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/wGhW2jSSCAUFP467O/builds/Sla1FYgDXJWeLCIXE/openapi.json
