# YesStyle Scraper - K-Beauty, Fashion, Prices & Reviews (`abotapi/yesstyle-com-scraper`) Actor

Scrape YesStyle products by keyword or URL. Extract prices, discounts, ratings, stock, images, categories, variants and customer reviews across K-beauty, fashion and lifestyle. Incremental mode tracks daily changes.

- **URL**: https://apify.com/abotapi/yesstyle-com-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Features:** Limited permissions
- **Stats:** 12 total users, 9 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

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

## YesStyle Scraper: K-Beauty, Fashion & Lifestyle Products + Reviews

YesStyle Scraper turns the YesStyle store into structured product and review data. Search by keyword or paste product, brand, category or search links, and get each product's price, discount, rating, review count, stock status, images and category trail, plus the store's own customer reviews. Export to JSON, CSV or Excel, or read the results straight through the API. Incremental mode tracks what changed since your last run.

### Why This Scraper?

- **Two ways in.** Run keywords through the store's own search, or paste product, brand, category and search links for a fixed catalogue.
- **75+ fields per product.** Price in local currency and USD, original price, discount, rating to two decimals, review count, brand id, variant and variant family, bestseller rank, awards, sale status, every active promotion, origin country, plus where the row came from and its rank in those results.
- **Full product pages.** Every gallery image at full size, the complete product details (size, benefits, how to use), ingredients, the rating breakdown by star, bestseller ranks per category, brand profile and satisfaction score, bundle offers, catalog number, delivery estimate and the category trail with ids.
- **Customer reviews attached.** Each product can carry its reviews as a nested list: title, rating, text, date, reviewer, helpful-vote counts, review images with thumbnails and the exact variant reviewed, sorted and filtered the way you choose.
- **Regional storefronts.** The connection's exit country decides which YesStyle storefront and currency a run reads (US by default).
- **Built for schedules.** Incremental mode returns only new, changed, reappeared or expired products on later runs, with the changed fields named on each row.

### Use Cases

- **Price and discount monitoring:** schedule a daily run over your brands or keywords and let incremental mode return only what changed.
- **Review mining:** pull ratings, review text, dates and helpful-vote counts for sentiment analysis or competitor research.
- **Catalogue feeds:** build a structured feed of a brand's or category's listings with full image galleries, ingredients, product details and category trails.
- **Stock, ranking and launch tracking:** watch availability, bestseller ranks and search positions, and catch new arrivals as they enter the results.

### Data You Get

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

| Field | Example |
| --- | --- |
| `productId` | `"1000000001"` |
| `url` | `"https://www.yesstyle.com/en/sample-sheet-mask/info.html/pid.1000000001"` |
| `name` | `"Sample Hydrating Sheet Mask"` |
| `brand` / `brandId` | `"Sample Brand"` / `300001` |
| `variant` | `"25ml"` |
| `price` / `currency` | `12.34` / `"USD"` |
| `originalPrice` / `discountPercent` | `18.0` / `31` |
| `priceUsd` | `12.34` |
| `rating` / `reviewCount` | `4.82` / `1000` |
| `ratingBreakdown` | `{"5": 800, "4": 150, "3": 30, "2": 10, "1": 10}` |
| `bestsellerRank` | `2` |
| `promotions` | `["limitedDeal", "highDiscount"]` |
| `itemStatus` | `"FLASH SALE"` |
| `images` | main shot plus every gallery image at full size (detail enrichment) |
| `productDescription` | `"Full product description appears here when detail enrichment is on."` |
| `productDetails` | size, benefits, types and how to use, as text (detail enrichment) |
| `ingredients` | `"Water, Glycerin, Niacinamide, ..."` (detail enrichment) |
| `brandOrigin` | `"South Korea"` (detail enrichment) |
| `bestsellerRanks` | `[{"rank": 2, "category": "Face Masks", "categoryId": 15561}]` (detail enrichment) |
| `variantProductIds` | ids of the other variants in the family |
| `bundles` | bundle offers that contain the product (detail enrichment) |
| `categories` | `["Home", "Beauty", "Skin Care", "Face Masks"]` (detail enrichment) |
| `searchRank` / `sourceQuery` | `3` / `"sheet mask"` |
| `reviews` | nested review rows, each key prefixed `review` (review enrichment) |

Every listing row also carries `originalPriceDisplay`, `priceDisplay`, `discountAmountUsd`, `isNew`, `hasVideos`, `variantCount`, `awards`, `productPackLabel`, `badges`, `originCountry`, `imageUrl` and `sourceUrl`. Detail enrichment adds `imageCount`, `coverImageUrl`, `productDetailSections`, `size`, `howToUse`, `benefits`, `brandUrl`, `brandDescription`, `brandSatisfactionPercent`, `brandReviewCount`, `brandPositiveReviewCount`, `yesStylerCount`, `availability`, `availabilityText`, `isSellable`, `condition`, `selectedOption`, `dealClaimedPercent`, `saleEndDate`, `parentProductId`, `productInformation`, `importedFrom`, `catalogNumber`, `categoryId`, `categoryIds`, `categoryUrls`, `searchKeywords`, `shipsTo`, `freeShippingOffer`, `deliveryEstimate`, `purchaseNote` and `nonReturnable`. Review enrichment adds `reviewsSummary` (total, satisfaction and per-star counts). Both enrichments are on by default. With Incremental mode on, every row also carries `changeType` (`NEW`, `UPDATED`, `UNCHANGED`, `REAPPEARED` or `EXPIRED`) and `changedFields`.

#### Output views and run summary

The dataset has four tabs: **Overview** (price, rating, stock and links per product), **Detail** (images, description, ingredients, categories and promotions), **Reviews** (the nested customer reviews) and **Changes** (incremental mode only: rows tagged `NEW`, `UPDATED`, `REAPPEARED` or `EXPIRED`, with `changedFields` and `priceChanges`). Every run also stores a small `OUTPUT` summary in the key-value store: mode, searches or links, products returned and scanned, details fetched, reviews attached, rejected requests, start and finish time, and in incremental mode the count per change type.

### How to Use

1. Pick a **mode**: `search` (run keywords through the store's own search) or `url` (paste product, browse or search links).
2. Toggle **Fetch product details** and **Fetch customer reviews** for the enriched fields; both are on by default.
3. Set **Max products** to control run size and cost, then click **Start**.
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Search by keyword:**

```json
{
  "mode": "search",
  "queries": ["sheet mask"],
  "sortBy": "bestsellers",
  "maxItems": 50
}
```

**Watch one brand's full catalogue:**

```json
{
  "mode": "url",
  "urls": ["https://www.yesstyle.com/en/anua/list.html/bpt.299_bid.325602"],
  "maxItems": 100,
  "fetchReviews": false
}
```

**One product, all its reviews, newest first:**

```json
{
  "mode": "url",
  "urls": ["https://www.yesstyle.com/en/aplb-glutathione-niacinamide-sheet-mask-25ml/info.html/pid.1124536886"],
  "reviewSort": "newest",
  "maxReviewsPerProduct": 0
}
```

**Daily change monitoring:**

```json
{
  "mode": "search",
  "queries": ["sheet mask"],
  "incrementalMode": true,
  "stateKey": "my-monitor",
  "maxItems": 100
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/yesstyle-com-scraper").call(run_input={
    "mode": "search", "queries": ["sheet mask"], "maxItems": 50,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["productId"], item["name"], item.get("price"), item.get("currency"))
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/yesstyle-com-scraper').call({
    mode: 'search', queries: ['sheet mask'], maxItems: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((i) => [i.productId, i.name, i.price]));
```

#### How `maxItems` shapes a scheduled run

**Max products** (`maxItems`, default 20) caps the whole run (`0` or a value above 100000 means 100000). **Max pages** (`maxPages`) caps each keyword or listing separately; leave it empty to walk up to the built-in limit of 1000 pages. Reviews are read only for products actually returned, and **Max reviews per product** (default 20, `0` = all, up to 1000 per product) caps each product's list.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run or dataset id and the actor skips every product already collected there, so you don't pay twice.
- **Incremental mode** (`incrementalMode`) is for scheduled runs over the same input. Each product is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED`, or `EXPIRED` (only after a complete scan, and only with `emitExpired` on). `stateKey` names or shares the stored state. Change detection tracks product-level fields (price, rating, review count, availability and so on), so a product with a new review comes back as `UPDATED` without re-sending every historical review. Excluded from the comparison because they move without the product changing: scrape time, USD figures, bestseller ranks, deal-claimed percent, YesStyler count, brand statistics, shipping offer, delivery estimate, search keywords, review summary and search rank. Individual reviews are never compared; a new review shows up through the rating and review count. List more fields in `ignoreFieldsForChanges` (a dotted path such as `bundles.bundlePrice` ignores one key inside list items). Set `changeScope` to `priceAndStock` to mark a product `UPDATED` only when price, original price, discount, currency, availability, item status or the sellable flag move. With `compactUpdates` on, `UPDATED` and `EXPIRED` rows are slim (ids, link, name, current price and availability, `priceChanges` and `variantChanges`, which is always an empty list because YesStyle lists every variant as its own product); they carry no reviews or detail data, so no review or detail-enrichment charge applies to them, and `NEW` rows stay complete. `expireAfterMissedScans` (default 1) waits for that many complete scans in a row before a product is marked `EXPIRED`; `EXPIRED` means the product is no longer in the results, not that it is unavailable. A scan that starts past page 1 of a pasted link, hits Max products or is resumed is never treated as complete, and `EXPIRED` rows never exceed Max products.

#### URL mode

Paste YesStyle links; each is routed by its own shape and keeps its own sort (`sb`), page (`pn`) and filters. A link starting on page 2 or later is a partial scope. Localized paths such as `/zh-CN/` are read as the English storefront. Anything else gets a per-link warning in the log.

| Shape | Example |
| --- | --- |
| Product detail | `https://www.yesstyle.com/en/aplb-glutathione-niacinamide-sheet-mask-25ml/info.html/pid.1124536886` |
| Product detail, slug-less | `https://www.yesstyle.com/en/info.html/pid.1124536886` |
| Keyword search | `https://www.yesstyle.com/en/list.html?q=sheet+mask` |
| Search, paginated and sorted | `https://www.yesstyle.com/en/list.html?q=sheet+mask&bpt=48&sb=141&pn=2` |
| Search, localized path | `https://www.yesstyle.com/zh-CN/list.html?q=serum` |
| Category browse | `https://www.yesstyle.com/en/beauty-sheet-masks/list.html/bcc.15554_bpt.46` |
| Category browse, paginated and sorted | `https://www.yesstyle.com/en/beauty-sheet-masks/list.html/bcc.15554_bpt.46?pn=2&sb=158` |
| Brand browse | `https://www.yesstyle.com/en/anua/list.html/bpt.299_bid.325602` |

Behaviour change: in URL mode with the links field left untouched, the run now scrapes one example of each of these 8 shapes (previously nothing). Set `maxItems` to cap the run. The two product-detail examples point at the same product, so together they return one product row.

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

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape: the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each record, not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify → Settings → Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip. `maxNotifyListings` caps how many products are sent per run (default 50).

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` (keywords) or `url` (pasted links, routed by their own shape). |
| `queries` | array | (none; prefilled with `["sheet mask"]` in the Console) | Keywords for search mode. |
| `sortBy` | string | `bestsellers` | Search mode only: `bestsellers`, `new_arrivals`, `price_low_high`, `price_high_low`, `best_value`, `availability` or `discount_high_low`. Pasted links keep their own sort. |
| `urls` | array | one example of each of the 8 shapes below (prefilled) | Product, brand, category or search links for URL mode. |
| `featured` | array | (none) | Both modes: keep only products in the store's featured collections (for example Vegan, Cruelty-free, Clearance, Flash Sales); several picks must all match. |
| `minPrice` | string | (none) | Both modes: keep only products priced at or above this value. |
| `maxPrice` | string | (none) | Both modes: keep only products priced at or below this value. |
| `inStockOnly` | boolean | `false` | Both modes: keep only products the store marks in stock (needs product details). |
| `fetchDetails` | boolean | `true` | Read each product's own page for the description, images, variant, stock wording and categories. |
| `fetchReviews` | boolean | `true` | Attach the product's customer reviews as a nested list, billed per review. |
| `reviewSort` | string | `relevant` | `relevant`, `newest`, `highest` or `helpful`. |
| `reviewFilter` | string | `all` | `all`, `five_star` to `one_star`, `positive`, `negative`, `photo` or `video`. |
| `maxReviewsPerProduct` | integer | `20` | Stop after this many reviews per product (`0` = all, capped at 1000 per product; larger values are also capped at 1000). |
| `maxItems` | integer | `20` | Product cap for the whole run (`0` or above 100000 = 100000). |
| `maxPages` | integer | (none) | Page cap per keyword or listing (empty or `0` = up to the built-in limit of 1000 pages). |
| `resumeFromRunId` | string | (none) | Continue one interrupted run; products it already collected are skipped. |
| `incrementalMode` | boolean | `false` | Return only new and changed products on scheduled runs. |
| `stateKey` | string | (none) | Name or share an incremental-mode state. |
| `emitUnchanged` | boolean | `false` | Also return (and bill) unchanged products. |
| `emitExpired` | boolean | `false` | Also return (and bill) products that disappeared after a complete scan. |
| `changeScope` | string | `all` | `priceAndStock` marks `UPDATED` on price and availability moves only. |
| `compactUpdates` | boolean | `false` | Slim `UPDATED` and `EXPIRED` rows with `priceChanges` (`variantChanges` is always empty). |
| `expireAfterMissedScans` | integer | `1` | Complete scans in a row a product must be missing before `EXPIRED`. |
| `ignoreFieldsForChanges` | array | (none) | Field names that alone should not mark a product `UPDATED`. |
| `proxy` | object | Apify Proxy, Residential, US (prefilled) | Connection settings; the exit country decides the regional storefront and currency. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each record to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which records are created. |
| `maxNotifyListings` | integer | `50` | Cap on products written to each connector per run. |

### Output Example

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

```json
{
  "productId": "1000000001",
  "url": "https://www.yesstyle.com/en/sample-sheet-mask/info.html/pid.1000000001",
  "name": "Sample Hydrating Sheet Mask",
  "brand": "Sample Brand",
  "brandId": 300001,
  "variant": "25ml",
  "price": 12.34,
  "currency": "USD",
  "priceDisplay": "US$ 12.34",
  "originalPrice": 18.0,
  "originalPriceDisplay": "US$ 18.00",
  "discountPercent": 31,
  "priceUsd": 12.34,
  "discountAmountUsd": 5.66,
  "rating": 4.82,
  "reviewCount": 1000,
  "ratingBreakdown": {"5": 800, "4": 150, "3": 30, "2": 10, "1": 10},
  "itemStatus": "FLASH SALE",
  "promotions": ["limitedDeal", "highDiscount"],
  "bestsellerRank": 2,
  "bestsellerRanks": [{"rank": 2, "category": "Face Masks", "categoryId": 10002}],
  "variantProductIds": ["1000000002", "1000000003"],
  "variantCount": 3,
  "originCountry": "KR",
  "images": [
    "https://d1flfk77wl2xk4.cloudfront.net/Assets/00/000/l_p0000000000.jpg",
    "https://d1flfk77wl2xk4.cloudfront.net/Assets/GalleryImage/00/000/L_g0000000001.jpg"
  ],
  "imageCount": 2,
  "productDescription": "Full product description appears here when detail enrichment is on.",
  "size": "25ml",
  "howToUse": "Apply to cleansed skin and remove after 15 minutes.",
  "ingredients": "Water, Glycerin, Niacinamide",
  "brandOrigin": "South Korea",
  "brandSatisfactionPercent": 98.5,
  "availability": "InStock",
  "dealClaimedPercent": 60,
  "saleEndDate": "2026-01-01T00:00:00Z",
  "categories": ["Home", "Beauty", "Skin Care", "Face Masks"],
  "categoryIds": [10000, 10001, 10002],
  "bundles": [{"bundleProductId": "1000000009", "bundleTitle": "Sample Sheet Mask Bundle Set", "bundlePrice": 49.0}],
  "importedFrom": "South Korea",
  "deliveryEstimate": "6 - 8 business days",
  "searchRank": 3,
  "sourceQuery": "sheet mask",
  "scrapedAt": "2026-01-01T00:00:00Z",
  "reviewsSummary": {"totalReviews": 1000, "satisfactionPercent": "98%", "ratingBreakdown": {"5": 800, "4": 150, "3": 30, "2": 10, "1": 10}},
  "reviews": [
    {
      "reviewId": 10000001,
      "reviewTitle": "Excellent for hydrating",
      "reviewRating": 5,
      "reviewText": "Review text appears here.",
      "reviewDate": "January 1, 2026",
      "reviewerName": "Jane Doe",
      "reviewHelpfulVotes": 10,
      "reviewTotalVotes": 12,
      "reviewImages": [],
      "reviewImageThumbnails": [],
      "reviewProductId": "1000000001"
    }
  ]
}
```

### Plan Requirement

The prefilled connection (Apify Proxy, Residential, US) is the default and is what the store was read with in most testing. Datacenter connections read most pages of this store, but some datacenter exits get a refusal page; the request is then retried on a fresh exit. Residential (the prefill) reads more cleanly, so keep it unless you need to save cost. Change the proxy country to read another regional storefront and its currency. When the selected group is refused, the run falls over to Apify datacenter, then to a backup connection.

On an Apify free plan, which does not include residential proxies, the log prints:

> The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable. For residential access, upgrade at https://apify.com/pricing or supply your own proxy URLs.

When the backup connection then serves data, the log notes "Served over the backup connection (the default connection was unavailable)". The backup keeps the storefront you selected but can be less reliable.

### FAQ

#### How much does it cost?

You pay per product returned, plus detail enrichment per product whose page was read and review enrichment per review attached. Turning both enrichments off gives the cheapest run. The **Pricing** tab shows the current rates. Use **Max products** and **Max reviews per product** to cap the cost of any run.

#### Is it legal to scrape YesStyle?

This actor collects only publicly available store data, without logging in. You are responsible for how you use it: follow YesStyle's terms and the laws that apply to you, including privacy law for reviewer names, and get legal advice if you plan commercial redistribution. Product photos and review text may be subject to third-party rights.

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

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. The first run records a baseline; later runs return only new, updated and reappeared products (and expired ones after a complete scan, if you turn on **Emit expired products**). Unchanged products are not billed.

#### Why did a run return fewer products than the store shows?

**Max products**, **Max pages**, the price bounds and **In stock only** all narrow results. The store also reorders results between visits, so two runs of the same keyword can differ slightly near the cut-off.

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

If every listing page is refused, the run stops with a clear message instead of finishing with zero items, so "no products" is never confused with "nothing could be read". The message is one of:

- "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later."
- "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested YesStyle pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again."
- "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required: https://apify.com/pricing. If you entered your own proxy URLs, check that their credentials are valid."

A genuinely empty search finishes normally with no items.

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

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

### 🔗 Want more fashion data?

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

<table>
<tr><td>👗 <a href="https://apify.com/abotapi/24s-com-scraper"><b>24S Scraper</b></a><br>Scrape 24S luxury fashion by category, filters, or URL. Extract brand, name, price...</td><td>🥦 <a href="https://apify.com/abotapi/elcorteingles-es-scraper"><b>El Corte Inglés Scraper</b></a><br>Scrape El Corte Inglés elcorteingles.es products across fashion, electronics, home...</td></tr>
<tr><td>👗 <a href="https://apify.com/abotapi/fashionnova-com-scraper"><b>Fashion Nova Scraper</b></a><br>Scrape Fashion Nova products by keyword, collection or URL. Extract product names...</td><td>👗 <a href="https://apify.com/abotapi/otto-de-scraper"><b>OTTO.de Scraper</b></a><br>Scrape OTTO.de products by search or URL. Extract prices, discounts, variants...</td></tr>
<tr><td>👗 <a href="https://apify.com/abotapi/zozotown-scraper"><b>ZOZOTOWN</b></a><br>Scrape ZOZOTOWN (zozo.jp), Japan's largest fashion marketplace: name, brand, JPY price...</td><td>👗 <a href="https://apify.com/abotapi/showpo-com-scraper"><b>Showpo Scraper</b></a><br>Scrape Showpo women's fashion by keyword, collection or URL. Extract product prices...</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/yesstyle-com-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`):

Choose 'search' to run one or more keywords through YesStyle's own search, or 'url' to scrape pasted links: product pages, browse (list.html) pages and search pages are all accepted.

## `queries` (type: `array`):

Only used when mode = search, ignored in url mode. One or more keywords, for example sheet mask, anua serum, korean dress.

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

Search mode only. Sort order applied to keyword searches, using the store's own sort codes. Pasted links in URL mode always keep their own ordering.

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

Only used when mode = url, ignored in search mode. Paste product page links, browse links (brand/category listings) or search links from yesstyle.com.

## `minPrice` (type: `string`):

Both modes. Keep only products priced at or above this value (in the storefront currency your run reads). Leave empty for no lower bound.

## `maxPrice` (type: `string`):

Both modes. Keep only products priced at or below this value. Leave empty for no upper bound.

## `featured` (type: `array`):

Both modes. Keep only products inside the store's own featured collections, such as Vegan, Cruelty-free, Clearance or Flash Sales. Pick several to require all of them. Leave empty for no collection filter.

## `inStockOnly` (type: `boolean`):

Both modes. Keep only products the product page marks as in stock. Needs Fetch product details enabled.

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

Read each product's own page for the description, availability, condition, selected variant, full image set and category trail. Costs one Detail enrichment unit per product returned.

## `fetchReviews` (type: `boolean`):

Attach the product's customer reviews to its record as a nested list. Costs one Review enrichment unit per review attached. Reviews are only read for products actually returned.

## `reviewSort` (type: `string`):

Both modes. Which reviews come first, using the store's own review orderings.

## `reviewFilter` (type: `string`):

Both modes. Which reviews the store includes, using its own review filters.

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

Both modes. Stop reading a product's reviews after this many. Use 0 to read every review the store returns for the product, up to 1000 per product.

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

Stop after this many products. The run ends cleanly once the cap is reached. Values of 0 or above 100000 are treated as 100000.

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

Walk at most this many result pages per keyword or listing. Leave empty or 0 for the built-in limit of 1000 pages.

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

Apify Proxy is enabled by default on the residential pool, which reads the store most cleanly; datacenter exits read most pages, but some exits get a refusal page and the request is retried on a fresh exit. The exit country decides the regional storefront and currency (US default).

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

Continue an interrupted run: paste a previous run's ID (or a dataset ID) from this account and every product it already collected is skipped.

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

Track the same search or links across scheduled runs and return only what changed: NEW, UPDATED, UNCHANGED (suppressed by default), REAPPEARED and EXPIRED products. The first run for a scope reports everything as NEW. UPDATED is decided by comparing the product's fields (price, original price, discount, availability, rating, review count, badges, descriptions, images and so on) with the last run; excluded from the comparison because they move without the product changing: scrape time, USD figures, bestseller ranks, deal-claimed percent, YesStyler count, brand statistics, shipping offer, delivery estimate, search keywords, review summary and search rank. Individual reviews are not compared; a new review shows up through the rating and review count. Edit the exclusions in Ignore fields.

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

Optional name for the incremental baseline. Runs sharing a state key share one baseline; leave empty to derive it from the search configuration automatically.

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

Also return products that did not change since the last incremental run (changeType UNCHANGED) instead of suppressing them.

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

After a complete scan, also return tracked products that are no longer in the results (changeType EXPIRED).

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

What counts as a change in incremental mode. All fields (default): any product-level change except volatile fields (USD figures, rankings, shipping offer, search keywords, review summary) marks a product UPDATED. Price and availability only: just price, original price, discount, currency, availability, item status and the sellable flag mark UPDATED; description, images, badges and ratings never do.

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

Return UPDATED and EXPIRED rows as slim rows with ids, link, name, current price and availability, priceChanges (old and new values) and variantChanges (always an empty list, because YesStyle lists every variant as its own product). NEW rows stay complete. Compact rows carry no reviews or detail data, so no review or detail-enrichment charge applies to them.

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

With Emit expired products, mark a product EXPIRED only after it was missing from this many complete scans in a row (default 1). EXPIRED means the product is no longer in the results; it does not prove the product is unavailable, check availability for that.

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

Advanced. Field names whose changes alone should not mark a product UPDATED (for example badges). Use a dotted path such as bundles.bundlePrice to ignore one key inside list items. The record's other fields still fingerprint normally.

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

Optional MCP connector IDs. Each returned product is also sent to the connector (for example a Notion database).

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

Used with a Notion MCP connector: the parent page or database the product pages are created under.

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

Cap how many of the returned products are sent to MCP connectors.

## Actor input object example

```json
{
  "mode": "search",
  "queries": [
    "sheet mask"
  ],
  "sortBy": "bestsellers",
  "urls": [
    "https://www.yesstyle.com/en/aplb-glutathione-niacinamide-sheet-mask-25ml/info.html/pid.1124536886",
    "https://www.yesstyle.com/en/info.html/pid.1124536886",
    "https://www.yesstyle.com/en/list.html?q=sheet+mask",
    "https://www.yesstyle.com/en/list.html?q=sheet+mask&bpt=48&sb=141&pn=2",
    "https://www.yesstyle.com/zh-CN/list.html?q=serum",
    "https://www.yesstyle.com/en/beauty-sheet-masks/list.html/bcc.15554_bpt.46",
    "https://www.yesstyle.com/en/beauty-sheet-masks/list.html/bcc.15554_bpt.46?pn=2&sb=158",
    "https://www.yesstyle.com/en/anua/list.html/bpt.299_bid.325602"
  ],
  "inStockOnly": false,
  "fetchDetails": true,
  "fetchReviews": true,
  "reviewSort": "relevant",
  "reviewFilter": "all",
  "maxReviewsPerProduct": 20,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "changeScope": "all",
  "compactUpdates": false,
  "expireAfterMissedScans": 1,
  "maxNotifyListings": 50
}
```

# Actor output Schema

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

No description

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

No description

## `reviews` (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",
    "queries": [
        "sheet mask"
    ],
    "sortBy": "bestsellers",
    "urls": [
        "https://www.yesstyle.com/en/aplb-glutathione-niacinamide-sheet-mask-25ml/info.html/pid.1124536886",
        "https://www.yesstyle.com/en/info.html/pid.1124536886",
        "https://www.yesstyle.com/en/list.html?q=sheet+mask",
        "https://www.yesstyle.com/en/list.html?q=sheet+mask&bpt=48&sb=141&pn=2",
        "https://www.yesstyle.com/zh-CN/list.html?q=serum",
        "https://www.yesstyle.com/en/beauty-sheet-masks/list.html/bcc.15554_bpt.46",
        "https://www.yesstyle.com/en/beauty-sheet-masks/list.html/bcc.15554_bpt.46?pn=2&sb=158",
        "https://www.yesstyle.com/en/anua/list.html/bpt.299_bid.325602"
    ],
    "fetchDetails": true,
    "fetchReviews": true,
    "reviewSort": "relevant",
    "reviewFilter": "all",
    "maxReviewsPerProduct": 20,
    "maxItems": 20,
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    },
    "maxNotifyListings": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/yesstyle-com-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",
    "queries": ["sheet mask"],
    "sortBy": "bestsellers",
    "urls": [
        "https://www.yesstyle.com/en/aplb-glutathione-niacinamide-sheet-mask-25ml/info.html/pid.1124536886",
        "https://www.yesstyle.com/en/info.html/pid.1124536886",
        "https://www.yesstyle.com/en/list.html?q=sheet+mask",
        "https://www.yesstyle.com/en/list.html?q=sheet+mask&bpt=48&sb=141&pn=2",
        "https://www.yesstyle.com/zh-CN/list.html?q=serum",
        "https://www.yesstyle.com/en/beauty-sheet-masks/list.html/bcc.15554_bpt.46",
        "https://www.yesstyle.com/en/beauty-sheet-masks/list.html/bcc.15554_bpt.46?pn=2&sb=158",
        "https://www.yesstyle.com/en/anua/list.html/bpt.299_bid.325602",
    ],
    "fetchDetails": True,
    "fetchReviews": True,
    "reviewSort": "relevant",
    "reviewFilter": "all",
    "maxReviewsPerProduct": 20,
    "maxItems": 20,
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
    "maxNotifyListings": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/yesstyle-com-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",
  "queries": [
    "sheet mask"
  ],
  "sortBy": "bestsellers",
  "urls": [
    "https://www.yesstyle.com/en/aplb-glutathione-niacinamide-sheet-mask-25ml/info.html/pid.1124536886",
    "https://www.yesstyle.com/en/info.html/pid.1124536886",
    "https://www.yesstyle.com/en/list.html?q=sheet+mask",
    "https://www.yesstyle.com/en/list.html?q=sheet+mask&bpt=48&sb=141&pn=2",
    "https://www.yesstyle.com/zh-CN/list.html?q=serum",
    "https://www.yesstyle.com/en/beauty-sheet-masks/list.html/bcc.15554_bpt.46",
    "https://www.yesstyle.com/en/beauty-sheet-masks/list.html/bcc.15554_bpt.46?pn=2&sb=158",
    "https://www.yesstyle.com/en/anua/list.html/bpt.299_bid.325602"
  ],
  "fetchDetails": true,
  "fetchReviews": true,
  "reviewSort": "relevant",
  "reviewFilter": "all",
  "maxReviewsPerProduct": 20,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  },
  "maxNotifyListings": 50
}' |
apify call abotapi/yesstyle-com-scraper --silent --output-dataset

```

## MCP server setup

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