# BookOff Japan Used Manga, Books, CDs — Price & Stock (`jpmarketdata/bookoff-market-checker`) Actor

Type a keyword and get what used books, manga, CDs and games cost on BookOff Japan's online store. Returns typical used price and range across all matching listings, plus in-stock vs sold-out counts and list-price discount in a 120-item sample. $0.02 per keyword; no results, no charge. Unofficial.

- **URL**: https://apify.com/jpmarketdata/bookoff-market-checker.md
- **Developed by:** [h ichi](https://apify.com/jpmarketdata) (community)
- **Categories:** E-commerce, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 keyword market analyzeds

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

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

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

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

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

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

# README

## BookOff Japan Used Manga, Books, CDs — Price & Stock

**What it does:** Type a keyword and get what used books, manga, CDs, DVDs and games cost on BookOff's official online store in Japan.

**You enter:** one or more keywords in Japanese, e.g. `ガンダム`; optional genre (books / comics / CD / DVD / games).

**You get:** typical used price, lowest–highest and middle 50%, usually read across all matching listings; from 120 sampled listings (the cheapest by default): in-stock vs sold-out counts, discount vs list price, new-copy price, top genres. Optional: one row per listing.

**Price:** $0.02 per keyword — every keyword in your list is charged — plus $0.002 per listing if you also want the list (off by default). No results = no charge.

**Example:** enter `ガンダム` → 4,893 listings · typical used price ¥550 (range ¥99–77,000) · 82% of the 120 sampled listings sold out · used copies about 78% below list price.

> Unofficial — not affiliated with BOOKOFF. Reads public pages only.

### Pricing — $0.02 per keyword

| What you pay for | Price | When |
|---|---|---|
| Keyword summary | **$0.02** | Per keyword, and every keyword in your list is charged |
| Individual listing | **$0.002** | Only if you turn on **Include individual listings** (off by default) |

A default run (1 keyword, summary only) costs **$0.02** and takes about 8 seconds. You pay per keyword; there is no monthly fee. **A keyword that returns zero listings is never charged.**

### Input

| Field | Example | Notes |
|---|---|---|
| `keywords` | `["ガンダム"]` | Japanese works best — the catalog is Japanese, and an English keyword only matches titles printed in Latin letters (measured: `Gundam` finds 498 listings, `ガンダム` 4,893). Each keyword costs $0.02 |
| `genreCode` | `"11"` | Optional: `12` Books / `11` Comics / `13` Magazines / `31` CD / `71` DVD & Blu-ray / `51` Games. Empty = all genres |
| `maxItemsPerKeyword` | `120` | How many listings are read for the stock split, the discount and the genre mix (30–360, 120 per page). Does **not** change the used-price figures; below 120 it only caps how many individual listings come back |
| `includeIndividualItems` | `false` | Turn on to also get each read listing as its own row |
| `convertToUsd` | `true` | Adds USD figures at the current exchange rate |

### Whole search or 120-item sample — every number says which

Every summary carries **`usedPriceJpyBasis`**, so you never have to guess how the used price was worked out:

| `usedPriceJpyBasis` | What it means | How it is obtained | When you get it |
|---|---|---|---|
| **`exact`** | Read from **every matching listing** | The whole result fits on one page (≤120 hits), so all of it is read — 1 request | Narrow keywords |
| **`population_quantiles`** | The cheapest, the middle 50% range, the median and the dearest come from **every matching listing, not from a sample**; `count` is the full hit count | Listings are ordered cheapest-first and the Actor jumps straight to the page holding the listing at that rank (e.g. hits 1,224 / 2,447 / 3,670 of 4,893 = pages 11 / 21 / 31), plus one dearest-first page for the highest price — 5 requests | Most keywords |
| **`null`** | Nothing was found, so there is no price to describe (`keywordStatus: "not_found"`, no charge) | — | Zero-hit keywords |
| **`sample`** | Ordinary statistics over only the listings that were read; `count` = how many that was | Fallback. Used when the price order turns out **not** to rise steadily from page to page, or when a multi-keyword run hits its time budget (then `truncatedForTimeLimit: true` is also set) | Rare |

The fallback is the point: if the store ever changes how it orders results, the Actor **stops claiming whole-search figures** and labels the row `sample` instead of quietly returning wrong numbers.

`newPriceJpy`, `stockBreakdown`, `outOfStockRatioSampled`, `discountVsListPricePct` and `genreTop` always come from the sample only (`sampledListings` tells you its size). With the default `maxItemsPerKeyword: 120` that sample is the 120 cheapest listings, so read the stock split as "the low-price end of this market"; raise it to 240/360 and the sample spreads across the whole price range using the pages that are read anyway — **no extra requests, no extra time.**

### Output example (`type: "market_summary"`)

*Measured on 2026-07-25 (real BookOff pages, keyword ガンダム); the hit count was still 4,893 on 2026-08-18*

```json
{
  "type": "market_summary",
  "keyword": "ガンダム",
  "genre": null,
  "genreName": null,
  "totalListingsFound": 4893,
  "sampledListings": 120,
  "keywordStatus": "ok",
  "hint": null,
  "usedPriceJpy": {"min": 99, "q1": 330, "median": 550, "q3": 1375, "max": 77000, "count": 4893},
  "usedPriceJpyBasis": "population_quantiles",
  "newPriceJpy": {"min": 528, "q1": 660, "median": 990, "q3": 1650, "max": 6600, "count": 14},
  "stockBreakdown": {"inStock": 12, "lowStock": 6, "lastOne": 4, "outOfStock": 98},
  "outOfStockRatioSampled": 0.8167,
  "discountVsListPricePct": {"median": 78},
  "genreTop": [["コミック", 61], ["書籍", 34], ["DVD・ブルーレイ", 12]],
  "usedPriceUsd": {"min": 0.63, "q1": 2.11, "median": 3.52, "q3": 8.8, "max": 492.8},
  "exchangeRateJpyUsd": 0.0064,
  "checkedAt": "2026-07-25T09:00:00+00:00",
  "sourceUrl": "https://shopping.bookoff.co.jp/search/keyword/%E3%82%AC%E3%83%B3%E3%83%80%E3%83%A0?per-page=120&sort=50&p=1"
}
```

`q1` and `q3` are the two ends of the middle 50% of prices: half of all ガンダム listings sit between ¥330 and ¥1,375.

**A keyword that found nothing still gets its row**, with every price field null, `keywordStatus: "not_found"`, `usedPriceJpyBasis: null` (nothing was measured, so no basis is claimed) and a one-line `hint` saying what to try next — and it is not charged. A keyword that found listings has `keywordStatus: "ok"` and `hint: null`.

With `includeIndividualItems: true` you additionally get one row per listing — *measured on 2026-08-18, keyword `ONE PIECE 105`*:

```json
{
  "type": "item",
  "keyword": "ONE PIECE 105",
  "id": "0019946797",
  "title": "ONE PIECE(巻百五) ジャンプC",
  "priceJpy": 220,
  "condition": "used",
  "stockStatus": "in_stock",
  "listPriceJpy": 528,
  "discountPct": 58,
  "releaseDate": "2023/03/03",
  "storePickup": true,
  "url": "https://shopping.bookoff.co.jp/used/0019946797"
}
```

### Use cases

- **Import & resale sourcing** — check the Japanese used price band for a title before buying through a proxy service, and compare it against what the same title sells for on eBay or Mercari
- **Pricing your own inventory** — the median and the top of the middle 50% range, read across the *whole* result set, are what the Japanese market actually charges, not what the loudest listing asks
- **Turnover screening** — a high `outOfStockRatioSampled` with a thin in-stock count means the title moves; a low one means it sits on shelves
- **Catalog / rights research** — how deep is the secondhand supply of a series, a label or an artist, and at what discount to list price
- **Repricing & monitoring** — schedule the Actor and track the median per keyword over time

### Notes & limits

- **Trading cards, figures and hobby goods are out of scope.** BookOff's official online store has no TCG / hobby genre — only books, comics, magazines, CDs, DVDs & Blu-ray and games. Use a Mandarake or Suruga-ya source for cards and figures
- Keywords are matched against a **Japanese** catalog. An English keyword matches only the titles that are printed in Latin letters, so it finds a part of the market, not all of it — measured 2026-08-18: `One Piece` 1,731 listings against `ワンピース` 2,174 (80%), `camera` 1,795 against `カメラ` 9,842 (18%), `Gundam` 498 against `ガンダム` 4,893 (10%), `manga` 689 against `漫画` 38,239 (2%). Use 日本語 (ガンダム, 鬼滅の刃, 米津玄師) for the whole picture
- BookOff is a fixed-price retailer, not a marketplace: prices are **asking prices**, and a sold-out product's price is the **last price it was offered at** — a good stand-in for what it sold for, but it is a product-master price, not a record of individual sales, and it carries no sale date (so no history over time)
- The store's default order is 人気順 (popularity), which is best-seller/ad weighted. This Actor **always sends an explicit order** so the numbers are not skewed
- `totalListingsFound` counts every matching listing, in stock or not
- "In stock only" / "used only" filters exist in the site's UI but their query parameters are not publicly stable, so v1 reports the stock split from the sample instead of filtering on the site's side
- Read-only and throttled (1 request / 1.5 s), 5 requests per keyword. Multi-keyword runs have a 95-second soft budget: keywords beyond it still return a summary, marked `truncatedForTimeLimit` with `usedPriceJpyBasis: "sample"`
- No personal data is collected — BookOff is a first-party retailer, there are no sellers

***

### 日本語ガイド

**ブックオフ公式オンラインストアの中古相場を、キーワード1件につき1レコードで返す Actor です。**

- **概要**: キーワードごとに **中古価格の代表値(最安・下位25%・中央値・上位25%・最高値)** を返します。特徴は、先頭ページだけのサンプル統計ではなく **検索結果の全件から** その値を読み取れること — 中古価格の安い順に並べ替え、その順位が載っているページへ直接ジャンプして読み取ります(例: 全4,893件なら 11 / 21 / 31 ページ目、計5リクエスト)。あわせて在庫内訳(在庫あり/残りわずか/残り1点/在庫なし)、**在庫なし比率**(ブックオフは売り切れ商品も価格付きで残るため、回転率と「実売価格に近い値」の指標になります)、定価に対する割引率の中央値、新品価格、ジャンル内訳、USD換算を返します(これらは読み取った120件のサンプル基準)。
- **使い方**: `keywords` に**日本語**のキーワードを入れてください(カタログが日本語のため)。英語キーワードはローマ字表記のタイトルにしか当たりません(実測 2026-08-18: Gundam 498件 / ガンダム 4,893件、One Piece 1,731件 / ワンピース 2,174件)。0件のときは `keywordStatus: "not_found"` と `hint` が付き、`usedPriceJpyBasis` は null になります(課金なし)。`genreCode` でジャンルを絞れます(12=書籍 / 11=コミック / 13=雑誌 / 31=CD / 71=DVD・ブルーレイ / 51=ゲーム)。個別商品の明細が必要なときだけ `includeIndividualItems` を ON にします。
- **料金**: キーワードサマリー1件 **$0.02**、個別商品レコードは **$0.002/件**(既定 OFF なので既定実行は $0.02 固定)。**0件のキーワードには課金されません。** 使った分だけの従量課金です。
- **数値の根拠は必ず明示**: `usedPriceJpyBasis` が `exact`(全件が1ページに収まり全数集計)/ `population_quantiles`(検索結果の全件から読み取り)/ `sample`(読み取った件数だけの統計)のどれかを示します。ページ間で価格の並びが単調に上がらない場合や、複数キーワードで時間予算(95秒)を超えた場合は**全件基準を名乗らず** `sample` に落ちます(誤った数値を黙って出さないため)。在庫内訳・割引率・ジャンル内訳・新品価格は常にサンプル基準です。
- **対象外**: **トレカ・ホビー・フィギュア系のジャンルは公式オンラインストアに存在しないため対象外です**(書籍・コミック・雑誌・CD・DVD・ゲームのみ)。トレカやフィギュアの相場はまんだらけ等のソースをご利用ください。
- **その他**: ブックオフは定価販売の中古小売であり、価格は「出品価格」です。売り切れ商品の価格は「最後に提示されていた価格」であって個々の成約記録ではなく、販売日時も取得できません(時系列分析は不可)。既定の並び順(人気順)は広告・売れ筋バイアスがあるため、本 Actor は常に並び順を明示して取得します。

### If something goes wrong

- **Wrong number or a failed run?** Open a ticket on the **Issues** tab. I read every one and reply within 2 business days (Japan time).
- **You never get a fake "empty" result.** If the site can't be read, the run fails and says so.
- **No results = no charge.** You only pay for results you actually get.
- **Checked every week.** An automatic test runs this tool weekly; if the site changes, I fix it.
- **Public pages only.** No login, no personal data, and it goes easy on the site.

### More tools by the same author

- [@cosme Japan Beauty Ranking — Top 50 Ratings & Prices](https://apify.com/jpmarketdata/cosme-beauty-market-checker)
- [Digimart Japan Used Guitar & Instrument Prices](https://apify.com/jpmarketdata/digimart-instrument-market-checker)
- [Fujiya Camera Japan Used Camera Prices by Condition](https://apify.com/jpmarketdata/fujiya-camera-market-checker)
- [HobbyLink Japan Gunpla & Figure Prices + Stock Status](https://apify.com/jpmarketdata/hlj-hobby-market-checker)
- [Iosys Japan Used iPhone & Phone Prices by Condition](https://apify.com/jpmarketdata/iosys-phone-market-checker)
- [Mandarake Japan Collectibles — Prices In Stock & Sold Out](https://apify.com/jpmarketdata/mandarake-market-checker)
- [Tackleberry Japan Used Fishing Tackle Prices & Counts](https://apify.com/jpmarketdata/tackleberry-tackle-market-checker)
- [Yuyu-tei Japan TCG Card Prices — Sell & Buy-back Price](https://apify.com/jpmarketdata/yuyutei-tcg-price-checker)
- [Mercari Japan Sold Prices — What Items Really Sell For](https://apify.com/jpmarketdata/mercari-japan-price-checker)
- [Yahoo! Auctions Japan Sold Prices — Median, Range, Bids](https://apify.com/jpmarketdata/yahoo-auction-sold-comps)

Other language editions of this tool: [中文](https://apify.com/jpmarketdata/bookoff-market-cn) · [한국어](https://apify.com/jpmarketdata/bookoff-market-kr)

All tools (Japan marketplaces, real estate, jobs, racing, prediction markets): <https://apify.com/jpmarketdata>

### Disclaimer

Unofficial, independent tool — **not affiliated with, endorsed by, or sponsored by BOOKOFF**. Product names and logos belong to their owners and only say where the data comes from. Data is read from public pages, for market research; check before you act on it.

# Actor input Schema

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

One or more search keywords. Japanese works best (ガンダム, ワンピース, ドラゴンクエスト, 米津玄師): the catalog is Japanese, so an English keyword only matches the titles printed in Latin letters — measured 2026-08-18, 'Gundam' finds 498 listings against 4,893 for 'ガンダム', 'One Piece' 1,731 against 2,174 for 'ワンピース'. A keyword that finds nothing comes back with keywordStatus 'not\_found' and is not charged. Each keyword costs $0.02.

## `genreCode` (type: `string`):

Restrict the search to one BookOff genre: 12=Books (書籍), 11=Comics (コミック), 13=Magazines (雑誌), 31=CD, 71=DVD & Blu-ray, 51=Games (ゲーム). Leave empty to search all genres. Note: trading cards and hobby/figure genres do not exist on the official online store.

## `maxItemsPerKeyword` (type: `integer`):

How many listings to inspect per keyword for the stock split, discount and genre mix. The used-price quartiles are read from the whole result set and are not affected. Results come 120 per page, so values above 120 add the quantile pages that are fetched anyway — the sample spreads across the price range at no extra request and no extra time — while values below 120 only limit how many individual listings are returned (and billed) when 'Include individual listings' is on (+$0.002 per listing).

## `includeIndividualItems` (type: `boolean`):

Off by default: a run costs a flat $0.02 per keyword summary. Enable to also get every sampled listing (title, price, condition, stock status, list price, discount, release date, store pickup, URL) at +$0.002 per listing.

## `convertToUsd` (type: `boolean`):

Adds USD statistics next to JPY using the current exchange rate (open.er-api.com).

## Actor input object example

```json
{
  "keywords": [
    "ガンダム"
  ],
  "maxItemsPerKeyword": 120,
  "includeIndividualItems": false,
  "convertToUsd": true
}
```

# 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 = {
    "keywords": [
        "ガンダム"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jpmarketdata/bookoff-market-checker").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 = { "keywords": ["ガンダム"] }

# Run the Actor and wait for it to finish
run = client.actor("jpmarketdata/bookoff-market-checker").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 '{
  "keywords": [
    "ガンダム"
  ]
}' |
apify call jpmarketdata/bookoff-market-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jpmarketdata/bookoff-market-checker"
        }
    }
}

```

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/OEmzx36D430SkYoV4/builds/2S70GoIjsTq0r2W4Y/openapi.json
