# Japan Used Guitar & Instrument Market — Search & Price Alerts (`keiya_dev/japan-used-instrument-market`) Actor

Search, benchmark and monitor used guitars, basses and wind instruments from Japanese shops (Hard Off, Shimokura Gakki) in one schema: Fender Japan / USA split, Made in Japan flag, production year & era, case, Reverb-style condition, JPY/USD. Median prices, price history, NEW / PRICE_DROP alerts.

- **URL**: https://apify.com/keiya_dev/japan-used-instrument-market.md
- **Developed by:** [Keiya](https://apify.com/keiya_dev) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 listings

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 Used Guitar & Instrument Market: Fender Japan, MIJ & more — Search, Stats, History & Alerts

### Quick start

1. Click **Try for free** / open the Actor in Apify Console.
2. Keep the prefilled input (`{"mode": "search", "sources": ["shimokura", "jguitar", "ishibashi", "shimamura", "ikebe", "offmall"], "keywords": ["Fender Japan"], "maxItems": 10}`) or type your own: a brand ("Tokai", "Greco"), a model ("Jazzmaster") or a model code ("ST57-70TX", "JB62").
3. Press **Start**. Listings appear in the Output tab in under a minute, with **brand split by country (Fender Japan / USA / Mexico), a Made-in flag, production year and era, case, a Reverb-style condition and the price in JPY and USD**.

**Example output** — 3 real rows from the prefilled run above (run on 2026-11-05; prices and stock change daily):

```json
[
  {
    "source": "shimokura",
    "sourceName": "Shimokura Gakki",
    "sourceItemId": "126659",
    "url": "https://www.shimokura-webshop.com/products/detail/126659",
    "title": "Japan Exclusive Classic 50s Stratocaster Texas Special",
    "brand": "Fender Japan",
    "brandJa": null,
    "brandRaw": "Fender Japan",
    "ref": null,
    "model": "fender japan japan exclusive classic 50s stratocaster texas special",
    "instrumentType": "electric guitar",
    "madeIn": "Japan",
    "madeInSource": "title",
    "year": 2015,
    "yearFrom": 2015,
    "yearTo": 2015,
    "era": "2010s",
    "accessories": {
      "caseType": "soft",
      "originalCase": false,
      "summary": "soft case",
      "raw": "ソフトケース"
    },
    "shop": "ハンズ1号",
    "conditionGrade": null,
    "conditionGradeRaw": null,
    "reverbCondition": null,
    "priceJpy": 137500,
    "inStock": true,
    "category": "used",
    "scrapedAt": "2026-11-05T12:49:30.272Z",
    "priceUsd": 868.88,
    "fxJpyPerUsd": 158.25
  },
  {
    "source": "ikebe",
    "sourceName": "Ikebe Music",
    "sourceItemId": "872018",
    "url": "https://www.ikebe-gakki.com/Form/Product/ProductDetail.aspx?shop=0&pid=872018&bid=ec",
    "title": "TL52-80TX[SN.A031738] フェンダージャパン",
    "brand": "Fender Japan",
    "brandJa": null,
    "brandRaw": "Fender Japan",
    "ref": "TL52-80TX",
    "model": "fender japan tl52-80tx",
    "instrumentType": "electric guitar",
    "madeIn": "Japan",
    "madeInSource": "brand",
    "year": null,
    "yearFrom": null,
    "yearTo": null,
    "era": null,
    "accessories": null,
    "shop": "イケシブリユース",
    "conditionGrade": null,
    "conditionGradeRaw": null,
    "reverbCondition": null,
    "priceJpy": 138001,
    "inStock": true,
    "category": "used",
    "scrapedAt": "2026-11-05T12:49:33.057Z",
    "priceUsd": 872.04,
    "fxJpyPerUsd": 158.25
  },
  {
    "source": "shimamura",
    "sourceName": "Shimamura Music",
    "sourceItemId": "tp107-0882632",
    "url": "https://store.shimamura.co.jp/ec/pro/disp/1/tp107-0882632",
    "title": "Made in Japan Traditional 60s Mustang (2022年製)",
    "brand": "Fender Japan",
    "brandJa": null,
    "brandRaw": "Fender",
    "ref": null,
    "model": "fender japan traditional 60s mustang",
    "instrumentType": "electric guitar",
    "madeIn": "Japan",
    "madeInSource": "title",
    "year": 2022,
    "yearFrom": 2022,
    "yearTo": 2022,
    "era": "2020s",
    "accessories": {
      "caseType": "soft",
      "originalCase": false,
      "summary": "soft case",
      "raw": "ソフトケース"
    },
    "shop": "イオン新浦安店",
    "conditionGrade": null,
    "conditionGradeRaw": null,
    "reverbCondition": null,
    "priceJpy": 117980,
    "inStock": true,
    "category": "used",
    "scrapedAt": "2026-11-05T12:49:33.084Z",
    "priceUsd": 745.53,
    "fxJpyPerUsd": 158.25
  }
]
```

Japan is where the good used guitars are: 80s and 90s Fender Japan (JV / E / A serials), Made in Japan Tokai, Greco, ESP, Navigator and Momose, Yamaha and Yanagisawa saxophones, at prices well below Reverb and eBay. The listings are only in Japanese, each shop words things differently, and "Made in Japan" is buried in a brand label or a staff comment. This Actor turns Japanese shops (and the dozens of shops on J-Guitar) into one clean, English dataset you can pipe into Google Sheets, n8n, Slack, Discord or your own pricing model.

### Who uses it

| You are… | You use… |
|---|---|
| **A Reverb or eBay seller** sourcing from Japan | `search` with a grade floor and a max price; `reverbCondition` is ready to paste; `monitor` to be first on new stock |
| **A Made in Japan collector** (Fender Japan, Tokai, Greco, Burny, ESP…) | `search` / `monitor` on a brand or model code; filter on `madeIn: "Japan"`, `era: "1980s"`, `accessories.caseType: "hard"` |
| **A vintage Fender Japan hunter** | `monitor` on "Fender Japan" or a code ("ST57", "TL52", "JB62") with alerts to Discord; `history` for how the Japanese median moves |
| **A dealer benchmarking Japanese prices** | `stats` (median per model, by shop and grade) and `history` |

### Shops

| Shop | Id | Listings | What you get |
|---|---|---|---|
| **Shimokura Gakki** (下倉楽器: Ochanomizu, Omiya, Hachioji and the "Second Hands" used-guitar shops) | `shimokura` | ~1,400 used instruments: electric / acoustic / classical guitars, basses, ukuleles, woodwinds, brass, effects | **no shop grade** (`conditionGrade` is `null`; the shop writes a free-text condition note instead). Brand as the shop labels it ("Fender Japan", "FENDER USA"), model, **production year from the title** ("2010～2012年製"), branch, price. From the product page: **case** ("original hard case") and year |
| **J-Guitar** (Jギター: a **marketplace listing shops across Japan**: Kurosawa, Gakkido, Woodman, Yamano, Miki Acoustic INN, Shimokura and more) | `jguitar` | ~11,000 used instruments on sale (guitars, basses, amps, effects…) | **one condition scale for all shops** (5\[M] … 1\[P]), brand, model, year, price, and **the listing shop in `shop`**: one J-Guitar search covers dozens of shops at once. From the product page: brand label, model code, category, **case** |
| **Ishibashi Music** (イシバシ楽器, 12 stores: Ochanomizu, Shinjuku, Shibuya, Yokohama, Umeda, Fukuoka…) | `ishibashi` | ~8,500 used instruments (guitars, effects, basses, amps, drums, wind instruments, keyboards…) | brand / model, **its 7-step rank** (S / A+ / A / B+ / B / C+ / C, read per rank list), price, store. From the product page: category, **case** |
| **Shimamura Music** (島村楽器, stores nationwide, mostly in shopping malls) | `shimamura` | ~5,500 used instruments (guitars, basses, keyboards, wind instruments, drums…) | **no shop grade** (`conditionGrade` is `null`), brand, model, **production year from the title**, price, store, stock (sold cards stay listed as 在庫切れ). From the product page: category, **case** |
| **Ikebe Music** (イケベ楽器, Shibuya / Akihabara / Osaka specialist stores) | `ikebe` | ~1,400 used and vintage instruments | **no shop grade** (`conditionGrade` is `null`), maker, model, price, category. From the product page: store, **case** |
| **Hard Off Off Mall** (ハードオフ オフモール, stores nationwide) | `offmall` | ~13,000 on sale: electric and acoustic guitars, basses, woodwinds, brass | brand, model code, grade N / S / A / B / C / D / ジャンク, price. From the product page: **case**, store, and year / "Crafted in Japan" from the staff comment |

Shimokura lists part of its stock on J-Guitar too, so a few instruments can appear twice (`shimokura` and `jguitar` with `shop: "下倉楽器 …"`).

**Shops not included**

| Shop | Why |
|---|---|
| Miki Gakki, Kurosawa Gakki, Woodman and other J-Guitar shops | **covered elsewhere**: their used stock is read through J-Guitar |
| Digimart (デジマート) | **blocked**: Cloudflare challenge to plain requests |

Want a shop added? Open an issue on the Actor page.

### What you can do

| Mode | What it does |
|---|---|
| **search** | Listings matching keywords / brands / grades / price. Keywords match brand + title in English or Japanese, **and model codes**. For each listing in the result, the product page is read once to add **case, store, year and country** when the listing itself doesn't say. |
| **stats** | Per-model summary of in-stock listings: count, **min / median / max** in JPY and USD, broken down by shop and grade, plus the cheapest listing. Models are grouped by **brand + model code**, so the same guitar groups across shops. |
| **monitor** | Run on a schedule. It keeps a snapshot and emits **only what changed**: `NEW`, `PRICE_DROP`, `PRICE_UP`, `SOLD_OUT`. An optional webhook goes to Slack / Discord / n8n / Make / Zapier. |
| **history** | Daily min / median / count per model, by shop and grade, from stored daily snapshots. There is no crawling, so it returns in seconds. Needs `keywords`, `brands` or `models`. |
| **deals** | In-stock listings at least `dealThresholdPct` % (default 15) **under the median of the same model in the same grade or better**, best `dealScore` first. Statistics only. See [Deals](#deals). |

### Made in Japan (`madeIn`) and the Fender split

`madeIn` is the country of manufacture: `Japan`, `USA`, `Mexico`, `Korea`, `Indonesia`, `China`, `France`, `Germany`, or `null` when nothing says. `madeInSource` tells you where it came from, in this order of trust:

1. **`title`**: the listing says it ("Made in Japan", "日本製", "Crafted in Japan", "MIJ"), or names a one-country model line ("American Standard", "American Vintage" → USA).
2. **`brand`**: the shop's brand label carries the country ("FENDER JAPAN", "FENDER MEXICO"), or the brand builds in one country only (Gibson → USA; ESP, Momose, Navigator, Yanagisawa, Muramatsu → Japan). Brands that also build abroad (Tokai, Yamaha, Ibanez, Epiphone, Squier…) are **not** assumed.
3. **`product-page`**: the staff comment says it ("CRAFTED IN JAPAN Rシリアル").

Phrases about parts ("USA製ピックアップ", "USA pickups") are ignored, and so is the "US" at the end of Fender Japan codes like "ST57-58US".

**Fender is named by country**, because that is how buyers search and price it: `Fender Japan`, `Fender USA`, `Fender Mexico`, or plain `Fender` when the country is not stated. `Fender Japan` covers both the 1982–2015 Fender Japan era and today's "Fender Made in Japan" line: use `year` / `era` to tell them apart. A model line beats a sloppy label: a listing labelled "Fender Japan" but titled "American Performer Stratocaster" is `Fender USA`. The shop's own label is kept in `brandRaw`.

### Production year and era (`year`, `yearFrom`, `yearTo`, `era`)

From the shop's wording: "2013年製" → `year: 2013`, `era: "2010s"`; "2010～2012年製" → `yearFrom: 2010`, `yearTo: 2012`; "80年代製" or "1980s" → `era: "1980s"`; a lone year at the end of a title ("ST72-75 NAT 1993") → 1993. For listings that don't say, the product page is checked ("シリアルから2004~2006年製であると思われます" → 2004–2006).

**Style names are not dates.** "Traditional 60s", "'50s", "60年代仕様", "1957年モデル" and "American Vintage II 1957" describe the spec of the guitar, not when it was made, and are ignored. Off Mall's "発売日" (the model's release year) is not used either.

### Case (`accessories`)

```json
"accessories": { "caseType": "hard", "originalCase": true, "summary": "original hard case", "raw": "オリジナルハードケース" }
```

`caseType` is `hard`, `semi-hard`, `soft` (gig bag), `none`, or `null` when a case is mentioned without its type. It is read from the shop's own accessories field on the product page (Shimokura "付属品", Off Mall "付属品"). That field lists everything included, so a field without a case means `none`. Without a product page (stats, history), it comes from the title only when the title names a case, otherwise `null`.

### Condition grades, normalized to Reverb's scale

`BRAND_NEW` > `MINT` > `EXCELLENT` > `VERY_GOOD` > `GOOD` > `FAIR` > `POOR` > `NON_FUNCTIONING`. `reverbCondition` holds Reverb's display name ("Very Good"), and the shop's own label is always kept in `conditionGradeRaw`.

| Shop | Raw → normalized |
|---|---|
| Off Mall | N 新品・未開封 → BRAND_NEW · S 新品同様・廃盤 → MINT · A 使用回数の少ない美品 → EXCELLENT · B 日常使用・傷汚少 → VERY_GOOD · C 使用感・傷汚れ多 → GOOD · D ダメージ多 → FAIR · ジャンク (sold as is, no warranty) → NON_FUNCTIONING |
| J-Guitar | 5\[M] 新品同様 → MINT · 4+\[NM] ほぼ新品同様 / 4\[EX+] 年代から見て状態が良い → EXCELLENT · 3+\[EX] 年代相応 / 3\[EX-] ほぼ標準的 → VERY_GOOD · 2+\[VG+] / 2\[VG] 演奏上の問題なし → GOOD · 1+\[G] 少し難あり → FAIR · 1\[P] 修理が必要 → POOR |
| Ishibashi | S 新品 → BRAND_NEW · A＋ 新品同様 → MINT · A 美品 → EXCELLENT · B＋ 多少傷あり・使用に問題なし → VERY_GOOD · B 傷・使用感あり・使用に問題なし → GOOD · C＋ 修理が必要 → POOR · C ジャンク → NON_FUNCTIONING |
| Shimokura, Shimamura, Ikebe | not graded: `conditionGrade` is `null`; the product page has a free-text note instead |

Filtering by `grades` therefore drops all Shimokura, Shimamura and Ikebe listings.

### Deals

`deals` mode reads the same listings as `stats`, then compares each in-stock listing with the **other listings of the same model** (same `model` key) **in the same grade or better**, and returns only those at least `dealThresholdPct` % under that median:

```json
{ "mode": "deals", "keywords": ["Fender Japan"], "dealThresholdPct": 15, "maxItems": 0 }
```

Each deal is a normal listing plus:

| Field | Meaning |
|---|---|
| `medianJpy` (`medianUsd`) | median price of the listings it was compared with |
| `comparisonCount` | how many listings that median is based on |
| `discountPct` | how far under the median, in % |
| `dealScore` | 0–100: the discount (40 % off = full marks) weighted by `comparisonCount` (1 → 60 %, 5 or more → 100 %). **Capped at 50 when `comparisonCount` is 2 or less** (low confidence) |

- Models with nothing to compare against are not returned. Grades sold as is (`NON_FUNCTIONING`) are neither returned nor used as comparisons. Shimokura prints no grade, so its listings are compared with every other listing of the model; an ungraded listing is never used to judge a graded one.
- The market is the listings this run read: use `maxItems: 0` (whole shops) or a keyword that covers the whole model, so every listing of "fender japan st57-70tx" is compared.
- No LLM is involved; it is the same arithmetic as `stats`.

**Deal alerts.** In `monitor` mode, `"dealsOnly": true` outputs and sends only the `NEW` / `PRICE_DROP` events that are deals against the listings that monitor tracks, with the same four fields. They are charged as normal monitor events.

**Daily deal digest.** In `deals` mode, set `alertWebhookUrl` (Slack, Discord or any URL) and the best `dealsWebhookTop` deals (default 10, highest `dealScore` first, ties broken by the deeper discount) are POSTed once per run, one line each: score, discount, grade, title, price vs median, link. Schedule it every morning (e.g. `0 7 * * *`, `maxItems: 0`) for a short list of the day's best-priced listings; the dataset still holds every deal.

**English summaries (optional, your own LLM key).** `"summarize": true` with `llmApiKey` (stored encrypted) adds `summaryEn` to every listing in `search` and `deals` mode, e.g. "Fender Japan ST57-70TX, 1990s, Very Good, soft case, 22% under Japan median". `llmProvider` is `anthropic` (default, Claude Haiku `claude-haiku-5-5`) or `openai` (`gpt-5-mini`); `llmModel` overrides the model. Listings are sent 25 per request, so the cost grows with the number of listings: with Claude Haiku, **100 listings ≈ $0.003, well under $0.01**. Your provider bills your key; the Actor charges nothing extra. Without a key the option is skipped with a warning, and an LLM error never fails the run (the listings are returned without `summaryEn`).

### Input

```json
{
  "mode": "search",
  "sources": ["shimokura", "jguitar", "offmall"],
  "keywords": ["Fender Japan", "Tokai"],
  "grades": ["MINT", "EXCELLENT", "VERY_GOOD"],
  "maxPriceJpy": 150000,
  "maxItems": 30
}
```

Monitor example (schedule it hourly):

```json
{
  "mode": "monitor",
  "sources": ["shimokura", "jguitar", "offmall"],
  "keywords": ["Fender Japan", "ST57", "JB62"],
  "alertWebhookUrl": "https://discord.com/api/webhooks/XXX/YYY",
  "alertEvents": ["NEW", "PRICE_DROP"]
}
```

The first monitor run only builds the snapshot and emits nothing. Each monitor keeps one snapshot per shop, keyed by its filters. Give each schedule a distinct `monitorId` if several use the same filters.

**Request budget:**

- Every request is one listing page (Shimokura 40 instruments, J-Guitar 50, Ishibashi 72, Shimamura 80, Ikebe 80, Off Mall 30), read newest-first. Shimokura has 8 category lists, J-Guitar 1, Ishibashi 7 (one per rank), Shimamura 1, Ikebe 2 (used, vintage), Off Mall 5.
- An hourly light monitor is normally **24 requests**, plus one product page per new listing.
- `"fullScan": true` reads everything: **Shimokura ≈ 40 pages (~2 min), J-Guitar ≈ 224 pages (~30 min), Ishibashi ≈ 121 pages (~4 min), Shimamura ≈ 69 pages (~7 min), Ikebe ≈ 19 pages (~1 min), Off Mall ≈ 440 pages (~8 min)**. A good setup is a frequent light monitor plus a daily full scan of Shimokura, Ishibashi, Shimamura and Ikebe.

### Price history since 2026-11-05

The Actor's own scheduled full scans store the complete inventory of each shop: **Shimokura, Ishibashi, Shimamura and Ikebe every day** (the last three from 2026-11-05), **J-Guitar and Off Mall once a week, on Sundays**. `history` mode reads those snapshots:

```json
{ "mode": "history", "models": ["fender japan st57-70tx", "fender japan jb62-58"], "days": 90 }
```

Each row is one model × day: `count`, `minJpy`, `medianJpy`, `maxJpy`, plus `byShop`, `byGrade` and `byShopGrade`.

- **History is still being collected.** Treat the first 30 days as indicative only.
- Off Mall numbers appear on Sunday rows only, so compare them week to week.

### Output

```json
{
  "source": "offmall",
  "sourceName": "Hard Off (Off Mall)",
  "sourceItemId": "6669970",
  "url": "https://netmall.hardoff.co.jp/product/6669970/",
  "title": "JB62-58 (エレキベース)",
  "brand": "Fender Japan",
  "brandRaw": "FENDER JAPAN",
  "ref": "JB62-58",
  "model": "fender japan jb62-58",
  "instrumentType": "bass",
  "madeIn": "Japan",
  "madeInSource": "brand",
  "year": 2002, "yearFrom": 2002, "yearTo": 2002, "era": "2000s",
  "conditionGrade": "VERY_GOOD",
  "conditionGradeRaw": "B",
  "reverbCondition": "Very Good",
  "accessories": { "caseType": "soft", "originalCase": false, "summary": "soft case", "raw": "ソフトケース" },
  "shop": "ハードオフ東大阪若江店",
  "priceJpy": 88000,
  "priceUsd": 555.94,
  "fxJpyPerUsd": 158.29,
  "inStock": true,
  "category": "used",
  "scrapedAt": "2026-11-04T08:45:29.866Z"
}
```

`stats` rows and monitor events have the same shape as in the [camera Actor](https://apify.com/keiya_dev/japan-used-camera-market): stats adds `count`, `minJpy`, `medianJpy`, `maxJpy`, `byShop`, `byGrade`; events add `eventType` and the price change.

### Pricing

Pay per event, no subscription:

| Event | Price |
|---|---|
| `listing` (search mode, per listing) | $0.003 |
| `model-stats` (stats mode, per model row) | $0.005 |
| `alert-event` (monitor mode, per NEW / PRICE_DROP / PRICE_UP / SOLD_OUT) | $0.01 |
| `history-row` (history mode, per model × day row) | $0.002 |
| `deal-row` (deals mode, per deal returned) | $0.005 |

Higher Apify plans get progressively lower prices (Bronze / Silver / Gold discounts).

### Integrations

- **Google Sheets**: Apify → Integrations → Google Sheets.
- **Slack / Discord**: paste an incoming-webhook URL into `alertWebhookUrl`.
- **n8n / Make / Zapier**: the Apify node, or point `alertWebhookUrl` at a webhook trigger.
- **AI agents**: see the next section.

### AI agents (MCP)

A dedicated MCP server, [`@keiya-dev/japan-used-market-mcp`](https://github.com/Enu27/japan-used-market-mcp) (open source, MIT), gives Claude, Cursor and other MCP clients tools backed by this Actor. Pass `"market": "instrument"` (the server also covers used cameras, its default, and watches):

| Tool | Mode |
|---|---|
| `search_listings` | search, with Made-in, year / era, case and Reverb condition |
| `price_stats` | stats |
| `price_history` | history |
| `start_monitor` | creates a scheduled monitor (Task + Schedule) in your Apify account |
| `list_markets` | shops and grades per market (no run) |

**Claude Desktop**: add this to `claude_desktop_config.json`. On macOS it is `~/Library/Application Support/Claude/claude_desktop_config.json`; on Windows, `%APPDATA%\Claude\claude_desktop_config.json`. Then restart the app:

```json
{
  "mcpServers": {
    "japan-used-market": {
      "command": "npx",
      "args": ["-y", "@keiya-dev/japan-used-market-mcp"],
      "env": { "APIFY_TOKEN": "apify_api_..." }
    }
  }
}
```

Get the token at Apify Console → Settings → API & Integrations. Runs are billed to your Apify account, as with any other run.

Then just ask: *"Find a Made in Japan Fender Jazz Bass from the 80s with a hard case under $1,000"*, *"What's the median price of a Fender Japan ST57-70TX in Japan?"*, *"Alert me on Discord when a new Tokai Love Rock appears."*

**Claude Code**: `claude mcp add japan-used-market -e APIFY_TOKEN=apify_api_... -- npx -y @keiya-dev/japan-used-market-mcp`

**Remote / HTTP clients**: run `npx -y @keiya-dev/japan-used-market-mcp --http --port 3000`. The endpoint is `/mcp` (Streamable HTTP); send your token as `Authorization: Bearer <APIFY_TOKEN>`.

The generic [Apify MCP server](https://mcp.apify.com) also works: add the Actor `keiya_dev/japan-used-instrument-market` as a tool.

### Limitations & fair use

- We read only public listing pages at low request rates and return factual listing data: brand, model / code, price, condition grade, stock, shop and URL. Product photos and the shops' own description text are not copied into the output.
- Prices are the shops' tax-included asking prices (税込), not sold prices. USD is a mid-market conversion for convenience. Shipping is not included.
- `madeIn`, `year` and `case` come from the shops' own words. When a shop doesn't say, the field is `null`: nothing is guessed from serial numbers.
- Only public listing pages and the product pages of returned or alerted listings are read. There is no login, no search endpoint and no sort parameter that robots.txt forbids.
- Shimokura, J-Guitar (販売中 filter), Ishibashi, Ikebe and Off Mall list instruments on sale only; Shimamura keeps sold cards at the end of its list as 在庫切れ (`inStock: false`). A sold instrument disappears, and `SOLD_OUT` for it is detected on full scans.
- If a shop's bot protection challenges a run, a page can't be loaded or a shop changes its layout, the run fails with a message saying what to do. It writes no partial data, charges nothing and leaves the monitor snapshot unchanged. A category the shop itself reports as empty today is skipped, not treated as an error.
- Not affiliated with any of the shops.

### Changelog

- **2026-11-05 — keywords: words are AND'ed.** A keyword with several words now matches listings that contain *all* of its words, in any order and position ("Fender Japan Jazzmaster" no longer needs the words side by side). Keywords are still OR'ed with each other. **Compatibility:** single-word keywords and phrases that appeared side by side still match, but a multi-word keyword can now match more listings than before (e.g. Leica M → "leica" + "m", and "m" is in "mm"). To keep the old exact-phrase behaviour, wrap the keyword in double quotes: `"\"Leica M\""` in JSON, `"Leica M"` in the Console. Monitors whose keywords change get a fresh baseline unless they set a `monitorId`.
- **0.3** (2026-11-05): **J-Guitar** (~11,000 used instruments from many shops, its 9-step condition scale mapped to Reverb's, the listing shop in `shop`), **Ishibashi Music** (~8,500 used instruments from its 12 stores, 7-step rank), **Shimamura Music** (~5,500 used instruments, not graded) and **Ikebe Music** (~1,400 used and vintage instruments, not graded) as new sources.
- **0.2** (2026-11-05): `deals` mode (listings under the same-model, same-or-better-grade median, with `dealScore`), `dealsOnly` for monitor alerts, optional English `summaryEn` with your own Anthropic / OpenAI key. Output is factual listing data only: `imageUrl` and the shops' free-text notes are no longer returned.
- **0.1** (2026-11-04): Shimokura Gakki (all used instruments, no shop grade) and Hard Off Off Mall (guitars, basses, woodwinds, brass). Search / stats / monitor / history, Fender split by country, `madeIn`, year / era, case, Reverb-scale grades.

### Related

- [Japan Used Camera Market](https://apify.com/keiya_dev/japan-used-camera-market): the same five modes for used cameras and lenses (Fujiya Camera, Sanpou Camera, Naniwa, Hard Off).
- [Japan Used Watch Market](https://apify.com/keiya_dev/japan-used-watch-market): Grand Seiko, Rolex and more from WATCHNIAN and Hard Off.
- [Japan Used Model Train Market](https://apify.com/keiya_dev/japan-used-model-train-market): KATO, TOMIX and MicroAce N / HO trains with product codes, scale and motor flag, from Hobbyland Pochi and Hard Off.

***

If this saved you a trip to Ochanomizu, a review on the Store helps others find it.

### 日本の方へ

下倉楽器・ハードオフの中古ギター・ベース・管楽器の在庫を、英語の統一形式（状態ランク・円とドル価格つき）で取り出す Actor です。

- **海外転売の仕入れ監視**：`monitor` モードを Schedule で定期実行し、新着（NEW）や値下げ（PRICE_DROP）を Slack / Discord に通知
- **相場確認**：`stats` / `history` モードで、モデルごとの最安・中央値・最高値と日々の推移を確認
- **割安出品の発見**：`deals` モードで、同じモデル・同ランク以上の中央値より安い出品だけを抽出

**使い方（Quick start）**：Apify Console でこの Actor を開き、Input の **Mode**（`search` / `stats` / `deals` / `monitor` / `history`）を選んで **Keywords** に "Fender Japan", "ST57", "Tokai" などを入れ、**Start** を押すだけです。結果は Output タブに表示され、CSV や Excel でダウンロードできます。

**料金の円換算目安**（1ドル＝150円で概算。実際の請求はドル建てで、為替により変わります）：

| 内容 | ドル | 円の目安 |
|---|---|---|
| 出品データ 1,000件（search） | $3 | 約450円 |
| モデル集計 1行（stats） | $0.005 | 約0.75円 |
| 割安出品 1件（deals） | $0.005 | 約0.75円 |
| アラート 1件（monitor） | $0.01 | 約1.5円 |
| 価格履歴 1行（history） | $0.002 | 約0.3円 |

Apify の上位プランでは割引（Bronze / Silver / Gold）が自動で適用されます。英語の要約（summarize）を使う場合は、ご自身の Anthropic / OpenAI の API キーに対して各社から別途請求されます（Actor 側の課金はありません）。

日本語でのお問い合わせ・不具合の報告は、Actor ページの **Issues** タブへどうぞ。

# Actor input Schema

## `mode` (type: `string`):

search = return listings. stats = model stats of in-stock listings (count, min / median / max by shop & condition grade). deals = in-stock listings at least dealThresholdPct % under the median of the same model in the same grade or better, with medianJpy, comparisonCount, discountPct and dealScore (statistics only). monitor = compare against the last run and emit only NEW / PRICE_DROP / PRICE_UP / SOLD_OUT events (use with a Schedule). history = daily min / median / count per model, by shop and condition grade, from stored daily snapshots (no crawling; needs keywords, brands or models). History is collected since 2026-11-05 (Shimokura daily, Ishibashi, Shimamura and Ikebe daily from 2026-11-05, J-Guitar and Off Mall weekly) — treat the first 30 days as indicative. Example: "deals" to list only underpriced listings.

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

Which shops to search. Shimokura Gakki (下倉楽器, Tokyo/Saitama, ~1,400 used instruments), J-Guitar (Jギター, a portal where many Japanese shops list their used stock: ~11,000 on sale, one condition scale for all, the listing shop in `shop`) Ishibashi Music (イシバシ楽器, ~8,500 used instruments from its 12 stores), Shimamura Music (島村楽器, ~5,500 used instruments from its stores nationwide, not graded), Ikebe Music (イケベ楽器, ~1,400 used and vintage instruments, not graded) and Hard Off Off Mall (~13,000 guitars, basses and wind instruments on sale). Case, store, year and country are completed from product pages for the listings a run returns. Example: \["shimokura", "ikebe"] for two shops only.

## `keywords` (type: `array`):

Only keep listings whose brand + title contains any of these (case-insensitive, English or Japanese; model codes work too). Leave empty to get everything. Examples: "Fender Japan", "ST57", "JB62", "Gibson Les Paul", "Tokai", "Martin D-28", "Yanagisawa". Words inside one keyword must all appear, in any order: "Fender Japan Jazzmaster" matches listings that contain every word. Put a keyword in double quotes for an exact phrase, e.g. '"Fender Japan"' (until 2026-11-05 every keyword was an exact phrase).

## `brands` (type: `array`):

Optional exact brand filter (canonical English names, e.g. Fender Japan, Fender USA, Fender Mexico, Fender, Squier, Gibson, Epiphone, Tokai, ESP, Ibanez, Yamaha, Greco, Martin, Yanagisawa, Selmer).

## `models` (type: `array`):

History mode: only these exact model keys, as shown in the "model" field of stats mode ("brand code", e.g. "fender japan st57-70tx", "fender japan jb62-58", "martin d-28").

## `days` (type: `integer`):

History mode: how many days back to return, counting today (JST). Example: 30 for the last month.

## `minPriceJpy` (type: `integer`):

Drop listings cheaper than this. Example: 30000 to skip effects pedals and cheap starter guitars.

## `maxPriceJpy` (type: `integer`):

Drop listings more expensive than this. Example: 150000 (about $1,000).

## `grades` (type: `array`):

Keep only these normalized grades (Reverb's scale). BRAND_NEW > MINT > EXCELLENT > VERY_GOOD > GOOD > FAIR > POOR > NON_FUNCTIONING (sold as is / for parts). J-Guitar 5\[M] = MINT, 4+\[NM] / 4\[EX+] = EXCELLENT, 3+\[EX] / 3\[EX-] = VERY_GOOD, 2+\[VG+] / 2\[VG] = GOOD, 1+\[G] = FAIR, 1\[P] = POOR. Ishibashi S = BRAND_NEW, A+ = MINT, A = EXCELLENT, B+ = VERY_GOOD, B = GOOD, C+ = POOR, C (junk) = NON_FUNCTIONING. Shimokura, Shimamura and Ikebe do not grade, so filtering by grade drops their listings. Example: \["MINT", "EXCELLENT"].

## `includeSoldOut` (type: `boolean`):

Search mode: also return listings marked sold out. Both shops list instruments on sale only, so this rarely changes anything. Example: on, to also catch a listing in the minutes after it sells.

## `fullScan` (type: `boolean`):

Monitor mode only. Off (default): lists are read newest-first and stop after 20 already-known listings in a row (normally 1 request per list per run). On: read every page (Shimokura ≈ 40 pages, ~2 min; J-Guitar ≈ 224 pages, ~30 min (requests ≥ 8 s apart); Ishibashi ≈ 121 pages, ~4 min; Shimamura ≈ 69 pages, ~7 min; Ikebe ≈ 19 pages, ~1 min; Off Mall ≈ 440 pages, ~8 min) to catch every PRICE_DROP / PRICE_UP / SOLD_OUT. Tip: frequent light runs plus a daily full scan of Shimokura only. Example: on in a once-a-day schedule, off in an hourly one.

## `monitorId` (type: `string`):

Optional. Each monitor keeps its own snapshot, keyed by its filters (keywords, brands, grades, price range, includeSoldOut). Set a monitorId to separate several schedules that use the same filters, or to keep the snapshot when you edit the filters. Letters, digits and - \_ . only. Example: "daily-full-scan".

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

Stop after this many matching listings across all selected shops (0 = no limit), split evenly between shops. Shimokura has ~1,400 used instruments, J-Guitar ~11,000, Ishibashi ~8,500, Shimamura ~5,500, Ikebe ~1,400, Off Mall ~13,000. In search mode each returned listing also costs one product-page request (case, store, year, country). Ignored in monitor mode. Example: 0 with keywords "Fender Japan" to get every Fender Japan listing.

## `jpyPerUsd` (type: `number`):

Exchange rate used for priceUsd. Leave empty to fetch the current rate automatically. Example: 150.

## `alertWebhookUrl` (type: `string`):

Optional. In monitor mode every batch of monitor events is POSTed as JSON to this URL. In deals mode the best dealsWebhookTop deals (highest dealScore first) are POSTed once per run — schedule it daily for a morning digest. Works with Slack/Discord incoming webhooks, n8n, Make, Zapier. Example: https://hooks.slack.com/services/T000/B000/XXXX.

## `dealsWebhookTop` (type: `integer`):

Deals mode with alertWebhookUrl: how many deals to POST, best dealScore first (ties: deeper discount first). The dataset still gets every deal. Example: 5 for a short Discord message.

## `alertEvents` (type: `array`):

Monitor mode: only these event types are written to the dataset, charged, and sent to the webhook. Example: \["NEW", "PRICE_DROP"] to hear about new listings and price cuts only.

## `dealsOnly` (type: `boolean`):

Monitor mode: output and send only the NEW / PRICE_DROP events whose listing is a deal (at least dealThresholdPct % under the median of the same model, same grade or better, among the listings this monitor tracks). Each event then carries medianJpy, comparisonCount, discountPct and dealScore. Charged as monitor events. Example: on, to get a Slack ping only when a new listing is a bargain.

## `dealThresholdPct` (type: `integer`):

Deals mode and monitor dealsOnly: a listing is a deal when it is at least this many % under the median of the same model in the same grade or better. Example: 20 = only listings at least 20 % under the median.

## `summarize` (type: `boolean`):

Search and deals mode: add summaryEn, a one-line English summary per listing (e.g. "Grand Seiko SBGX063, A-grade, full set, 18% under Japan median"), written by an LLM with YOUR API key below. The Actor charges nothing for it; your LLM provider bills you (Claude Haiku: roughly $0.01 per 100 listings or less). Without a key it is skipped with a warning.

## `llmApiKey` (type: `string`):

Your Anthropic or OpenAI API key, used only for summarize. Stored encrypted as a secret input. Example: sk-ant-api03-… (Anthropic) or sk-… (OpenAI).

## `llmProvider` (type: `string`):

anthropic (default, model claude-haiku-5-5) or openai (model gpt-5-mini). Example: "openai" if you only have an OpenAI key.

## `llmModel` (type: `string`):

Optional model id override, e.g. claude-sonnet-5-5. Leave empty for the provider default.

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

Off by default (direct connection). Switch to an Apify proxy only if runs get blocked. Example: Apify Proxy → RESIDENTIAL group, if a shop returns 403.

## Actor input object example

```json
{
  "mode": "search",
  "sources": [
    "shimokura",
    "jguitar",
    "ishibashi",
    "shimamura",
    "ikebe",
    "offmall"
  ],
  "keywords": [
    "Fender Japan"
  ],
  "days": 90,
  "includeSoldOut": false,
  "fullScan": false,
  "maxItems": 10,
  "dealsWebhookTop": 10,
  "alertEvents": [
    "NEW",
    "PRICE_DROP"
  ],
  "dealsOnly": false,
  "dealThresholdPct": 15,
  "summarize": false,
  "llmProvider": "anthropic",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset items. Shape depends on mode — see the dataset schema (listing / model stats row / monitor event / history row).

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

No description

## `stats` (type: `string`):

No description

## `history` (type: `string`):

No description

## `deals` (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 = {
    "sources": [
        "shimokura",
        "jguitar",
        "ishibashi",
        "shimamura",
        "ikebe",
        "offmall"
    ],
    "keywords": [
        "Fender Japan"
    ],
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("keiya_dev/japan-used-instrument-market").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 = {
    "sources": [
        "shimokura",
        "jguitar",
        "ishibashi",
        "shimamura",
        "ikebe",
        "offmall",
    ],
    "keywords": ["Fender Japan"],
    "maxItems": 10,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("keiya_dev/japan-used-instrument-market").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 '{
  "sources": [
    "shimokura",
    "jguitar",
    "ishibashi",
    "shimamura",
    "ikebe",
    "offmall"
  ],
  "keywords": [
    "Fender Japan"
  ],
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call keiya_dev/japan-used-instrument-market --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,keiya_dev/japan-used-instrument-market"
        }
    }
}
```

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/o6m4nGxGRlQHQoxNj/builds/bK2rbrXQLHq3CJLGW/openapi.json
