# Anime Figure & Gunpla Price — Japan Resale Value vs Retail (`jpmarketdata/japan-figure-gunpla-resale-value`) Actor

What is an anime figure or Gunpla kit worth in Japan vs its retail price? One call returns HobbyLink Japan retail, Mandarake/BookOff shop-used and Yahoo Auctions/Mercari sold medians, plus the resale premium. Every number tagged retail/shop\_used/c2c. From $0.02, no subscription. 定価比プレミアムを1コールで。

- **URL**: https://apify.com/jpmarketdata/japan-figure-gunpla-resale-value.md
- **Developed by:** [h ichi](https://apify.com/jpmarketdata) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 figure/kit valued across markets

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/platform/actors/running/actors-in-store#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

## Anime Figure & Gunpla Price — Japan Resale Value vs Retail

**What does this figure or model kit cost new in Japan, and what is it actually selling for second-hand right now?** One call per keyword returns both sides and the number in between: **`premium`**, the resale median as a ratio of the retail price.

Measured 2026-08-07, `RG Nu Gundam`, default settings, 6.3 seconds:

> retail **¥4,500** (HobbyLink Japan, in stock) → sold **¥8,141** (Yahoo! Auctions + Mercari) = **+80.9 %**

| Channel | Source | What you get | `priceKind` |
|---|---|---|---|
| `retail` | [HobbyLink Japan](https://www.hlj.com/) | New stock: current price **and** Japanese list price (定価), plus stock state | `list` |
| `shop_used` | [Mandarake](https://order.mandarake.co.jp/) (まんだらけ) | In-stock **and** sold-out used stock, by branch | `asking` + `sold` |
| `shop_used` | [BookOff](https://shopping.bookoff.co.jp/) (ブックオフ) | Used stock, population quartiles | `asking` |
| `c2c` | [Yahoo! Auctions](https://auctions.yahoo.co.jp/) (ヤフオク) | Closed auctions with at least one bid | `sold` |
| `c2c` | [Mercari Japan](https://jp.mercari.com/) (メルカリ) | Sold-out and/or on-sale listings | `sold` / `asking` |
| `c2c` | [PayPay Flea Market](https://paypayfleamarket.yahoo.co.jp/) | Live listings | `asking` |

Nobody else on the Store carries the **retail anchor**. Sold comps for Japanese hobby goods are easy to find; the price the thing costs *new* is what turns them into a premium.

### Two tags on every number, because they are two different questions

- **`priceBasis`** — *who is selling*: `retail` (a shop selling new) / `shop_used` (a second-hand chain reselling at its own fixed price) / `c2c` (a private seller).
- **`priceKind`** — *what the number is*: `list` / `asking` (nobody has agreed to it) / `sold` (somebody paid it).

They are kept orthogonal, never collapsed. Mandarake sells at fixed prices, so a **sold-out** Mandarake listing is a realized price while an **in-stock** one is an ask — the same product, two different quantities, so they come back as two blocks (`mandarake_sold_out`, `mandarake_in_stock`), never one blended median.

Entries are then grouped into **pools** keyed `<priceBasis>_<priceKind>` — `retail_list`, `c2c_sold`, `shop_used_asking`, … — so each pool is homogeneous on both axes, and every premium is stamped with the pair it came from (`basis: "c2c_sold_vs_retail_best_match"`). A pool's median is the **median of its sources' medians**, not a median over pooled prices: sample sizes differ by an order of magnitude between sources, and pooling raw rows would silently weight the answer by whichever site returned the most.

### The retail anchor (read this before comparing runs)

HLJ's catalogue mixes ¥500 decal sheets, ¥900 magazines and ¥4,000 art books in with the kits, and its search matches all of them. Measured on `RG Nu Gundam`: 273 hits, 24 sampled, **catalogue median ¥500** — 20 of the 24 rows are decals — while rank 1 is the actual kit at **¥4,500**.

So the anchor is an explicit input, never a silent threshold:

| `retailAnchor` | Anchor | `RG Nu Gundam` premium |
|---|---|---|
| `best_match` (default) | HLJ's **top relevance-ranked priced hit** — one product, one price, nothing averaged | ¥4,500 → **+80.9 %** |
| `catalog_median` | Median of the whole HLJ sample. Right when the keyword names a *category* ("nendoroid") | ¥500 → +1528.2 % |

**Both are always reported** in `premium.byAnchor`, so one run shows you what the other choice would have said. A top-N median was tried and rejected: it repairs `RG Nu Gundam` but breaks `PG Unleashed RX-78-2`, where three books outvote the kit (¥25,000 → ¥3,300).

Retail is also reported twice on purpose: `retailMedianJpy` is what HLJ charges **today** (an importer's real acquisition cost) and `msrpMedianJpy` is the Japanese **list price 定価** before any HLJ discount — `premium.vsMsrp` divides by that one.

### Pricing — from $0.02 per keyword, no subscription

| Event | Price | When |
|---|---|---|
| Keyword analyzed | **$0.02** | Per keyword, whatever the number of sources |
| Individual listing | **$0.002** | Only if you enable **Include individual listings** |

A default run (1 keyword, 4 sources, summary only) costs **$0.02** and took **6.3 s** measured. All six sources, three keywords, summaries only: **$0.06**, 24.1 s.

Apify's **$5 monthly free credit covers about 250 default runs**. No subscription, no minimum.

**A keyword is only charged when at least two of the selected sources actually returned data** (or the single one, if you selected only one). A "retail vs resale" record with one source in it is not a comparison, so it is free. The two Mandarake blocks are *one* source and cannot satisfy that on their own.

### Input

| Field | Example | Notes |
|---|---|---|
| `keywords` | `["RG Nu Gundam"]` | The keyword **is** the join key across all sources — best when it names one product. Japanese matches more second-hand listings. $0.02 each |
| `sources` | `["hlj","mandarake","yahoo_auction","mercari"]` | Default four = one per channel plus the sold-comp leg. `bookoff` and `paypay_flea` are opt-in depth. Price per keyword is unchanged |
| `retailAnchor` | `"best_match"` | `best_match` (a product keyword) or `catalog_median` (a category keyword). Both always reported |
| `mercariStatus` | `"sold_out"` | `sold_out` (realized, default) / `on_sale` (asking) / `both` (two blocks, one extra request) |
| `maxItemsPerSource` | `60` | 20–240 listings sampled per source (and per Mercari status) |
| `priceMinJpy` / `priceMaxJpy` | `4000` | Optional window, applied **identically to every source**. Cuts parts, stickers and bulk lots |
| `includeIndividualItems` | `false` | Enable to also get every sampled listing, +$0.002 each |
| `convertToUsd` | `true` | Adds USD stats at the current rate (one FX lookup per run) |

### Output example (`type: "resale_value_summary"`, abridged, measured 2026-08-07)

```json
{
  "type": "resale_value_summary",
  "keyword": "RG Nu Gundam",
  "premium": {
    "retailAnchor": "best_match", "retailAnchorUsed": "best_match",
    "retailMedianJpy": 4500, "msrpMedianJpy": 4500,
    "retailBestMatch": {
      "relevanceRank": 1, "id": "BANH578426-UP", "title": "RG NU Gundam",
      "priceJpy": 4500, "listPriceJpy": 4500, "stockStatusCode": "instock",
      "releaseDate": "October 2025",
      "url": "https://www.hlj.com/1-144-scale-rg-nu-gundam-banh578426-up"
    },
    "resalePool": "c2c_sold", "resaleMedianJpy": 8141,
    "resaleSources": ["yahoo_auction", "mercari_sold"],
    "basis": "c2c_sold_vs_retail_best_match",
    "premiumJpy": 3641, "premiumPct": 80.9, "ratio": 1.809, "aboveRetail": true,
    "byPool": {
      "shop_used_sold":   {"medianJpy": 4500, "premiumPct": 0.0,  "sources": ["mandarake_sold_out"]},
      "shop_used_asking": {"medianJpy": 6650, "premiumPct": 47.8, "sources": ["mandarake_in_stock"]},
      "c2c_sold":         {"medianJpy": 8141, "premiumPct": 80.9, "sources": ["yahoo_auction", "mercari_sold"]}
    },
    "byAnchor": {
      "best_match":     {"retailJpy": 4500, "msrpJpy": 4500, "premiumPct": 80.9},
      "catalog_median": {"retailJpy": 500,  "msrpJpy": 500,  "premiumPct": 1528.2}
    },
    "retailMedianUsd": 28.44, "resaleMedianUsd": 51.46, "premiumUsd": 23.01,
    "note": "Premium is a realized resale median over a retail median… It is gross — Japanese marketplace fees (~10%), shipping and proxy/export costs are not deducted."
  },
  "identity": {
    "joinKey": "keyword", "retailListingsFound": 273,
    "retailPriceDispersionRatio": 8.25, "dispersionThreshold": 2.0,
    "looksLikeOneProduct": false,
    "note": "The retail hits span a wide price range… every resale median is keyword-wide."
  },
  "pools": {
    "retail_list":      {"priceBasis": "retail",    "priceKind": "list",   "medianJpy": 500,  "aggregation": "single_source"},
    "shop_used_sold":   {"priceBasis": "shop_used", "priceKind": "sold",   "medianJpy": 4500, "aggregation": "single_source"},
    "shop_used_asking": {"priceBasis": "shop_used", "priceKind": "asking", "medianJpy": 6650, "aggregation": "single_source"},
    "c2c_sold":         {"priceBasis": "c2c",       "priceKind": "sold",   "medianJpy": 8141,
                         "sourceMediansJpy": {"yahoo_auction": 6580, "mercari_sold": 9702},
                         "aggregation": "median_of_source_medians"}
  },
  "resaleSpread": {
    "available": true, "pool": "c2c_sold",
    "cheapestSource": "yahoo_auction", "cheapestMedianJpy": 6580,
    "priciestSource": "mercari_sold",  "priciestMedianJpy": 9702,
    "spreadJpy": 3122, "spreadPct": 47.4
  },
  "sources": {
    "hlj_retail": {
      "priceBasis": "retail", "priceKind": "list", "available": true,
      "totalListingsFound": 273, "sampledListings": 24, "pricedListings": 24,
      "priceJpy": {"min": 500, "p25": 500, "median": 500, "p75": 4125, "max": 60000, "average": 4596},
      "statisticsBasis": "sample",
      "signals": {"stockBreakdown": {"instock": 15, "backorder": 9},
                  "inStockRatioSampled": 0.625, "releaseYearTop": [[2025, 11], [2021, 8]]}
    },
    "mandarake_in_stock": {"priceKind": "asking", "totalListingsFound": 10, "priceJpy": {"median": 6650},
                           "statisticsBasis": "exact", "signals": {"shopTop": [["Kokura", 2]]}},
    "mandarake_sold_out": {"priceKind": "sold",   "totalListingsFound": 9,  "priceJpy": {"median": 4500},
                           "signals": {"shopTop": [["Complex", 3], ["Grandchaos", 2]]}},
    "yahoo_auction":      {"priceKind": "sold",   "totalListingsFound": 2,  "priceJpy": {"median": 6580},
                           "signals": {"sellThroughRatioSampled": 1.0, "bidCount": {"median": 4}}},
    "mercari_sold":       {"priceKind": "sold",   "totalListingsFound": 32, "priceJpy": {"median": 9702},
                           "signals": {"medianDaysToSell": 12}}
  },
  "channelsWithData": ["retail", "shop_used", "c2c"],
  "checkedAt": "2026-08-07T06:56:00+00:00"
}
```

With `includeIndividualItems: true` you additionally get one record per listing (`type: "listing"`), each tagged with `source`, `sourceEntry`, `priceBasis` and `priceKind`.

### Use cases

- **Flipping and proxy buying** — `premium.premiumPct` on the `c2c_sold` pool is the gross spread between buying new and selling used. `resaleSpread` says which marketplace pays more for the same item
- **Preorder decisions** — a kit already trading above list price (`aboveRetail: true`) while HLJ still shows `instock` is a kit to buy now; `signals.stockBreakdown` and `releaseYearTop` say how long that window is
- **Export and reselling outside Japan** — `retailMedianUsd` is landed-cost input, `resaleMedianUsd` is the Japanese ceiling you are arbitraging against
- **Collection valuation** — schedule the Actor over your want list and watch `ratio` move
- **Deciding where to list** — `totalListingsFound` is the supply you would compete with, `signals.sellThroughRatioSampled` (Yahoo) and `signals.medianDaysToSell` (Mercari) are the liquidity

### Notes & limits

- **The keyword is the join key — there is no name matching.** `identity.retailPriceDispersionRatio` (retail p75/p25) and `looksLikeOneProduct` tell you whether that held. When it is `false`, `best_match` still pins the retail side to one product but every resale median is keyword-wide; narrow the keyword or set `priceMinJpy` / `priceMaxJpy`
- **The premium is gross.** Japanese marketplace fees (~10 %), shipping, and proxy/export costs are not deducted
- `sold` beats `asking`: the headline uses `c2c_sold` when it exists and falls back to `c2c_asking` with a different `note` — an asking-based premium is an upper bound, not a margin
- **Check `pricedListings` before trusting a median.** A narrow keyword can leave a source with two or three listings; `totalListingsFound` is what each site reports and is never rewritten by the client-side price window
- `statisticsBasis` says how each block's quartiles were produced: `exact` (the whole result set was read), `population_quantiles` (read out of BookOff's price-sorted result set), `sample`, or `stratified_sample` (a price window was applied on top of BookOff's spread sample)
- **BookOff is media-first.** It carries art books, magazines, discs and games — measured, it returns **0 hits** for most kit keywords and its Gundam hits are books. Useful for anime/hobby *media*, not for kits; it is off by default
- **PayPay Flea Market can never return sold prices** — they are not server-rendered. Nothing here pretends otherwise
- **An out-of-print item may have no retail anchor at all.** `premium.available: false` with a reason, rather than a division by a made-up number — and that absence is itself why a premium exists
- **A source that fails does not fail the run**: it comes back as `available: false` with an `error`, and the remaining sources are still compared. Only a keyword where *every* source failed fails the run
- Read-only, no login, no browser. Requests to one host are throttled to one per 1.5 s, and **Yahoo! Auctions and PayPay Flea Market are queried sequentially** because they share one backend
- No personal data is collected — sellers are excluded from every record

***

**日本語**: フィギュア・ガンプラの「**定価に対するプレミアム**」を1コールで返します(HLJ の新品価格を基準に、まんだらけ/ブックオフの店頭中古とヤフオク落札/メルカリ/PayPay の個人間実売を比較。全数値に `retail`/`shop_used`/`c2c` と `list`/`asking`/`sold` のタグ付き、キーワード1件 $0.02・既定 OFF の個別明細のみ $0.002/件)。

**中文**: 一次调用即可得到日本手办与高达模型的「相对定价的溢价」(以 HLJ 新品价为基准,对比万代书店/BookOff 的店铺二手与雅虎拍卖/煤炉/PayPay 的个人成交价,每个关键词 $0.02,无订阅)。

# Actor input Schema

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

One or more product searches. The keyword is the join key across every source, so it works best when it names ONE product: "RG Nu Gundam" or "MG Sazabi Ver.Ka", not "gundam". Japanese matches more second-hand listings than English (ねんどろいど 初音ミク). Each keyword costs $0.02.

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

Which Japanese shops and marketplaces to price. The default four cover all three channels — retail (HobbyLink Japan), shop-used (Mandarake) and private resale (Yahoo! Auctions sold + Mercari) — and keep a run short. BookOff and PayPay Flea Market are extra depth: adding them roughly doubles the run time. The price of a keyword is the same whichever sources you pick.

## `retailAnchor` (type: `string`):

HobbyLink Japan's catalogue mixes ¥500 decals, magazines and art books in with the kits, so a median over its search results is not the price of any one product (measured: "RG Nu Gundam" has a catalogue median of ¥500 against a rank-1 kit price of ¥4,500). 'Best match' uses the price of HLJ's top relevance-ranked hit — one product, one price. Choose 'Catalog median' when your keyword names a category rather than a product. Both are always reported in premium.byAnchor.

## `mercariStatus` (type: `string`):

Which Mercari listings to price. 'Sold out' gives realized resale prices (the ones the premium is built on) and is the default. 'On sale' gives asking prices. 'Both' returns them as two separate blocks so each keeps a single, honest price kind — and costs one extra request.

## `maxItemsPerSource` (type: `integer`):

How many listings to sample per source (and per Mercari status) before computing the statistics. Larger samples are steadier but slower: HobbyLink Japan returns 24 per page, Yahoo! Auctions 50, PayPay 100, Mercari and Mandarake 120, and requests to one host are throttled to one per 1.5 s.

## `priceMinJpy` (type: `integer`):

Drop listings priced below this before computing the statistics. Applied identically to every source so the retail and resale medians stay comparable. Useful to cut parts, stickers and empty boxes out of a keyword. Note: it forces every source back onto sample statistics (`statisticsBasis`).

## `priceMaxJpy` (type: `integer`):

Drop listings priced above this before computing the statistics. Applied identically to every source. Useful to cut bulk lots and 'set of 12' listings out of a keyword.

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

Off by default: a run costs a flat $0.02 per keyword, whatever the number of sources. Enable to also get every sampled listing from every source (title, price, stock status, condition, URL, priceBasis, priceKind) at +$0.002 per listing.

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

Adds USD statistics next to JPY using the current exchange rate (open.er-api.com, looked up once per run).

## Actor input object example

```json
{
  "keywords": [
    "RG Nu Gundam"
  ],
  "sources": [
    "hlj",
    "mandarake",
    "yahoo_auction",
    "mercari"
  ],
  "retailAnchor": "best_match",
  "mercariStatus": "sold_out",
  "maxItemsPerSource": 60,
  "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": [
        "RG Nu Gundam"
    ],
    "sources": [
        "hlj",
        "mandarake",
        "yahoo_auction",
        "mercari"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jpmarketdata/japan-figure-gunpla-resale-value").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": ["RG Nu Gundam"],
    "sources": [
        "hlj",
        "mandarake",
        "yahoo_auction",
        "mercari",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("jpmarketdata/japan-figure-gunpla-resale-value").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": [
    "RG Nu Gundam"
  ],
  "sources": [
    "hlj",
    "mandarake",
    "yahoo_auction",
    "mercari"
  ]
}' |
apify call jpmarketdata/japan-figure-gunpla-resale-value --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jpmarketdata/japan-figure-gunpla-resale-value"
        }
    }
}

```

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/uWUfKAQISXJOnldPJ/builds/Yz5t2hHjWcBYSAJ2o/openapi.json
