# Mercari Japan Scraper & New Listing Monitor - Prices in JPY (`neverempty/mercari-japan-scraper`) Actor

For resellers, sourcing and price research: Mercari Japan listings by keyword or search URL, newest first, with title, price in JPY as a number, on sale or sold, condition, brand, photo, link and listing time. Search sold items to see what things sold for. Monitoring returns only new listings.

- **URL**: https://apify.com/neverempty/mercari-japan-scraper.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (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 $2.92 / 1,000 listing returneds

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

## Mercari Japan Scraper & New Listing Monitor - Prices in JPY

Search **Mercari Japan** (jp.mercari.com) by keyword or by pasting a search URL, and get one row per listing, **newest first**: item id and link, title, **price in JPY as a number**, item status (on sale, trading, sold out), condition, brand, who pays shipping, photo, and **when the listing was created and last updated**.

Turn on **monitoring mode**, schedule the Actor, and each run returns **only new listings**: listings created since the previous run of the same search that were not returned before. Use it to catch new listings for a product, a brand or a price range without paying for the same listings again.

> Unofficial. This Actor is not affiliated with or endorsed by Mercari, Inc. It reads the same search results the jp.mercari.com website shows to anyone without an account. It does not log in and does not collect seller names or seller ids.

### What you can use it for

- **New listing alerts**: schedule monitoring mode for `ポケモンカード` with a price range and send the new rows to Slack, email or a spreadsheet with an Apify integration.
- **Price research**: search with `status: ["sold_out"]` to see what items actually sold for, or `on_sale` for current asking prices.
- **Sourcing and resale (せどり)**: watch a model name with `condition: ["new"]` and a maximum price.
- **Market data**: export listings with price, condition, brand and category id to CSV, Excel or JSON.

### How it works

1. For each keyword (or search URL), the Actor sends the same search request the jp.mercari.com website sends (`api.mercari.jp/v2/entities:search`, with a signing key created for each run; no account).
2. Mercari returns up to 120 listings per results page. The Actor reads pages one at a time, with a 1.5 second pause between pages, until it has `limit` listings or Mercari has no more.
3. Every row says which search and which position it came from (`searchKeyword`, `searchUrl`, `position`, `page`). The same listing found by two searches in one run is returned and charged once.
4. Filters (price, status, condition, excluded words) are applied by Mercari's own search. On 2026-09-17 a price filter of 3,000-5,000 yen returned 8,267 matches and 0 rows outside the range, and `sold_out` returned only sold listings.

If Mercari refuses a request (HTTP 403 or 429), the run stops at once and says so in a free row, instead of retrying harder.

### Input

| Field | Default | What it does |
| --- | --- | --- |
| `keywords` | example keyword | Search terms, one per line. Japanese terms match the most listings. |
| `keyword` | - | One more search term (same field name as other Mercari scrapers). |
| `startUrls` | - | jp.mercari.com search URLs. Their own filters are used: `keyword`, `exclude_keyword`, `price_min`, `price_max`, `status`, `item_condition_id`, `category_id`, `brand_id`, `shipping_payer_id`, `sort`, `order`. A URL with any other filter gets a free `invalid-input` row, because ignoring the filter would return a wider search. |
| `excludeKeyword` | - | Leave out listings containing this word (for example `ジャンク`). |
| `status` | `["on_sale"]` | `on_sale`, `trading`, `sold_out`. An empty list returns all statuses. |
| `condition` | all | `new`, `like_new`, `good`, `fair`, `poor`, `bad`. |
| `priceMin`, `priceMax` | no limit | Price range in yen. |
| `sort`, `order` | `created_time`, `desc` | `created_time` (newest first), `score` (relevance) or `price`; `desc` or `asc`. Monitoring mode always uses newest first. |
| `limit` | `100` | Listings per search, up to 10,000 (a larger value is read as 10,000). In monitoring mode it applies to the first run of a search only. |
| `monitoringMode` | `false` | Return only new listings (see below). |
| `resetMonitoringState` | `false` | Forget what was remembered for the searches in this input. Turn it off again after one run. |

`keyword`, `startUrls`, `status`, `priceMin`, `priceMax`, `sort`, `order` and `limit` use the same names and values as the most used Mercari Japan scraper on Apify, so an input from it can be pasted here. Two differences: without `status` this Actor returns only listings on sale (pass `"status": []` for all), and only search result URLs are read from `startUrls` (not item or category pages).

```json
{
    "keywords": ["ポケモンカード リザードン", "nintendo switch 2"],
    "status": ["on_sale"],
    "priceMin": 3000,
    "priceMax": 30000,
    "limit": 200
}
```

If you leave `keywords`, `keyword` and `startUrls` out with monitoring off, the example keyword `ポケモンカード` is searched and the run log says so. In monitoring mode a keyword or URL is required, so a schedule never pays to watch the example.

### Output

One row per listing (read on 2026-09-17, UTC):

```json
{
    "status": "ok",
    "searchKeyword": "ニンテンドースイッチ",
    "searchUrl": "https://jp.mercari.com/search?keyword=%E3%83%8B%E3%83%B3%E3%83%86%E3%83%B3%E3%83%89%E3%83%BC%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81&price_min=3000&price_max=5000&status=on_sale&sort=created_time&order=desc",
    "position": 1,
    "page": 1,
    "itemId": "m58924705013",
    "itemUrl": "https://jp.mercari.com/item/m58924705013",
    "name": "Switch2 アナザーエデン ビギンズ 通常版 ①",
    "priceJpy": 3980,
    "currency": "JPY",
    "itemStatus": "on_sale",
    "conditionId": 1,
    "condition": "New, unused",
    "conditionJa": "新品、未使用",
    "listingType": "mercari",
    "brand": "Nintendo Switch",
    "categoryId": 7015,
    "shippingPaidBy": "seller",
    "thumbnailUrl": "https://static.mercdn.net/thumb/item/webp/m58924705013_1.jpg?1789606516",
    "photoUrl": "https://static.mercdn.net/item/detail/webp/photos/m58924705013_1.jpg?1789606516",
    "createdAt": "2026-09-17T00:55:16.000Z",
    "updatedAt": "2026-09-17T00:55:16.000Z",
    "isNewSinceLastRun": null
}
```

- `priceJpy` is the listed price in yen as a number. `isPriceHidden` is `true` (and `priceJpy` is `null`) when Mercari marks the price as not shown.
- `itemStatus` is `on_sale`, `trading` (bought, not yet completed) or `sold_out`; `itemStatusRaw` keeps Mercari's own value.
- `condition` is an English label for Mercari's condition id and `conditionJa` is the label Mercari shows. The six ids were checked against Mercari's own item pages on 2026-09-17.
- `shippingPaidBy` is `seller` (送料込み) or `buyer` (着払い), checked the same way; `null` when Mercari does not say (Mercari Shops listings).
- `listingType` is `mercari` or `mercari-shops`. Mercari Shops items have a `shopId` and an item URL under `/shops/product/`.
- **`createdAt` and `updatedAt`**: Mercari's "newest first" order is not strictly by creation time. A listing the seller edits (for example a lower price) can move up, so a row near the top can have an old `createdAt`. On 2026-09-17 the first results page for ニンテンドースイッチ included a listing created about 160 days earlier.
- `isNewSinceLastRun` is `null` with monitoring off, `false` on the first monitoring run of a search and `true` on later runs.
- Seller names, seller ids, buyer ids and descriptions are not returned.

### Rows that are never charged

| Status | Meaning |
| --- | --- |
| `no-results` | Mercari answered with a result count of 0 for the search. |
| `no-new-listings` | Monitoring mode: nothing new in this search since the previous check. |
| `limit-reached` | `limit` listings were returned and Mercari has more (the row says how many Mercari reports; Mercari's count stops at 15,000). |
| `no-further-results-served` | Mercari stopped returning further results pages before the count it reported. On 2026-09-17 results page 85 (listings 10,081-10,200) still worked and page 125 came back empty. |
| `more-new-listings-possible` | Monitoring mode read its maximum of 20 results pages for the search without reaching the listings it had already seen; check more often or narrow the search. |
| `blocked` | Mercari answered HTTP 403 or 429. The run stops. |
| `request-rejected` | Mercari refused the request (HTTP 400 or 401). The run stops. |
| `unreadable` | A results page could not be read. |
| `invalid-input` | A URL that is not a jp.mercari.com search page, uses a filter this Actor does not apply, or another input error. |
| `duplicate-search` | The same keyword and filters appeared earlier in the input. |
| `budget-reached` | The run's maximum total charge had no room for more. |
| `not-checked` | The search was not read (the run stopped earlier, or more than 50 searches were given). |

### Pricing

- **$4.00 per 1,000 listings**, charged only for rows with `status: "ok"`.
- In monitoring mode, also **$0.30 per 1,000 results pages read**, whether or not a page has new listings. Example: 5 keywords checked every 15 minutes, one page each, is 14,400 pages a month = **$4.32**, plus $4.00 per 1,000 new listings returned.
- How many pages a check reads depends on how busy the search is. Measured on 2026-09-17: a check of ロレックス デイトナ read 1 page, and checks of ニンテンドースイッチ 5 minutes apart read 1 to 2 pages. ポケモンカード (on sale, no other filter) changes by about one results page every 1.5 minutes, so a check every 15 minutes reads about 10 pages ($0.003 per check) and returns several hundred new listings. Narrow busy searches with a price range, condition or excluded words.

The Actor reads only as many pages as the run's maximum total charge can pay for (with monitoring on, a page check and a listing each), and a free row says what was not read.

### Monitoring mode

- The Actor remembers, for each search (keyword plus all filters), when it last checked and which listings it returned. Changing any filter makes it a new search.
- **First run of a search**: returns up to `limit` listings, newest first, and remembers the other listings on the results pages it read, back to 15 minutes before the run.
- **Later runs**: return listings **created** since 15 minutes before the previous check that were not returned before. The Actor reads newest first and stops after the first results page that is older than that (by the median update time on the page), or that is mostly listings it has already seen and older than the previous check. At most 20 results pages (2,400 listings) are read per search per run.
- If a results page cannot be read or Mercari refuses a request, the search keeps its previous check time, so the next run looks at the same period again; the run does not report "no new listings" for it.
- The same listing is not returned again by another search of the same input in a later run: listings a search skipped because another search had returned them are remembered for both.
- Older listings that a seller edits can move up Mercari's order; they are not returned again as new. Price changes of listings already returned are not tracked.
- **Do not put the same search in two schedules that can run at the same time**: each run merges only what it handled into the stored record and checks its write, but Apify's key-value store has no atomic update, so two runs finishing at the same moment can still overwrite each other.
- If Apify restarts or moves a run, listings already in the run's dataset are not returned or charged again, results pages already charged are not charged again, and searches already finished are skipped.

### Limits

- Up to 50 searches and up to 10,000 listings per search per run, read one page at a time with a 1.5 second pause between pages (about 85 pages for 10,000 listings).
- In monitoring mode, a run of many busy searches can take several minutes (up to 20 pages per search). Keep the schedule interval longer than a run, so that a run does not start while the previous one is still going.
- This Actor uses Mercari's web search interface, which is not a public API and can change without notice. If Mercari changes it, rows come back as `unreadable` or `request-rejected` instead of wrong data.
- Item descriptions, all photos, seller ratings and comments are not read (one request per listing would multiply the load on Mercari).

# Actor input Schema

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

One search per line, e.g. ポケモンカード or nintendo switch. Japanese keywords match the most listings. The filters below (status, condition, price, sort) apply to every keyword. The same keyword twice (ignoring upper/lower case and full-width characters) is searched once. If you leave both this field and Search URLs empty with monitoring off, the example keyword ポケモンカード is searched; with monitoring on, a keyword or URL is required.

## `keyword` (type: `string`):

One more keyword, in addition to the list above. The field has the same name as in other Mercari scrapers, so an existing input can be pasted as it is.

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

Mercari Japan search result URLs, e.g. https://jp.mercari.com/search?keyword=switch\&status=on\_sale\&price\_min=3000. The filters in the URL are used (keyword, exclude\_keyword, price\_min, price\_max, status, item\_condition\_id, category\_id, brand\_id, shipping\_payer\_id, sort, order) and the filters below are not applied to it. A URL with any other filter, and item, profile or category pages, come back as a free row with the reason, because ignoring a filter would return a wider search than the URL shows.

## `excludeKeyword` (type: `string`):

Listings containing this word are left out by Mercari's own search (for example ジャンク for junk items). Applies to the keywords above.

## `status` (type: `array`):

on\_sale = still for sale, trading = bought and being completed, sold\_out = sold. Leave the default to get only listings still for sale; choose sold\_out to see what things sold for. An empty list returns all statuses.

## `condition` (type: `array`):

Keep only these conditions, as the seller set them. Empty = every condition.

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

Only listings priced at or above this many yen. Empty or 0 = no minimum.

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

Only listings priced at or below this many yen. Empty or 0 = no maximum.

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

created\_time is Mercari's "newest first" order. Mercari also moves a listing up this order when the seller updates it (for example lowers the price), so every row has both createdAt and updatedAt. Monitoring mode always uses newest first.

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

desc = newest or highest price first; asc = oldest or lowest price first.

## `limit` (type: `integer`):

How many listings to return for each keyword or URL (Mercari serves 120 per results page). Up to 10,000 per search; a larger value is read as 10,000. With monitoring on, this limit applies only to the first run of a search; later runs return every new listing they find, reading at most 20 results pages (2,400 listings) per search.

## `monitoringMode` (type: `boolean`):

Off = every run returns the current results. On = the Actor remembers, for each search (keyword plus filters), when it last checked and which listings it returned. The first run of a search returns up to the limit (newest first) and remembers the other listings on the results pages it read. Later runs return only listings created since the previous check (with a 15-minute overlap) that were not returned before, reading newest first until a results page is older than that or already seen, at most 20 pages per search. Busy searches read more pages per check (on 2026-09-17, ポケモンカード with no filter changed by about one page every 1.5 minutes). Older listings that a seller edits move up Mercari's order but are not returned again. **In monitoring mode every results page read costs $0.30 per 1,000 pages, whether or not it has new listings**, plus the price of each listing row returned. Example: 5 keywords checked every 15 minutes, one page each = 14,400 pages a month = $4.32. Do not put the same search in two schedules that can run at the same time.

## `resetMonitoringState` (type: `boolean`):

Clears what was remembered for the searches in this input only, so this run is a first run for them again. Turn it off again after one run: left on in a schedule, every run is a first run.

## Actor input object example

```json
{
  "keywords": [
    "ポケモンカード"
  ],
  "status": [
    "on_sale"
  ],
  "sort": "created_time",
  "order": "desc",
  "limit": 100,
  "monitoringMode": false,
  "resetMonitoringState": false
}
```

# Actor output Schema

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

One row per Mercari Japan listing found by your searches: item id and URL, title, price in JPY, item status (on sale, trading, sold out), condition, Mercari or Mercari Shops, brand, category id, who pays shipping, photo and thumbnail URLs, and when the listing was created and last updated, with the search and position it came from. Searches with no results, refused requests and invalid input come back as free rows that say why.

# 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("neverempty/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": ["ポケモンカード"] }

# Run the Actor and wait for it to finish
run = client.actor("neverempty/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": [
    "ポケモンカード"
  ]
}' |
apify call neverempty/mercari-japan-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/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/Q6cJIBiCscnGTnQrl/builds/TVnm4DsNybysMX4nB/openapi.json
