# Hwahae Scraper — K-Beauty Rankings, Ratings & Prices (화해) (`kdatafactory/hwahae-scraper`) Actor

Scrape K-beauty product rankings from Hwahae (화해), Korea's #1 cosmetics review app: name, brand, category, rank, star rating, review count, USD price and review-topic keywords as clean JSON. Global English data, no personal data collected. For K-beauty market research, trend tracking & pricing.

- **URL**: https://apify.com/kdatafactory/hwahae-scraper.md
- **Developed by:** [Seok June Park](https://apify.com/kdatafactory) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

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

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

## What's an Apify Actor?

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

## How to integrate an Actor?

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

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

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

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

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

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

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

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

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

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

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


# README

## Hwahae Scraper — K-Beauty Rankings, Ratings & Prices

Scrape **Korean beauty product rankings from [Hwahae](https://www.hwahae.com/en/rankings) (화해)** — Korea's #1 cosmetics review app, built on 10M+ real user reviews. Point it at Hwahae's global English rankings and get back clean, structured JSON for every ranked product: name, brand, category, rank, **star rating**, **review count**, **USD price**, discount rate, and review-topic keywords.

Hwahae is *the* K-beauty consumer authority in Korea — its rankings reflect what Korean users actually rate highest, a review-driven signal distinct from what a store is merely pushing. If you need to know which K-beauty products are winning in Korea right now, this is the source, in English and USD.

> **Try it free.** Apify's free plan includes $5 of monthly platform credit — roughly **2,500 results** from this actor, no credit card required. Set your input, click Start, and export JSON/CSV/Excel.

> **Privacy-first.** No personal data is ever collected — no reviewer names, IDs, or profiles. Product, brand, ranking, rating, and price data only.

---

### What it does

- Reads Hwahae's public, server-rendered **global rankings** (English) — works from most IPs, including datacenter.
- Extracts each ranked product from the page's embedded `__NEXT_DATA__` blob.
- Emits one clean record per product against a stable schema.

### Input

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `categoryThemeIds` | string[] | `["5102"]` | Hwahae ranking category `theme_id`s. Empty = default "All Categories" trending list. E.g. `5102` All Categories, `5103` Skincare, `5177` Cleansers, `5296` Suncare, `5338` Face Makeup. |
| `maxProducts` | integer | `40` | Max products to scrape across all requested rankings. |
| `proxyConfiguration` | object | RESIDENTIAL | Proxy settings (optional for ranking data). |

#### Input example

```json
{
  "categoryThemeIds": ["5102", "5103"],
  "maxProducts": 40
}
````

### Output

One dataset item per product. This is **real output** from a live run of the global rankings (see `samples/sample-output.json` for 39 real records):

```json
{
  "source": "hwahae",
  "product_id": "1918760",
  "name": "MUNG BEAN pH-BALANCED CLEANSING FOAM",
  "brand": "beplain",
  "category": "All Categories",
  "rank": 1,
  "rating": 4.63,
  "review_count": 49461,
  "price_usd": 9.96,
  "currency": "USD",
  "capacity": "80mL ≈ 2.71 fl. oz.",
  "discount_rate": 40,
  "keywords": ["알갱이있는", "각질제거잘되는", "미끌거리지않는"],
  "url": "https://www.hwahae.com/en/products/MUNG-BEAN-pH-BALANCED-CLEANSING-FOAM/1918760",
  "image_url": "https://img.hwahae.co.kr/products/1918760/1918760_20230628115919.jpg",
  "scraped_at": "2026-07-09T12:00:00+09:00"
}
```

#### Field notes

- `product_id` — Hwahae's stable product identifier.
- `price_usd` / `currency` — Hwahae's live exchange-rate price for the global store (USD). `discount_rate` is the current percent discount when present.
- `rating` — 1–5 star average from real Hwahae reviews; `review_count` is the number of reviews behind it. Together these are the core "what Korea actually rates highly" signal.
- `keywords` — Hwahae's top review "topics" for the product (the aspects reviewers mention most), as native Korean topic labels — a compact, ready-made input for aspect/sentiment analysis.
- `rank` — 1-based position within its ranking list.

### Use cases

- **Market research for K-beauty market entry** — pull the current top-rated products by category with real ratings, review counts, USD prices and review-topic keywords before launching a competing SKU.
- **Trend tracking** — snapshot the rankings on a schedule to see what's rising and falling in Korean consumer favor over time.
- **Pricing & dropshipping** — track top K-beauty products, their USD price and discount rate.
- **Aspect/sentiment signal** — thousands of privacy-clean review-topic keywords feed straight into an NLP/LLM pipeline. No PII to scrub.

### Proxy & rate limits

The ranking data — the product this actor sells — reads from Hwahae's server-rendered `__NEXT_DATA__` and works from **most IPs, including datacenter** (the 39-record sample here was produced with **no proxy**). A residential proxy is only worth enabling for high-volume runs. The actor runs politely: effectively concurrency 1 with ≥600 ms between requests, and if a proxy tunnel hangs it retries directly so a bad tunnel never hangs the run.

> **Note on category coverage.** Only "All Categories" trending views embed their product list in server-rendered HTML; narrow leaf-category rankings load client-side and aren't in the SSR blob. The actor scrapes every ranking view that embeds products and skips the rest.

### Known limitation — ingredients & review text (not currently available)

Hwahae's flagship **ingredient lists** and full **review text** live only on product **detail pages** (`hwahae.com/en/products/<slug>/<id>`), which are protected by a JavaScript bot-challenge that returns `HTTP 202` with an empty body — **even through residential proxies** (verified). There is an experimental `includeIngredients` input, but it is **off by default and normally returns empty** ingredient/review fields; the actor falls back to the ranking record. Delivering ingredient/review-text data reliably would require full browser automation to clear the challenge — a possible future enhancement, not a current feature. **This actor is sold on its ranking, rating, review-count and price data, which are reliable.**

### Legality & data ethics

- Only **public** ranking data is collected — no login, no private endpoints.
- **No personal data.** Reviewer names, IDs, and profiles are never read or stored.
- You are responsible for using the output in compliance with Hwahae's terms and applicable law. Because no personal data is emitted, output is safe to feed directly into analytics and LLM pipelines.

### ❓ FAQ

**Is it legal to scrape this data?**
This actor collects only public, non-personal ranking data — the same rankings any visitor sees on Hwahae's global site without logging in. No personal data is collected (no reviewer names, IDs, or profiles). You are responsible for how you use the data; see the legality note above.

**What does it cost in practice?**
$2.00 per 1,000 results (launch pricing) + a few cents of platform usage. Example: a 500-result daily pull costs about $1.00/day. Apify's free $5 monthly credit covers ~2,500 results.

**Do I need to configure proxies?**
No — the default settings work out of the box, and the ranking data works from most IPs, including datacenter. Optionally, enable a residential proxy for high-volume runs.

**How fresh is the data?**
Every run scrapes the live site at run time. Schedule the actor for recurring snapshots.

**What is NOT included?**
Ingredient lists and full review text are not currently available — they live on bot-challenge-protected detail pages (see the known limitation above). Also, only ranking views that embed products in server-rendered HTML are scraped; narrow leaf-category rankings that load client-side are skipped.

### 🇰🇷 More Korean data actors

This actor is part of a suite of Korean-platform scrapers by the same maintainer:

- [oliveyoung-scraper](https://apify.com/kdatafactory/oliveyoung-scraper) — Olive Young K-beauty bestsellers, prices and reviews.
- [glowpick-scraper](https://apify.com/kdatafactory/glowpick-scraper) — Glowpick Korean cosmetics award rankings and ratings.

Browse all: [apify.com/kdatafactory](https://apify.com/kdatafactory)

### Local development

```bash
npm install
## put input in ./storage/key_value_stores/default/INPUT.json, then:
npm start   # results land in ./storage/datasets/default

## polite lite test against the live site (<=2 pages, ~40 products):
HWAHAE_SCRAPER_LITE_TEST=1 npm start
```

***

*If this actor saves you time, a rating on the [Store page](https://apify.com/kdatafactory/hwahae-scraper) helps a solo maintainer a lot. Found an issue? Open it in the Issues tab — I respond fast.*

# Actor input Schema

## `categoryThemeIds` (type: `array`):

Hwahae ranking category theme IDs to scrape (the `theme_id` used on hwahae.com/en/rankings). Leave empty to scrape the default global "All Categories" trending ranking. Example top-level IDs: 5102 (All Categories), 5103 (Skincare), 5177 (Cleansers), 5296 (Suncare), 5338 (Face Makeup). Each theme yields up to 20 ranked products embedded in the page.

## `maxProducts` (type: `integer`):

Maximum number of ranked products to scrape across all requested rankings.

## `includeIngredients` (type: `boolean`):

EXPERIMENTAL / usually unavailable. Attempts to enrich each product from its detail page with ingredients and review text. Hwahae's detail pages are protected by a JS bot-challenge that returns HTTP 202 (empty) even through residential proxies, so these fields normally come back empty and the actor falls back to the ranking record. Leave OFF for fast, reliable ranking data. Reviewer identity is never collected.

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

Maximum number of reviews to collect per product (only used when Include ingredients & reviews is on).

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

Hwahae bot-gates product detail pages (ingredients + reviews) on datacenter IPs (HTTP 202 / empty body). RESIDENTIAL proxies (Apify Proxy, group RESIDENTIAL) are strongly recommended for detail-page enrichment. The ranking lists themselves are readable from most IPs.

## Actor input object example

```json
{
  "categoryThemeIds": [
    "5102",
    "5103"
  ],
  "maxProducts": 40,
  "includeIngredients": false,
  "maxReviewsPerProduct": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "categoryThemeIds": [
        "5102"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("kdatafactory/hwahae-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 = { "categoryThemeIds": ["5102"] }

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

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

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

```

## CLI example

```bash
echo '{
  "categoryThemeIds": [
    "5102"
  ]
}' |
apify call kdatafactory/hwahae-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Hwahae Scraper — K-Beauty Rankings, Ratings & Prices (화해)",
        "description": "Scrape K-beauty product rankings from Hwahae (화해), Korea's #1 cosmetics review app: name, brand, category, rank, star rating, review count, USD price and review-topic keywords as clean JSON. Global English data, no personal data collected. For K-beauty market research, trend tracking & pricing.",
        "version": "0.1",
        "x-build-id": "YAfpG75oqsZRDR21o"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/kdatafactory~hwahae-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-kdatafactory-hwahae-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/kdatafactory~hwahae-scraper/runs": {
            "post": {
                "operationId": "runs-sync-kdatafactory-hwahae-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/kdatafactory~hwahae-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-kdatafactory-hwahae-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "categoryThemeIds": {
                        "title": "Category theme IDs",
                        "type": "array",
                        "description": "Hwahae ranking category theme IDs to scrape (the `theme_id` used on hwahae.com/en/rankings). Leave empty to scrape the default global \"All Categories\" trending ranking. Example top-level IDs: 5102 (All Categories), 5103 (Skincare), 5177 (Cleansers), 5296 (Suncare), 5338 (Face Makeup). Each theme yields up to 20 ranked products embedded in the page.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxProducts": {
                        "title": "Max products",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Maximum number of ranked products to scrape across all requested rankings.",
                        "default": 40
                    },
                    "includeIngredients": {
                        "title": "Attempt ingredient/review enrichment (experimental)",
                        "type": "boolean",
                        "description": "EXPERIMENTAL / usually unavailable. Attempts to enrich each product from its detail page with ingredients and review text. Hwahae's detail pages are protected by a JS bot-challenge that returns HTTP 202 (empty) even through residential proxies, so these fields normally come back empty and the actor falls back to the ranking record. Leave OFF for fast, reliable ranking data. Reviewer identity is never collected.",
                        "default": false
                    },
                    "maxReviewsPerProduct": {
                        "title": "Max reviews per product",
                        "minimum": 0,
                        "maximum": 200,
                        "type": "integer",
                        "description": "Maximum number of reviews to collect per product (only used when Include ingredients & reviews is on).",
                        "default": 20
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Hwahae bot-gates product detail pages (ingredients + reviews) on datacenter IPs (HTTP 202 / empty body). RESIDENTIAL proxies (Apify Proxy, group RESIDENTIAL) are strongly recommended for detail-page enrichment. The ranking lists themselves are readable from most IPs.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
