# Japan Stationery Rankings & Prices (文房具ランキング) (`magenta_courser/japan-stationery-rankings`) Actor

Pick a stationery category (pens, notebooks, planners, office, stickers...) and get Japanese bestseller rankings and prices from Rakuten, Amazon.co.jp, LOFT, MUJI, Hands and Itoya in one table: rank, JAN, maker, price in yen, rating, reviews, stock, with rank and price change since your last run.

- **URL**: https://apify.com/magenta_courser/japan-stationery-rankings.md
- **Developed by:** [SUNGHWAN CHO](https://apify.com/magenta_courser) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 products

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

## Japan Stationery Rankings & Prices (文房具ランキング) - Rakuten, Amazon JP, LOFT, MUJI, Hands, Itoya

Pick a stationery category (pens, notebooks, planners, office supplies, stickers...) and get the current Japanese bestseller rankings and prices from **Rakuten Ichiba (楽天ランキング)**, **Amazon.co.jp best sellers (売れ筋ランキング)**, **LOFT (ロフト)**, **MUJI (無印良品)**, **Hands (ハンズ, formerly Tokyu Hands)** and **Itoya (伊東屋)** in one table: rank, JAN code, maker (Pilot, Zebra, uni, Pentel, Kokuyo...), price in yen, sale flag, rating, review count and stock, plus **rank and price change since your last run**.

Built for buyers and resellers of Japanese stationery outside Japan, K-/J-stationery shops choosing what to import, and trend watchers who want to see which pens, notebooks and planners are selling in Japan this week.

### What you get

- **One row per product per list**, the same columns for every store.
- **Six Japanese sources** in one run; a store that fails does not stop the others and is not charged.
- **Rank and price tracking**: each list is compared with your previous run (`previousRank`, `rankChange`, `previousPrice`, `priceChange`, `isNewEntry`, `previousInStock`).
- **Changes-only mode**: `outputMode: changesOnly` saves (and charges) only products that are new in the ranking or whose rank, price or stock changed. Ideal for a daily schedule.
- **Maker detection** in English (`maker`), so "三菱鉛筆", "uni" and "ジェットストリーム" all become `Mitsubishi Pencil (uni)`.
- Names are NFKC-normalized (full-width "０．５ｍｍ" becomes "0.5mm"), text stays in Japanese.

### Sources

| source | What is read | Order / rank | Depth | Notes |
|---|---|---|---|---|
| `rakuten` | Rakuten Ichiba genre ranking (daily, weekly or realtime) | Rakuten rank | up to 1,000 | Names are shortened by Rakuten (end with "…"). Rating is the star display (0.5 steps). Shop name included, `sourceRankTrend` = up/down/same/new from Rakuten. |
| `amazon` | Amazon.co.jp best sellers (文房具・オフィス用品 and sub-categories) | Amazon rank | 100 | ASIN, rating, review count, lowest offer price ("from" price when several sellers). |
| `loft` | LOFT net store ranking (ステーショナリー) | LOFT rank | 40 (overall stationery ranking: 10) | JAN, brand, LOFT category, sale and LOFT-limited labels. A few seasonal rankings (e.g. 手帳) are shown without rank badges; then rank is the page position and RUN_SUMMARY has a warning. |
| `muji` | MUJI net store section in best-selling order (売れ筋順) | position | whole section | JAN, sale price and old price, stock. |
| `hands` | Hands net store category list (store's recommended order) | position | whole category | JAN, rating, reviews, net-store stock (inStock / lowStock / outOfStock). Uses a Japanese residential proxy automatically. |
| `itoya` | Itoya online store category, newest first | position | whole category | JAN, brand, price, out-of-stock tag. |

`listType` is `ranking` for real rankings (Rakuten, Amazon, LOFT, MUJI best-selling order) and `categoryList` for Hands and Itoya (their sites have no public ranking list; rank is the position in the list).

### Categories

| Preset | Rakuten | Amazon | LOFT | MUJI | Hands | Itoya |
|---|---|---|---|---|---|---|
| `all` (文房具 総合) | 文房具・事務用品 | 文房具・オフィス用品 | ステーショナリー | 文房具 | - | 筆記具 |
| `writing` (筆記具) | 筆記具 | 筆記具 | 筆記具 | 筆記用具・消しゴム | ボールペン | 筆記具 |
| `notebooks` (ノート) | 手帳・ノート・紙製品 | ノート・メモ帳 | ノート・ルーズリーフ | ノート・付箋 | ノート・メモ | ノート・メモ |
| `planners` (手帳) | - | 手帳・カレンダー | 手帳 | - | 手帳・ダイアリー | 手帳 |
| `office` (事務用品) | ファイル・バインダー | 事務用品 | 事務用品・ファイル | 事務小物 | ファイル | 事務用品 |
| `stickersTapes` | ラベル・ステッカー | - | マステ・シール・スタンプ | - | シール | - |
| `pencases` | - | - | ペンケース | ペンケース | ペンケース | - |
| `lettersCards` | - | 封筒・はがき・レター | カード・便箋・封筒 | カード・レター | レターセット | カード・便箋・封筒 |
| `calendars` | - | - | カレンダー | カレンダー | カレンダー | カレンダー |

Need another list? Paste any of these into **listUrls**:

- `https://ranking.rakuten.co.jp/daily/100926/` (any Rakuten genre ranking, daily/weekly/realtime)
- `https://www.amazon.co.jp/gp/bestsellers/office-products/89088051/` (any Amazon.co.jp best-seller category)
- `https://www.loft.co.jp/store/r/rr30104/` (LOFT ranking)
- `https://www.muji.com/jp/ja/store/cmdty/section/S1070105` (MUJI section)
- `https://hands.net/cate/stationery/seal/` (Hands category)
- `https://www.ito-ya.co.jp/category/E5/` (Itoya category)

### Input example

```json
{
  "categories": ["writing", "notebooks"],
  "sources": ["rakuten", "amazon", "loft", "muji", "hands", "itoya"],
  "maxItems": 50,
  "outputMode": "all"
}
```

For a daily tracker, schedule the same input with `"outputMode": "changesOnly"`.

### Output example

```json
{
  "source": "amazon",
  "rankingName": "筆記具",
  "listType": "ranking",
  "category": "writing",
  "rank": 1,
  "productId": "B0BZD3R23R",
  "asin": "B0BZD3R23R",
  "janCode": null,
  "name": "三菱鉛筆 ボールペン替芯 ジェットストリーム 多色多機能 0.38mm 黒 5本 SXR8038K5P.24",
  "brand": null,
  "maker": "Mitsubishi Pencil (uni)",
  "price": 348,
  "currency": "JPY",
  "priceIsFrom": false,
  "rating": 4.6,
  "reviewCount": 1796,
  "stockStatus": null,
  "previousRank": 3,
  "rankChange": 2,
  "previousPrice": 348,
  "priceChange": 0,
  "isNewEntry": false,
  "url": "https://www.amazon.co.jp/dp/B0BZD3R23R",
  "scrapedAt": "2026-10-30T11:20:00.000Z"
}
```

Main fields: `source`, `sourceName`, `listType`, `rankingName`, `category`, `categoryId`, `period` (Rakuten), `rank`, `productId`, `janCode`, `asin`, `itemCode` (Rakuten shop:item), `name`, `brand`, `maker`, `shopName` (Rakuten), `productCategory` (LOFT), `price`, `priceIsFrom`, `originalPrice`, `isOnSale`, `labels`, `rating`, `reviewCount`, `inStock`, `stockStatus`, `sourceRankTrend`, `imageUrl`, `url`, `previousRank`, `rankChange` (positive = moved up), `previousPrice`, `priceChange`, `priceChangePercent`, `previousInStock`, `isNewEntry`, `previousScrapedAt`, `listUrl`, `scrapedAt`. Missing values are `null`; every row has every field.

A `RUN_SUMMARY` record in the key-value store lists each source and list with status (`completed`, `partial`, `failed`, `budgetLimited`), the stop reason and the number of products saved.

### Pricing

Pay per product row saved (event `product`). Lists that fail and products skipped by `changesOnly` are free. When your "Maximum cost per run" is reached, the run stops cleanly with the message "Stopped at the maximum cost per run" and keeps everything saved so far.

### Notes and limits

- Prices are the yen prices shown on each store (tax included). Amazon prices are the lowest offer shown in the ranking; Rakuten prices are the shop's price ("from" when the item has variations).
- Rating and review count are not shown by LOFT, MUJI and Itoya lists (`null`).
- `janCode` is filled only when the store's product code is a valid JAN (EAN-13). Amazon rows have the ASIN instead.
- Hands answers only Japanese IPs. The Actor uses Apify's RESIDENTIAL proxy with country JP for Hands automatically. If your plan has no residential proxy, Hands lists fail (free) and the other sources still run.
- Only public product lists are read; no login, no personal data. The Actor never solves captchas: if a store shows a robot check, it retries with a new IP and otherwise reports that list as failed.
- Store layouts change; if a source stops returning rows, please open an issue.

# Actor input Schema

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

Stationery categories, mapped to the matching ranking or category list of every selected source. Sources without a matching list are skipped (free).

## `sources` (type: `array`):

Which stores to read. rakuten = Rakuten Ichiba ranking (楽天ランキング), amazon = Amazon.co.jp best sellers (売れ筋ランキング), loft = LOFT net store ranking, muji = MUJI net store in best-selling order, hands = Hands net store category list (needs a Japanese residential proxy, used automatically), itoya = Itoya (伊東屋) online store, newest first. Leave empty for all six.

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

Maximum products per source and category. Natural limits: Amazon 100, LOFT 40 (overall stationery 10), Rakuten 1,000. 6 sources x 1 category x 50 = up to about 290 rows.

## `listUrls` (type: `array`):

Any supported list, e.g. https://ranking.rakuten.co.jp/daily/100926/, https://www.amazon.co.jp/gp/bestsellers/office-products/89088051/, https://www.loft.co.jp/store/r/rr30104/, https://www.muji.com/jp/ja/store/cmdty/section/S1070105, https://hands.net/cate/stationery/seal/ or https://www.ito-ya.co.jp/category/E5/.

## `rakutenPeriod` (type: `string`):

Rakuten ranking type for preset categories (a pasted Rakuten URL keeps its own period).

## `compareWithLastRun` (type: `boolean`):

Adds previousRank, rankChange (positive = moved up), previousPrice, priceChange, priceChangePercent, previousInStock and isNewEntry compared with the last completed run of the same list (kept in a named key-value store).

## `outputMode` (type: `string`):

changesOnly saves (and charges) only products that are new in the list or whose rank, price or stock changed since the last run. The first run of each list saves everything.

## `historyStoreName` (type: `string`):

Named key-value store that keeps the last ranks and prices. Use a different name to keep separate histories (e.g. per schedule).

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

Apify Proxy for Rakuten, Amazon, LOFT, MUJI and Itoya. The default datacenter proxy works for them.

## `useJapanResidentialForHands` (type: `boolean`):

Hands refuses datacenter IPs, so its requests go through Apify RESIDENTIAL proxy with country JP. Turn off only if your account has no residential proxy (Hands lists will then fail, free of charge).

## Actor input object example

```json
{
  "categories": [
    "writing"
  ],
  "sources": [
    "rakuten",
    "amazon",
    "loft",
    "muji",
    "hands",
    "itoya"
  ],
  "maxItems": 20,
  "rakutenPeriod": "daily",
  "compareWithLastRun": true,
  "outputMode": "all",
  "historyStoreName": "japan-stationery-rank-history",
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "useJapanResidentialForHands": true
}
```

# Actor output Schema

## `products` (type: `string`):

One row per product per list (source + ranking or category), with rank, JAN, maker, price in JPY, rating, reviews, stock and rank/price change since the last run.

## `runSummary` (type: `string`):

Per source and per list: status (completed, partial, failed, budgetLimited, notStarted), stopReason, productsSaved and errors. Failed lists are not charged.

# 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 = {
    "categories": [
        "writing"
    ],
    "sources": [
        "rakuten",
        "amazon",
        "loft",
        "muji",
        "hands",
        "itoya"
    ],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("magenta_courser/japan-stationery-rankings").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 = {
    "categories": ["writing"],
    "sources": [
        "rakuten",
        "amazon",
        "loft",
        "muji",
        "hands",
        "itoya",
    ],
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("magenta_courser/japan-stationery-rankings").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 '{
  "categories": [
    "writing"
  ],
  "sources": [
    "rakuten",
    "amazon",
    "loft",
    "muji",
    "hands",
    "itoya"
  ],
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call magenta_courser/japan-stationery-rankings --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,magenta_courser/japan-stationery-rankings"
        }
    }
}
```

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/ptpkMoT4NQspcOjP9/builds/jjF2NZwOFFPc5eK3n/openapi.json
