# Mercari Japan Scraper — Listings & Sold Prices (`khadinakbar/mercari-japan-scraper`) Actor

Scrape Mercari Japan listings and sold prices by keyword or jp.mercari.com URL. Returns JPY price, status, seller, photos, timestamps, plus optional median sold-comp stats. HTTP-only and MCP-ready. $0.005/listing, $0.02/sold-comp report.

- **URL**: https://apify.com/khadinakbar/mercari-japan-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** E-commerce, Automation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 listing scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Mercari Japan listings and sold prices

Scrape public **Mercari Japan** (`jp.mercari.com`) listings and sold prices into one dataset. Pass a keyword or a search/item URL and get JPY price, status (`on_sale` / `sold_out` / `trading`), condition, seller, photos, timestamps, and optional median sold-comp stats. Built for Japan resale sourcing, brand price tracking, and AI agents that need structured comps without a Mercari login.

Use this Actor when you need Mercari Japan sold prices or live listings as structured JSON. For Mercari US or Buyee, start with a US Mercari or Buyee-specific Actor.

### Best fit for this Actor

- You need **sold prices** (status `sold_out`) to set a buy/sell band on Japan C2C.
- You need **live listings** for a keyword, category search URL, or a single item URL.
- You want one MCP-ready tool that returns flat JSON plus a terminal `OUTPUT.outcome`.
- For US Mercari, Yahoo Auctions via Buyee, or eBay, use a different Actor in this portfolio.

### Use case: Japan resale comps for a Switch accessory

A reseller is about to source `nintendo switch` stock from Japan. They run this Actor with `status: "sold_out"`, `maxItems: 30`, and `includeSoldStats: true`. Each listing row has `priceJpy`, `daysToSell`, and `itemUrl`. The extra `marketStats` row gives median / IQR JPY and typical days-to-sell. They skip lots priced above the 75th percentile and keep the item URLs in the buying sheet.

### Quick start input

```json
{
    "keywords": ["nintendo switch"],
    "status": "sold_out",
    "maxItems": 3,
    "includeSoldStats": true
}
```

`maxItems` caps listing rows. A sold-comp report is an extra row and does not consume that cap.

### Input reference

| Field | Type | What it controls |
|---|---|---|
| `keywords` | array | Search phrases, English or Japanese, up to 50. Example: `nintendo switch`. |
| `startUrls` | array | `jp.mercari.com` search or item URLs, up to 50. |
| `status` | enum | `all` (default), `on_sale`, `sold_out`, or `trading`. Prefill `sold_out`. |
| `sort` | enum | `created_time` (default), `score`, `price`, `likes`. |
| `order` | enum | `desc` (default) or `asc`. |
| `priceMin` / `priceMax` | integer | JPY band. Empty = no bound. |
| `maxItems` | integer | Listing cap, 1–500. Default 50. Prefill 3. |
| `includeSoldStats` | boolean | One `marketStats` row per keyword. Default false. Prefill true. |
| `soldStatsSampleSize` | integer | Sold prices sampled for the report, 5–100. Default 30. |
| `fetchItemDetails` | boolean | Adds description, seller name, likes. Default false. Item URLs always fetch detail. |

Provide at least one keyword or a valid Mercari Japan URL. Empty input returns `INVALID_INPUT` with zero listing charges.

### What data you receive

One dataset item is either a listing or a sold-comp summary.

```json
{
    "recordType": "listing",
    "itemId": "m30214061125",
    "itemUrl": "https://jp.mercari.com/item/m30214061125",
    "title": "ドラゴンクエストⅣ",
    "priceJpy": 600,
    "currency": "JPY",
    "status": "sold_out",
    "conditionName": "Poor",
    "sellerId": "389403353",
    "daysToSell": 5,
    "query": "nintendo switch",
    "scrapedAt": "2026-09-15T07:00:00.000Z"
}
```

`marketStats` rows add `medianPriceJpy`, `p25PriceJpy`, `p75PriceJpy`, `minPriceJpy`, `maxPriceJpy`, `meanPriceJpy`, `medianDaysToSell`, and `sampleSize`. Days-to-sell is the gap between Mercari `created` and `updated` on sold items — an approximation, not an official sold-at clock.

| Field | Type | Notes |
|---|---|---|
| `recordType` | string | `listing` or `marketStats` |
| `itemId` / `itemUrl` | string | Mercari id and `jp.mercari.com/item/` page |
| `title` | string | Public listing title |
| `priceJpy` | integer | Listed or sold yen price |
| `status` | string | `on_sale`, `sold_out`, or `trading` |
| `conditionName` | string | New through Bad |
| `sellerId` / `sellerName` | string | Public seller when Mercari exposes it |
| `daysToSell` | number | Approximate created→updated gap on sold items |
| `medianPriceJpy` | number | Sold-comp report only |

### Real-world use cases

#### 1. Sold comps for a keyword

```json
{
    "keywords": ["nintendo switch"],
    "status": "sold_out",
    "maxItems": 30,
    "includeSoldStats": true
}
```

#### 2. Live listings only

```json
{
    "keywords": ["ナイキ ダンク"],
    "status": "on_sale",
    "sort": "created_time",
    "maxItems": 50
}
```

#### 3. Search URL with sold filter

```json
{
    "startUrls": ["https://jp.mercari.com/search?keyword=watch&status=sold_out"],
    "maxItems": 20
}
```

#### 4. Single item URL

```json
{
    "startUrls": ["https://jp.mercari.com/item/m30214061125"]
}
```

#### 5. Price band

```json
{
    "keywords": ["iPhone 15"],
    "status": "sold_out",
    "priceMin": 20000,
    "priceMax": 80000,
    "maxItems": 40
}
```

#### 6. Cheap-first live search

```json
{
    "keywords": ["ポケモンカード"],
    "status": "on_sale",
    "sort": "price",
    "order": "asc",
    "maxItems": 25
}
```

#### 7. Keyword plus item URL

```json
{
    "keywords": ["airpods"],
    "startUrls": ["https://jp.mercari.com/item/m30214061125"],
    "status": "all",
    "maxItems": 15
}
```

#### 8. Bounded agent call

```json
{
    "keywords": ["casio g-shock"],
    "status": "sold_out",
    "maxItems": 10,
    "includeSoldStats": true,
    "fetchItemDetails": false
}
```

### Why agents choose this Actor

- One tool for **live listings and sold prices**, not two SKUs.
- Predictable PPE: `$0.005` per listing, `$0.02` per sold-comp report, `$0.00005` start, plus platform usage.
- `maxItems` is a hard listing ceiling; empty searches finish `VALID_EMPTY` so you can change the query.
- US Mercari URLs finish `INVALID_INPUT` so the run stays on `jp.mercari.com`.
- Flat fields (`priceJpy`, `status`, `itemUrl`, `daysToSell`) stay inside a small token budget.
- Terminal `OUTPUT.outcome` values are `COMPLETE`, `PARTIAL`, `VALID_EMPTY`, `INVALID_INPUT`, or `UPSTREAM_FAILED`.

### Agent checklist

1. Use `jp.mercari.com` keywords or URLs only. Mercari US and Buyee are out of scope.
2. Set `status` to `sold_out` when you need comps; `on_sale` when you need current asking prices.
3. Cap `maxItems` to the budget you can spend at `$0.005` per listing.
4. Turn on `includeSoldStats` only when you need a median/IQR row (`$0.02`).
5. After the run, read `OUTPUT.outcome`, then the dataset. Zero rows with `VALID_EMPTY` means the query matched nothing public.
6. Treat `daysToSell` as approximate. Mercari does not publish an official sold-at timestamp in this public payload.
7. When `OUTPUT.outcome` is `UPSTREAM_FAILED`, retry with Apify Residential in `proxyConfiguration`.

### Use through the API

```bash
curl "https://api.apify.com/v2/acts/khadinakbar~mercari-japan-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "keywords": ["nintendo switch"],
    "status": "sold_out",
    "maxItems": 3,
    "includeSoldStats": true
  }'
```

When the Actor completes, read dataset items from the default dataset and the `OUTPUT` record from the default key-value store.

### Use with AI agents through Apify MCP

> Scrape Mercari Japan sold prices for "nintendo switch". Return up to 10 rows with JPY price, status, item URL, and a sold-comp median. Keep the source on jp.mercari.com.

Point the MCP client at <https://mcp.apify.com>, call `khadinakbar/mercari-japan-scraper`, then read the dataset and `OUTPUT.outcome`.

### Pricing

Pay per event plus platform usage (`isPPEPlatformUsagePaidByUser: true`):

| Event | When | Price |
|---|---|---|
| `apify-actor-start` | Every run | $0.00005 |
| `listing-scraped` | Each saved listing | $0.005 |
| `sold-comp-report` | Each saved `marketStats` row | $0.02 |

A 3-listing sold sample with one report is about `$0.035` in events plus compute/proxy. Invalid input and valid empty searches leave listing and report events unbilled.

Open the live Pricing tab for current event details. This Actor uses Pay per event plus Apify platform usage.

### Best results

- Japanese keywords usually match Mercari's catalog better than English for JP-only goods.
- `created_time` + `sold_out` is the usual comps window; raise `maxItems` if the median looks jumpy.
- `fetchItemDetails` is slower; leave it off unless you need descriptions.
- Direct HTTP works from many networks; switch `proxyConfiguration` to Apify Residential when the public search asks for another route.

### Builder's note

I built this as HTTP-only after I found Mercari Japan's search HTML has no usable `__NEXT_DATA__`. In my testing, `POST https://api.mercari.jp/v2/entities:search` with a fresh ES256 DPoP proof per request returns `items[]` and `meta.nextPageToken`, and `GET https://api.mercari.jp/items/get?id=` fills description and seller. My goal is a truthful sold-comp row, so a rotated DPoP requirement finishes `UPSTREAM_FAILED` rather than inventing prices.

### Connect the workflow

When you need US auction sold comps instead of Mercari Japan, search [eBay All-in-One Scraper](https://apify.com/khadinakbar/ebay-all-in-one-scraper) then pass those listings into the same pricing sheet.

For US vehicle listings rather than Japan C2C, start with [Autotrader Scraper](https://apify.com/khadinakbar/autotrader-scraper) after this Actor when the SKU is a car.

For handmade listing research, feed titles from this Actor into [Etsy All-in-One Scraper](https://apify.com/khadinakbar/etsy-all-in-one-scraper) when the next market is Etsy.

### FAQ and responsible use

**Is this affiliated with Mercari?** No. Mercari is a trademark of its owner. This independent Actor is not endorsed by Mercari, Inc.

**Is scraping allowed?** You are responsible for complying with Mercari's terms, applicable law, and your own data-use policy. Keep collection to public listing fields.

**Why was my run empty?** A valid keyword with zero public matches finishes `SUCCEEDED` / `VALID_EMPTY`. A US URL or empty input finishes `INVALID_INPUT`. When every search route is unavailable the outcome is `UPSTREAM_FAILED`.

**Does it return emails or phones?** No. Public listing fields only.

Open the Actor **Issues** tab for bugs. This Actor is independent research tooling, not legal, investment, or sourcing advice.

# Actor input Schema

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

Product, brand, or model phrases to search on Mercari Japan, for example 'nintendo switch' or 'ナイキ ダンク'. Each keyword is searched separately, up to 50 per run. Use this for market dumps and sold comps. NOT a Mercari US query and not a Buyee URL.

## `startUrls` (type: `array`):

jp.mercari.com search or item URLs, for example https://jp.mercari.com/search?keyword=watch\&status=sold\_out or https://jp.mercari.com/item/m30214061125. Search query params for keyword, status, category\_id, brand\_id, and price are honored. Maximum 50 URLs. Do not paste mercari.com US links.

## `status` (type: `string`):

Which Mercari listing states to return. sold\_out is the sold-price / comps filter. on\_sale is currently listed asking prices. all mixes both. Default all. This is not Mercari Shops inventory outside the public item search.

## `sort` (type: `string`):

How Mercari orders search results before pagination. created\_time (default) is newest first when order is desc. score is Mercari relevance. Use created\_time for sold-comp freshness. This is not a custom ranking formula.

## `order` (type: `string`):

Sort direction for the selected sort field. desc (default) is newest or highest first. Pair price+asc for cheapest listings. Ignored for item-URL lookups.

## `priceMin` (type: `integer`):

Only include listings priced at or above this yen amount, for example 1000. Leave empty for no lower bound. This is Mercari's listed JPY price, not a USD conversion and not a shipping-inclusive total.

## `priceMax` (type: `integer`):

Only include listings priced at or below this yen amount, for example 15000. Leave empty for no upper bound. Combined with priceMin this is a JPY band, not a percent discount filter.

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

Maximum listing rows to save across every keyword and URL. Default 50. Prefill 3 keeps the quality test under five minutes. Sold-comp report rows are extra and do not consume this cap. Hard ceiling 500.

## `includeSoldStats` (type: `boolean`):

When true, add one marketStats row per keyword with median/p25/p75/min/max JPY and approximate days-to-sell from sold\_out listings. Charges $0.02 extra when a report is saved. Default false. Prefill true for the sold-price sample. This is a sample statistic, not a Mercari official index.

## `soldStatsSampleSize` (type: `integer`):

How many sold\_out prices to sample when building the optional sold-comp report. Default 30. Used only when includeSoldStats is true. Does not raise maxItems.

## `fetchItemDetails` (type: `boolean`):

When true, call Mercari item detail for each listing to add description, seller name, likes, and shipping payer. Slower; still charged as listing-scraped only. Default false. Item URLs always fetch detail. This is not a comments scrape.

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

Apify proxy used if direct Mercari requests are blocked. Direct-first, then this proxy. Default Apify proxy on. Prefer RESIDENTIAL if you see HTTP 403. This is not a Mercari account login.

## Actor input object example

```json
{
  "keywords": [
    "nintendo switch"
  ],
  "status": "sold_out",
  "sort": "created_time",
  "order": "desc",
  "maxItems": 3,
  "includeSoldStats": true,
  "soldStatsSampleSize": 30,
  "fetchItemDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Dataset items: one listing per item, plus optional marketStats sold-comp reports.

## `summary` (type: `string`):

Machine-readable OUTPUT with outcome, itemsPushed, charges, and warnings.

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

Detailed RUN\_SUMMARY record for diagnostics.

# 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": [
        "nintendo switch"
    ],
    "status": "sold_out",
    "maxItems": 3,
    "includeSoldStats": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/mercari-japan-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": ["nintendo switch"],
    "status": "sold_out",
    "maxItems": 3,
    "includeSoldStats": True,
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/mercari-japan-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywords": [
    "nintendo switch"
  ],
  "status": "sold_out",
  "maxItems": 3,
  "includeSoldStats": true
}' |
apify call khadinakbar/mercari-japan-scraper --silent --output-dataset

```

## MCP server setup

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

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/cgaCL9cFzK3sfzy99/builds/zow02z3T7eqBzvaff/openapi.json
