# Isetan Mitsukoshi - Products, Prices, Stock & Reviews (`abotapi/mistore-jp-scraper`) Actor

Scrape the Isetan Mitsukoshi department store online shop (mistore.jp). Search by keyword or department, or paste search, department, brand and product links. Returns id, title, brand, category, JPY price, sale window, stock, colours and images, plus specifications, variants and customer reviews.

- **URL**: https://apify.com/abotapi/mistore-jp-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 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

## Isetan Mitsukoshi Online Store Scraper: Products, Prices, Variants & Reviews

Isetan Mitsukoshi Online Store Scraper turns the Isetan Mitsukoshi department store's online shop into a clean product data feed. Get id, title, brand, department and breadcrumb trail, price in Japanese yen, sale flags and sale window, stock, colour options and the image gallery, plus, with full detail turned on, the description, specification list, size and colour variants with per variant price and barcode, shipping and gift terms, payment methods, an allergen panel and customer reviews where the store has them. Search by keyword or department, or paste store links, then export to JSON, CSV or Excel, or pull results straight into your app through the API.

### Why This Scraper?

- **Two ways in.** Search by keyword and department with the store's own native filters, or paste search, department, brand and product links directly. No need to build URLs by hand.
- **A genuine department store catalogue.** Womenswear, menswear, baby and kids, bags, shoes, home, kitchen and art, food and gifts are all covered by the same actor, with the same consistent record shape across every department.
- **Full detail on demand.** Turn on full product details for the description, every size and colour variant with its own price, barcode and stock count, the full image gallery, shipping and gift terms and payment methods, and turn on reviews for the aggregate rating, star breakdown and individual review text, only when you want the extra cost.
- **Real filters, applied at the source.** Sort order, badges, colour family, brand and price band are the store's own refinement, sent with the request, so a filtered-out product is never fetched and never billed.
- **Built for monitoring.** Incremental mode returns only new, updated and reappeared products on a recurring schedule, and Resume continues one interrupted run without returning or paying for what it already collected.
- **Honest gaps, not guesses.** A stock flag, a list price or a review the store never published comes back `null` or empty rather than invented.
- **A single, well understood storefront.** Every price is in Japanese yen and there is no country or currency selector to configure: this is a Japan-only catalogue and the actor is built around that.

### Use Cases

- **Competitive pricing and merchandising:** track price, sale window and stock across bags, fashion, home and food departments for benchmarking or repricing.
- **Brand monitoring:** follow one brand's full catalogue, availability and customer reviews across every department it sells in.
- **Gift and seasonal catalogue research:** pull the food, wine and gift departments with delivery and gift-wrap terms ahead of a season.
- **Customer sentiment research:** collect star ratings, rating breakdowns and individual review text for the products that carry them.
- **Recurring inventory and price feeds:** schedule incremental runs to receive only new, updated or delisted products instead of re-downloading the whole catalogue.

### Data You Get

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

| Field | Example |
| --- | --- |
| `productId` | `"200000000000000012345"` |
| `title` | `"Sample Quilted Tote Bag"` |
| `brand` / `brandCode` | `"Sample Brand Label"` / `"010101"` |
| `url` | link to the product page |
| `topCategory` / `categoryPath` | `"レディース"` / `["レディース", "バッグ", "トートバッグ"]` |
| `price` / `priceMin` / `priceMax` | `12800` / `12800` / `14300` |
| `originalPrice` / `discountPercent` | `null` / `null` (the store rarely publishes a list price behind a sale flag, see the tip below) |
| `currency` | `"JPY"` |
| `onSale` / `badges` | `true` / `["SALE"]` |
| `inStock` / `availability` | `true` / `"InStock"` |
| `saleStartsAt` / `saleEndsAt` | an ISO date, or `null` when the store does not declare one |
| `image` / `images` / `thumbnails` | the cover image, the full gallery, and thumbnail crops |
| `variants[]` | colour, size, barcode, per-variant price and stock count (with full detail on) |
| `specifications[]` | `name` / `value` spec rows such as material and country of origin (with full detail on) |
| `allergens[]` | `name` / `present` allergen panel rows, mainly on food products (with full detail on) |
| `giftOptions[]` | gift-wrap availability and note (with full detail on) |
| `shippingFee` / `shippingNote` / `deliveryNotes` | shipping cost in yen and the store's own delivery terms |
| `paymentMethods` | accepted payment methods |
| `rating` / `reviewCount` / `ratingBreakdown` | aggregate star rating, review count and a 0-5 star histogram (with reviews on) |
| `reviews[]` | individual reviews: author handle, rating, title, text, post date and helpful votes (with reviews on) |
| `searchMode` / `scrapedAt` | how this record was found, and when it was scraped |
| `changeType` / `changedFields` / `firstSeenAt` / `lastSeenAt` | incremental mode only: `NEW`, `UPDATED`, `UNCHANGED`, `REAPPEARED` or `EXPIRED`, and the fields that changed |

A department listing renders only a handful of products in full; the rest arrive as placeholders the actor resolves through the store's own tile endpoint before they are ever filtered or emitted, so `inStock` and `brand` can legitimately be `null` on a listing-only run for a product a full-detail run would fill in.

### How to Use

1. Pick a **mode**: `search` (keyword and/or department) or `url` (paste store links or product ids).
2. Fill in your keywords, departments or links, and switch on the filters, full product details and reviews you want.
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 a keyword:**

```json
{
  "mode": "search",
  "queries": ["バッグ"],
  "fetchDetails": true,
  "maxItems": 50
}
```

**Browse a department, filtered and sorted:**

```json
{
  "mode": "search",
  "categories": ["womens"],
  "badges": ["sale"],
  "minPrice": 5000,
  "maxPrice": 50000,
  "sortBy": "price_asc",
  "maxItems": 100
}
```

**Paste links (a department listing and a single product):**

```json
{
  "mode": "url",
  "urls": [
    "https://www.mistore.jp/shopping/productlist?cgid=28_011500",
    "https://www.mistore.jp/shopping/product/200000000000000012345.html"
  ],
  "fetchDetails": true
}
```

**Recurring department monitoring:**

```json
{
  "mode": "search",
  "categories": ["food"],
  "incrementalMode": true,
  "stateKey": "food-department-daily",
  "maxItems": 500
}
```

Departments accept a friendly name (`womens`, `mens`, `baby_kids`, `bags`, `shoes`, `home_kitchen_art`, `food`, `events`) or a store category code such as `28_011500` for a narrower sub-department. The store files **bags** and **shoes** under each audience rather than as one store-wide department, so `bags` and `shoes` each expand into three or four separate department codes, all covered in full within the same run. A well-formed code the store does not know (for example a typo) is detected on its first page, logged as a warning that names the code, and skipped without collecting or billing anything; the same applies to a pasted listing link with such a `cgid`.

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/mistore-jp-scraper").call(run_input={"mode": "search", "queries": ["バッグ"], "maxItems": 20})
for product in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(product["title"], product["price"], product["currency"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/mistore-jp-scraper').call({ mode: 'search', queries: ['バッグ'], maxItems: 20 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

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

#### Departments, links and multiple scopes in one run

Each keyword, department and pasted listing link in a run is walked forward as its own scope, and every scope in a run shares one running memory of the product ids it has already taken, so the same product is never returned twice from two scopes in the same run.

**Keep the scopes in one run distinct where you can.** Two scopes overlap when they list some of the same products: a keyword and a department, two departments, or the several store codes that `bags` and `shoes` expand into whenever a product is filed under more than one audience. When they do, two things can happen in the same run:

- once a later scope has taken at least one new product, it ends its own walk at the first page that holds nothing new for it (every product on it was already taken by an earlier scope), and never requests the pages after it, even if they still held genuinely new products;
- on a busy department listing, a placeholder product that a scope skipped because its share of **Max products** was already used up still counts as taken, so a later, overlapping scope in the same run does not pick it up.

In incremental mode with **Emit expired** on, the first case also counts as that scope reaching its real end, so products that are still listed on the pages it never requested can be returned, and billed, as `EXPIRED`. Run broad, overlapping searches as separate runs (with separate State keys when monitoring), rather than relying on one run to reconcile them.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run or dataset id and the actor skips every product it already collected there, so you don't pay twice.
- **Incremental mode** (`incrementalMode`) is for scheduled runs over the same scope. Each product is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED` or `EXPIRED` (only after a run that scanned the whole scope, and only with `emitExpired`). `stateKey` names or shares the stored state. A product counts as `UPDATED` when any field of its record changes (price, original price, sale flag, stock, variants, images, description, badges, category). The scrape time and the order of badge and colour codes never count; new reviews and rating changes do count. To stop review activity from producing `UPDATED` rows, add `reviews`, `rating`, `reviewCount` and `ratingBreakdown` to `ignoreFieldsForChanges`, which excludes any further field you name as well. Optional `changeScope` = `priceAndStock` compares only price, original price, discount, sale flag, stock and sale window (of the product and of each variant, in a stable order). `compactUpdates` returns `UPDATED` and `EXPIRED` rows slim (identifiers, current price and stock, `priceChanges`, `variantChanges`, and an empty `reviews` list so they never appear in the Reviews view); `NEW` rows stay complete, and the detail enrichment unit is not charged for a compact row because it does not carry the enriched record. `expireAfterMissedScans` (default 1) tombstones a product only after it was missing from that many complete scans in a row; `EXPIRED` means the product was no longer found in the listing, not that it is unavailable, so read the stock fields for availability. A pasted listing link that starts after its first page is a partial scope and never produces `EXPIRED` rows. With incremental mode off, every matching product is returned on every run.
- **A note on Emit expired and Max products.** Expired rows are produced only when a run counts as a complete scan of the tracked search: it took in fewer products than Max products (or Max products is 0), it was not a Resume, and every scope stopped at an end of results rather than at a page or item limit. When that holds, every tracked product not seen in the run is returned and billed as `EXPIRED` in that one run, and this batch is **not** trimmed to Max products. For example, with Max products at 20 and 500 products tracked, a run that now finds only 19 of them returns 481 expired rows, plus any of the 19 that changed (or all 19 with Emit unchanged on). The expired batch can be as large as the whole tracked baseline, so keep each State key's search to a size you are happy to see expire in one run, or leave Emit expired off. Overlapping scopes in one run can also produce false expired rows; see "Departments, links and multiple scopes in one run" above.

#### URL mode: supported link shapes

Running URL mode with the field untouched now scrapes one example of each shape below (the field previously had no default). Replace the list with your own links. The apex-host (mistore.jp without www) product link is offered in the prefill only, because it resolves to the same product as the www link and would be deduplicated in the default list.

| Shape | Example |
|---|---|
| Keyword search | `https://www.mistore.jp/shopping/search?q=バッグ` (the older `/shopping/search-word` link also works) |
| Department listing | `https://www.mistore.jp/shopping/productlist?cgid=28_011500` |
| Paginated and sorted listing | `...productlist?cgid=28_011500&start=60&srule=inexpensive` |
| Badge-filtered listing | `...productlist?cgid=28_011500&other=ref_sale_flg` |
| Price-filtered listing | `...productlist?cgid=28_011500&pmin=1000&pmax=5000` (the store applies `pmin` and `pmax` itself and narrows the listing, measured 3191 to 406 products for 1000 to 5000 yen, but it can include a few products slightly outside the range, and the actor does not re-check `pmin`/`pmax` inside a pasted link; set minPrice and maxPrice for a range that is enforced on every row, so a product outside it is never returned or billed) |
| Paginated and sorted keyword search | `...search?q=バッグ&srule=new-arrival&start=60` |
| Brand listing | `https://www.mistore.jp/shopping/brand/list?brand=002383` |
| Product page | `https://www.mistore.jp/shopping/product/900000000000000003062447.html` |
| Product page on the bare host | `https://mistore.jp/shopping/product/900000000000000003062447.html` |
| Bare product id | `900000000000000003062447` |

Any other link is skipped with a warning in the log. A link that starts partway into a listing (`start` above 0) covers only that part of the listing.

### 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 product, 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, API and 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 product pages should be created.
4. Use `maxNotifyListings` to cap how many products are written to each connector per run.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` (keyword and/or department, with filters) or `url` (paste store links or product ids). |
| `queries` | array | (none, prefilled `["バッグ"]`) | Search mode only. Keywords to search; each is covered separately, across all of its results. |
| `categories` | array | (empty) | Search mode only. Departments to browse, by friendly name or store category code. |
| `urls` | array | one example of each supported link shape (see URL mode table) | URL mode only. Store listing or product links, or bare product ids. |
| `sortBy` | string | `recommended` | The store's own result ordering: `recommended`, `newest`, `price_asc`, or `price_desc`. |
| `badges` | array | `[]` | Keep only products carrying any of these store badges. |
| `colors` | array | `[]` | Keep only products available in these colour families. |
| `brandCodes` | array | `[]` | Keep only products from these store brand codes. |
| `minPrice` | integer | (none) | Only keep products priced at or above this many yen. |
| `maxPrice` | integer | (none) | Only keep products priced at or below this many yen. |
| `includeOutOfStock` | boolean | `false` | Off by default, matching the store, which hides out of stock products. |
| `fetchDetails` | boolean | `true` | Collect each product's full record: description, variants, specifications, images, shipping and gift terms, payment methods, allergens and badge marks. Off returns listing fields only. |
| `fetchReviews` | boolean | `false` | Collect each product's rating, review count, rating breakdown and individual reviews. Costs one extra request per product. |
| `maxReviewsPerProduct` | integer | `20` | Cap on individual reviews returned per product, from 1 to 500. Only used when Fetch customer reviews is on. Reviews are covered by the same detail enrichment unit as full product details, charged once per delivered product, with no separate per review charge. |
| `maxItems` | integer | `20` | Maximum number of products to return across the whole run. `0` = unlimited. |
| `maxPages` | integer | `0` | Maximum result pages per keyword, department or link. `0` = unlimited. Each page holds 60 products. |
| `resumeFromRunId` | string | (none) | Continue one interrupted run without returning or being charged for products it already collected. |
| `incrementalMode` | boolean | `false` | Turn on for recurring monitoring: return only new, updated and reappeared products on later runs. |
| `stateKey` | string | (none) | Name or share an incremental-mode monitoring campaign. |
| `changeScope` | string | `all` | Incremental mode: `all` or `priceAndStock` (only price, stock and sale fields decide `UPDATED`). |
| `compactUpdates` | boolean | `false` | Incremental mode: return `UPDATED` and `EXPIRED` rows slim, with `priceChanges` and `variantChanges`. |
| `expireAfterMissedScans` | integer | `1` | Incremental mode: scans in a row a product must be missing before it is marked `EXPIRED`. |
| `ignoreFieldsForChanges` | string\[] | (none) | Incremental mode: field names or dotted paths such as `variants.image` that never make a product `UPDATED`. |
| `emitUnchanged` | boolean | `false` | Also return (and bill) products unchanged since the last run. |
| `emitExpired` | boolean | `false` | Also return (and bill) products no longer found, after a complete scan. |
| `proxy` | object | Japanese exit, metered residential pool | Proxy and connection settings. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each product to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which product pages 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": "200000000000000012345",
  "title": "Sample Quilted Tote Bag",
  "brand": "Sample Brand Label",
  "brandCode": "010101",
  "url": "https://www.mistore.jp/shopping/product/200000000000000012345.html",
  "image": "https://example.test/images/sample-tote-cover.jpg",
  "images": ["https://example.test/images/sample-tote-1.jpg", "https://example.test/images/sample-tote-2.jpg"],
  "thumbnails": ["https://example.test/images/sample-tote-thumb-1.jpg"],
  "topCategory": "レディース",
  "categoryPath": ["レディース", "バッグ", "トートバッグ"],
  "categoryCode": "28_011504",
  "price": 12800,
  "priceMin": 12800,
  "priceMax": 14300,
  "originalPrice": null,
  "discountPercent": null,
  "currency": "JPY",
  "onSale": true,
  "badges": ["SALE"],
  "inStock": true,
  "availability": "InStock",
  "saleStartsAt": "2026-09-01T00:00:00Z",
  "saleEndsAt": "2026-09-30T14:59:59Z",
  "variants": [
    {
      "variantId": "300000000000000098765",
      "color": "サンプルブラック",
      "colorCode": "10",
      "size": "フリーサイズ",
      "barcode": "4900000000000",
      "price": 12800,
      "originalPrice": null,
      "discountPercent": null,
      "stock": 3,
      "inStock": true,
      "onSale": true
    }
  ],
  "specifications": [
    { "name": "素材", "value": "本体: 合成皮革 / 裏地: ポリエステル" },
    { "name": "原産国", "value": "中国" }
  ],
  "allergens": [],
  "giftOptions": [{ "name": "ギフト包装", "available": true, "note": "対応可" }],
  "shippingFee": 715,
  "shippingNote": "一部地域を除き送料無料",
  "deliveryNotes": ["通常3-5営業日で発送"],
  "paymentMethods": ["クレジットカード", "代金引換", "d払い"],
  "rating": 4.5,
  "reviewCount": 2,
  "ratingBreakdown": { "0": 0, "1": 0, "2": 0, "3": 0, "4": 1, "5": 1 },
  "reviews": [
    {
      "author": "サンプルユーザー",
      "rating": 5.0,
      "title": "サンプルタイトル",
      "text": "サンプルレビュー本文です。",
      "postedAt": "2026-08-01",
      "postedTime": "10:00:00",
      "helpfulCount": 1,
      "totalVotes": 1,
      "images": []
    }
  ],
  "searchMode": "search",
  "scrapedAt": "2026-09-30T07:00:00Z"
}
```

### Plan Requirement

**Japanese residential proxies are required.** The storefront serves pages only to Japanese residential exits. Datacenter exits get no response from the store (the connection opens, then no data arrives), so a datacenter pool does not work here. The default proxy setting is a Japanese exit on the residential pool; keep it, or supply your own Japanese residential proxy URLs. Residential traffic is metered by Apify and is part of the cost of a run.

Free Apify plans do not include residential proxies. On such a plan the run logs this notice and continues on a backup connection:

> 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 pages are then served over the backup, the log says: "Served over the backup connection (the default connection was unavailable)." The backup is best effort and may not load every page. The actor never sends requests directly, and this is a change: runs without proxy access used to attempt a direct request and could hang; they now stop with a clear message. If you enter your own proxy URLs, only those are used, with no backup connection.

If no page can be loaded the run ends as failed with one of these messages, instead of reporting an empty success:

- 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, or check that your own proxy URLs have valid credentials.
- 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 Isetan Mitsukoshi pages.
- Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search.

Upgrade at https://apify.com/pricing or supply your own proxy URLs for reliable access.

#### Output views and billing

The dataset has four views: **Overview** (price, stock and sale fields), **Detail** (description, variants, specifications, shipping and gift terms), **Reviews** (one row per review) and **Changes** (incremental `changeType`, `changedFields`, `priceChanges`, `variantChanges`). The run also stores an `OUTPUT` summary with per-source counts.

Billing events are the run start, one event per product returned, and one detail enrichment event per delivered product when full details or reviews are on. Reviews are covered by that same enrichment event; there is no separate per review charge. Products that are filtered out by price, unchanged, or compact update rows are not charged the enrichment event. The Pricing tab shows the current rates.

### FAQ

#### How much does it cost?

You pay a small charge per run start and per product returned, plus a per-product surcharge only when full detail and/or reviews are switched on. The **Pricing** tab shows the current rates. Use **Max products** to cap the cost of any run.

#### Is it legal to scrape the Isetan Mitsukoshi online store?

This actor collects only publicly available product data. You are responsible for how you use it: follow the store's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Product names, prices and stock are generally facts, but photos and descriptive text may be subject to third-party rights.

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

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. Turn on **Emit unchanged** or **Emit expired** only if you also want those returned and billed; see the tip under How to Use about Emit expired and Max products before relying on it for a very large, fast-changing catalogue.

#### Why did a run return fewer products than I expected from overlapping departments or links?

Departments, keywords and pasted links in one run share a single running memory of product ids already taken. When two of them list some of the same products, a later scope can stop on a page that an earlier scope already fully covered and skip its remaining pages, and a placeholder product one scope skipped for lack of budget is not picked up by the other. With Emit expired on, the early stop can also mark still-listed products as expired. See the tip under How to Use for the trigger condition and the workaround.

#### Why is `originalPrice` or `discountPercent` often `null`?

Because the store itself usually does not publish a list price or a discount rate behind a `SALE` badge, only the current price. `onSale` still reflects the store's own flag reliably; `originalPrice` and `discountPercent` come through automatically whenever the store does publish them.

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

If the site refuses every request, the run stops with a clear message so "no products matched" is never confused with "nothing could be read". Run it again in a few minutes. If only some departments or links could be read, you still get what was found.

#### 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.

### 🔗 More scrapers you might like

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

<table>
<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/rakuten-ichiba-scraper"><b>Rakuten</b></a><br>Scrape Rakuten Ichiba (rakuten.co.jp): name, JPY price, reference price and discount...</td></tr>
<tr><td>🛒 <a href="https://apify.com/abotapi/nitori-net-jp-scraper"><b>Nitori Japan Furniture &amp; Home Goods Scraper</b></a><br>Scrape Nitori Japan (nitori-net.jp) furniture and home goods by keyword, category or...</td><td>🛒 <a href="https://apify.com/abotapi/mercari-jp-scraper"><b>Mercari Japan Scraper</b></a><br>Scrape Mercari Japan listings, sellers and reviews at scale. Extract names, prices...</td></tr>
<tr><td>🧩 <a href="https://apify.com/abotapi/suumo-jp-scraper"><b>Suumo.jp Scraper</b></a><br>Scrape Suumo, Japan's largest property portal: rental rooms with rent, management fees...</td><td>🔌 <a href="https://apify.com/abotapi/biccamera-com-scraper"><b>Bic Camera Scraper</b></a><br>Scrape Bic Camera (biccamera.com) products: JPY price, list price and discount, Bic Point...</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/mistore-jp-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' for keywords and departments with filters, or 'url' to scrape pasted links: a search, department or brand listing link is covered in full, and a product link or bare product id returns that one product with full detail.

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

Only used when mode = search, ignored in URL mode. One or more keywords to search, for example バッグ (bag), コート (coat) or ワイン (wine). English keywords work too, but the catalogue is Japanese, so Japanese keywords return far more.

## `categories` (type: `array`):

Only used when mode = search, ignored in URL mode. Browse a whole department instead of, or as well as, a keyword. Use a name from this list: womens, mens, baby_kids, bags, shoes, home_kitchen_art, food, events. The store files bags and shoes under each audience rather than as one store-wide department, so 'bags' browses the women's, men's and kids' bag departments and 'shoes' browses the women's, men's, kids' and baby shoe departments; each is covered in full. A store category code such as 28_011500 also works if you want a narrower sub-department: open the department on the site, refine it, and copy the cgid value out of the address bar. A code the store does not recognise is not an error on this site - it quietly returns the whole catalogue - so check that the department you copied really is the one you wanted.

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

Only used when mode = url, ignored in search mode. Mix freely: product pages under /shopping/product/<id>.html , keyword searches under /shopping/search , department listings under /shopping/productlist , brand listings under /shopping/brand/list , or a bare product id such as 900000000000000003062447 . The older /shopping/search-word keyword link and links on the bare mistore.jp host are accepted too. A link that is not one of these is skipped with a warning in the log.

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

The store's own result ordering. 'Recommended' is the store default.

## `badges` (type: `array`):

Optional. Keep only products carrying the store's own badges. Selecting more than one returns products carrying any of them, which is how the store's own refinement behaves.

## `colors` (type: `array`):

Optional. Keep only products available in these colour families, using the store's own colour grouping.

## `brandCodes` (type: `array`):

Optional. Keep only products from these brands, using the store's own brand codes. To get one: open a brand page on the site and copy the brand value out of the address bar, for example 002383 for ANTEPRIMA. Several codes can be given at once.

## `minPrice` (type: `integer`):

Optional. Only keep products priced at or above this many yen. Sent to the store as its own price refinement, so it narrows the results at the source rather than filtering afterwards.

## `maxPrice` (type: `integer`):

Optional. Only keep products priced at or below this many yen. Sent to the store as its own price refinement.

## `includeOutOfStock` (type: `boolean`):

Off by default, matching the store, which hides out of stock products. Turn on to include them: the store's own catalogue roughly doubles in size when they are shown.

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

Collect each product's full record: description, specification list, size and colour variants with per variant price, barcode and stock count, all gallery images, shipping and delivery terms, gift wrapping availability, payment methods, allergen panel and badge marks. Turn off for a faster, cheaper run that returns the listing fields only (id, title, brand, link, price band, sale flags, stock, colour options, image).

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

Off by default because it costs one extra request per product. Turn on to also collect each product's average rating, review count, rating breakdown and individual reviews (author, date, rating, title, text, helpful votes). Reviews are sparse on this catalogue, so most products come back with an empty reviews list and a null rating rather than invented zeros.

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

Cap on how many individual reviews are returned for one product. Only used when Fetch customer reviews is on. The rating and review count are always the store's own totals and are not affected by this cap.

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

Maximum number of products to return across the whole run. This is the run's cap and what you are billed for. Use 0 for unlimited.

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

Maximum number of result pages to take per keyword, department or pasted listing link. 0 = unlimited, which returns everything the store has for it. Each result page holds 60 products.

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

A Japanese residential exit is required and is the default (Apify Proxy, Residential group, country JP). Datacenter pools do not work for this store. Residential traffic is metered per use.

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

Paste a previous run ID or dataset ID to continue a large catalogue pull without returning or being charged for products already collected there. Use this after an interrupted run. For recurring monitoring of the same search, use Incremental mode below instead.

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

Turn this on for daily or recurring monitoring. The first run returns all matching products as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED products. A product is UPDATED when any field of its record changes (price, original price, sale flag, stock, variants, images, description, badges, category and so on). The scrape time and the order of badge and colour codes never count. New reviews and rating changes do count; to stop them, add reviews, rating, reviewCount and ratingBreakdown to Ignore fields. Turn on Emit unchanged or Emit expired only when you also want those products returned, and billed. State is kept separately for each combination of mode, keywords, departments, links, filters and enrichment settings; use State key when you want to name or deliberately share a monitoring campaign.

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

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently configured runs. Leave empty to let the actor derive a key automatically, so two different searches never mix state with each other.

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

Off by default. Turn on to also return products that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have, so leave it off unless you specifically want the full snapshot every run.

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

Off by default. Turn on to also return products that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search, not when Max products capped it and not when Resume was used. This returns, and bills, extra synthetic rows, so leave it off unless you need expiry tracking.

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

All (default) treats any change to a product's data as UPDATED. Price and availability only compares just the price, original price, discount, sale flag, stock and sale window of the product and of each variant (in a stable order), so description, image, badge and label changes never create an UPDATED row. Changing this setting without a State key starts a new auto-named campaign, so set a State key to keep your baseline.

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

Off by default. UPDATED and EXPIRED rows are returned slim: identifiers, current price and stock, priceChanges (old and new per moved field) and variantChanges (per changed, added or removed variant). NEW rows stay complete. A compact row does not carry the enriched product record, so the detail enrichment unit is not charged for it.

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

With Emit expired on, a product is marked EXPIRED only after it was missing from this many complete scans in a row (default 1). EXPIRED means the product was no longer found in the listing, not that it is unavailable: a listing drop and a delisting look the same without opening the product, so read the stock fields for availability.

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

Field names that never make a product UPDATED and never appear in changedFields, while staying in the output, for example thumbnails, images, or reviews, rating, reviewCount and ratingBreakdown to ignore review activity. Use a dotted path for a key inside a list, for example variants.image or variants.stock, which drops that key from every variant while the rest of the variant is still compared.

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

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

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

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

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

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

## Actor input object example

```json
{
  "mode": "search",
  "queries": [
    "バッグ"
  ],
  "categories": [],
  "urls": [
    "https://www.mistore.jp/shopping/search?q=%E3%83%90%E3%83%83%E3%82%B0",
    "https://www.mistore.jp/shopping/productlist?cgid=28_011500",
    "https://www.mistore.jp/shopping/productlist?cgid=28_011500&start=60&srule=inexpensive",
    "https://www.mistore.jp/shopping/productlist?cgid=28_011500&other=ref_sale_flg",
    "https://www.mistore.jp/shopping/productlist?cgid=28_011500&pmin=1000&pmax=5000",
    "https://www.mistore.jp/shopping/search?q=%E3%83%90%E3%83%83%E3%82%B0&srule=new-arrival&start=60",
    "https://www.mistore.jp/shopping/brand/list?brand=002383",
    "https://www.mistore.jp/shopping/product/900000000000000003062447.html",
    "https://mistore.jp/shopping/product/900000000000000003062447.html"
  ],
  "sortBy": "recommended",
  "badges": [],
  "colors": [],
  "brandCodes": [],
  "includeOutOfStock": false,
  "fetchDetails": true,
  "fetchReviews": false,
  "maxReviewsPerProduct": 20,
  "maxItems": 20,
  "maxPages": 0,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyCountry": "JP"
  },
  "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

# 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": [
        "バッグ"
    ],
    "categories": [],
    "urls": [
        "https://www.mistore.jp/shopping/search?q=%E3%83%90%E3%83%83%E3%82%B0",
        "https://www.mistore.jp/shopping/productlist?cgid=28_011500",
        "https://www.mistore.jp/shopping/productlist?cgid=28_011500&start=60&srule=inexpensive",
        "https://www.mistore.jp/shopping/productlist?cgid=28_011500&other=ref_sale_flg",
        "https://www.mistore.jp/shopping/productlist?cgid=28_011500&pmin=1000&pmax=5000",
        "https://www.mistore.jp/shopping/search?q=%E3%83%90%E3%83%83%E3%82%B0&srule=new-arrival&start=60",
        "https://www.mistore.jp/shopping/brand/list?brand=002383",
        "https://www.mistore.jp/shopping/product/900000000000000003062447.html",
        "https://mistore.jp/shopping/product/900000000000000003062447.html"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyCountry": "JP"
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "compactUpdates": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/mistore-jp-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": ["バッグ"],
    "categories": [],
    "urls": [
        "https://www.mistore.jp/shopping/search?q=%E3%83%90%E3%83%83%E3%82%B0",
        "https://www.mistore.jp/shopping/productlist?cgid=28_011500",
        "https://www.mistore.jp/shopping/productlist?cgid=28_011500&start=60&srule=inexpensive",
        "https://www.mistore.jp/shopping/productlist?cgid=28_011500&other=ref_sale_flg",
        "https://www.mistore.jp/shopping/productlist?cgid=28_011500&pmin=1000&pmax=5000",
        "https://www.mistore.jp/shopping/search?q=%E3%83%90%E3%83%83%E3%82%B0&srule=new-arrival&start=60",
        "https://www.mistore.jp/shopping/brand/list?brand=002383",
        "https://www.mistore.jp/shopping/product/900000000000000003062447.html",
        "https://mistore.jp/shopping/product/900000000000000003062447.html",
    ],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyCountry": "JP",
    },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "compactUpdates": False,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/mistore-jp-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": [
    "バッグ"
  ],
  "categories": [],
  "urls": [
    "https://www.mistore.jp/shopping/search?q=%E3%83%90%E3%83%83%E3%82%B0",
    "https://www.mistore.jp/shopping/productlist?cgid=28_011500",
    "https://www.mistore.jp/shopping/productlist?cgid=28_011500&start=60&srule=inexpensive",
    "https://www.mistore.jp/shopping/productlist?cgid=28_011500&other=ref_sale_flg",
    "https://www.mistore.jp/shopping/productlist?cgid=28_011500&pmin=1000&pmax=5000",
    "https://www.mistore.jp/shopping/search?q=%E3%83%90%E3%83%83%E3%82%B0&srule=new-arrival&start=60",
    "https://www.mistore.jp/shopping/brand/list?brand=002383",
    "https://www.mistore.jp/shopping/product/900000000000000003062447.html",
    "https://mistore.jp/shopping/product/900000000000000003062447.html"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyCountry": "JP"
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "compactUpdates": false
}' |
apify call abotapi/mistore-jp-scraper --silent --output-dataset

```

## MCP server setup

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