# Mercari Japan Scraper - Products, Sellers & Reviews (`abotapi/mercari-jp-scraper`) Actor

From $0.80/1K. Scrape Mercari Japan listings, sellers and reviews at scale. Extract names, prices, conditions, photos, shipping details, descriptions and seller profiles. Search by keyword with nine filters or paste Mercari URLs directly.

- **URL**: https://apify.com/abotapi/mercari-jp-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Features:** Limited permissions
- **Stats:** 41 total users, 12 monthly users, 64.8% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 results

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: Items, Sellers & Reviews

Mercari Japan Scraper turns Mercari (jp.mercari.com), Japan's largest consumer marketplace app, into structured data. Search by keyword with nine filters, paste marketplace URLs directly, or pull every review left for one or more sellers. Get listing names, prices, condition, brand, category, photos, shipping details and full seller profiles (rating breakdown, sell count, follower counts, official flag), then export to JSON, CSV or Excel, or pull results straight into your app through the API.

### Why This Scraper?

- **Three ways to find data.** Search by keyword with nine filters, paste any jp.mercari.com search, item or profile URL, or list seller IDs to pull their review history.
- **Detail enrichment on demand.** Turn on `fetchDetails` to add full descriptions, every photo, comments, hashtags and a complete seller profile (bio, follower counts, rating split). Leave it off for lean, fast runs.
- **Rich seller data.** With `fetchDetails` on, listings carry the seller's score, sell count, star rating, ratings breakdown, follower counts, official flag and SMS-verified status; review rows always carry the reviewed seller's score, ratings breakdown, follower counts and official flag.
- **Filter at the source.** Status, condition, shipping payer, price range, brand, category and exclude-keyword all flow into the search itself, so you only pay for items you actually wanted.
- **Multi-keyword and multi-seller runs.** List several keywords, URLs or seller IDs in one run; searches share the budget so each keyword or search URL gets a share, and Max Listings caps the whole run.
- **Built for monitoring.** Incremental mode returns only new, changed, reappeared or expired listings on repeat runs, and Resume continues one interrupted run without re-collecting or re-billing rows it already has.

### Use Cases

- **Resellers and arbitrage:** compare prices for the same keyword or category across many listings and sellers before buying or listing.
- **Seller due diligence:** pull a seller's full review history, rating breakdown and follower counts before a trade.
- **Price and market monitoring:** track a keyword or category over time with incremental mode and inspect `changedFields` for what moved.
- **Brand and category watching:** keep an eye on a set of brand or category IDs and get only the new listings on each run.
- **Marketplace analytics:** feed listing and seller data into a spreadsheet, dashboard or BI tool.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live listing.

| Field | Example |
| --- | --- |
| `id` | `m12345678901` |
| `url` | `https://jp.mercari.com/item/m12345678901` |
| `itemType` | `marketplace` (or `shop`) |
| `name` | `Nintendo Switch 有機ELモデル 本体` |
| `price` | `28000` |
| `currency` | `JPY` |
| `status` | `on_sale` |
| `itemCondition` | `like new` |
| `categoryId` | `112` |
| `itemBrandName` | `Nintendo` |
| `shippingPayer` | `seller` |
| `thumbnail` | `https://static.mercdn.net/thumb/item/webp/m12345678901_1.jpg` |
| `photos` | `["https://static.mercdn.net/item/detail/orig/photos/m12345678901_1.jpg"]` |
| `sellerId` | `123456789` |
| `createdAt` | `2026-01-01T00:00:00+00:00` |

An item row carries no `kind` field. Turning on `fetchDetails` additionally fills `description`, `sellerName`, `itemConditionSubname`, `categoryName`, `categoryPath`, `shippingMethodName`, `numLikes`, `numComments`, `comments`, `hashtags`, and the full seller profile (`sellerIntroduction`, `sellerScore`, `sellerStarRating`, `sellerFollowerCount`, `sellerFollowingCount`, `sellerIsOfficial`, `sellerSmsVerified`); those columns are `null` when detail enrichment is off, so every row has the same shape either way. A review row (reviews mode) carries `kind: review`, `subject` (`seller` or `buyer`), `fame` (`good`/`normal`/`bad`), `message`, `raterName`, an `id` of `<sellerId>:<pagerId>` that stays stable across runs, and the reviewed seller's profile: `sellerId`, `sellerName`, `sellerProfileUrl`, `sellerIntroduction`, `sellerNumRatings`, `sellerStarRating`, `sellerRatingsGood`/`sellerRatingsNormal`/`sellerRatingsBad`, `sellerFollowerCount`, `sellerFollowingCount` and `sellerIsOfficial`, so a single export already has seller context next to each review.

### How to Use

1. Pick a **mode**: `search` (keyword + filters), `url` (paste marketplace links), or `reviews` (seller IDs).
2. Fill in the fields for that mode, and turn on **Fetch Item Details** if you need full descriptions, all photos or rich seller profiles.
3. Set **Max Listings** (and optionally **Max Pages Per Search**) to control run size and cost, then click **Start**.
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Search by keyword with filters:**

```json
{
  "mode": "search",
  "queries": ["nintendo switch"],
  "status": "on_sale",
  "sortBy": "created-desc",
  "maxListings": 100
}
```

**Multi-keyword search with a price range and condition filter:**

```json
{
  "mode": "search",
  "queries": ["iphone 15", "iphone 14"],
  "minPrice": 30000,
  "maxPrice": 80000,
  "itemCondition": ["1", "2"],
  "maxListings": 200
}
```

**URL mode: a search link plus a direct item page, enriched:**

```json
{
  "mode": "url",
  "urls": [
    "https://jp.mercari.com/search?keyword=pokemon&sort=created_time&order=desc",
    "https://jp.mercari.com/item/m12345678901"
  ],
  "fetchDetails": true,
  "maxListings": 150
}
```

#### URL mode: supported link shapes

| Shape | Example | Output |
|---|---|---|
| Keyword search with sort | `https://jp.mercari.com/search?keyword=iphone&sort=price&order=asc` | listings |
| Category search | `https://jp.mercari.com/search?category_id=859` | listings |
| Paginated search | `https://jp.mercari.com/search?keyword=iphone&page_token=v1%3A1` | listings from that page onward |
| Filtered search | `https://jp.mercari.com/search?keyword=iphone&brand_id=3272&status=on_sale&price_min=1000&price_max=50000&item_condition_id=1` | listings |
| Item page | `https://jp.mercari.com/item/m98254537705` | one listing |
| English item page | `https://jp.mercari.com/en/item/m10455274260` | one listing |
| English search | `https://jp.mercari.com/en/search?keyword=iphone` | listings |
| Seller profile | `https://jp.mercari.com/user/profile/140382083` | the seller's reviews |
| Seller reviews | `https://jp.mercari.com/user/reviews/186383006` | the seller's reviews |
| Legacy item host | `https://item.mercari.com/jp/m17042911590/` | one listing |
| Shop product, seller-scoped search (`seller_id=`), `/categories?category_id=` | | accepted; logged with a warning if they return nothing |

Category IDs and Brand IDs in Search mode take either the number from a Mercari URL (`category_id=859`, `brand_id=3272`) or the name as Mercari shows it (for example `Smartphones` or `Apple`), which the actor looks up in Mercari's own category and brand lists before searching. A name that matches nothing, or matches several categories or brands, stops the run with a message naming it.

**Reviews mode: harvest one seller's review history:**

```json
{
  "mode": "reviews",
  "sellerIds": ["123456789", "https://jp.mercari.com/user/profile/140382083"],
  "reviewSubject": "seller",
  "maxListings": 300
}
```

Each `sellerIds` entry can be a bare numeric ID or the full `/user/profile/<id>` / `/user/reviews/<id>` URL; both work, and you can mix them in one list.

`/user/profile/<id>` and `/user/reviews/<id>` URLs work the same way in `url` mode: any such URL is treated as an implicit reviews request for that seller, alongside any other URLs in the list.

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/mercari-jp-scraper").call(run_input={"mode": "search", "queries": ["nintendo switch"]})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["name"], item["price"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/mercari-jp-scraper').call({ mode: 'search', queries: ['nintendo switch'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run or dataset ID and the actor reads that dataset first, skipping every item and review it already contains, so this run only returns what is new. An invalid ID fails the run immediately, before any scraping starts. The actor also checkpoints its own progress, so a platform migration or a Resurrect of a failed run continues that exact run with no duplicate rows.
- **Incremental mode** (`incrementalMode`) is for running the same search or URLs again and again (for example, daily) and getting only what changed. Review rows are not classified. UPDATED means listing content changed (price, status, title, description, photos, condition, shipping and similar); `changedFields` names what. Live counters (likes, comment count and the seller rating, follower and sell-count statistics) are shown in the output but excluded from the comparison, as is anything you list in `ignoreFieldsForChanges`. The auction, promotions, size, buyer and shop fields are compared like every other field; for a tracked item saved by an older version they start counting as a change from the second run after the upgrade, so the upgrade itself causes no wave of UPDATED rows. A run that starts from a pasted search URL with a page token, is capped, or stops early never produces EXPIRED. Each item row is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED`, or `EXPIRED` (only after a run that scanned the whole tracked scope, and only with `emitExpired`). State is kept per search/URL/filter combination in a dedicated store and compared without re-visiting the site, so classification costs no extra requests. `stateKey` names or shares that state; leaving it empty derives a key automatically from the search scope and filters. Turning on Incremental mode together with Resume on a search that already has tracked state fails the run with a clear message, since the two features would otherwise disagree on the baseline.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape: the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each record, not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify → Settings → Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` (keyword + filters), `url` (paste marketplace URLs), or `reviews` (seller IDs). |
| `queries` | array | none (prefill: `["nintendo switch"]`) | Keywords to search for (Search mode only). Multi-keyword supported. Japanese and English both work. Each keyword runs its own paginated search; results are combined. |
| `status` | string | `on_sale` | Listing availability status (Search mode only): `any`, `on_sale`, `sold_out`, `trading`. |
| `statuses` | array | none | Multi-select of `on_sale`, `sold_out`, `trading` (Search mode only). When set it overrides `status`; leave empty to use the single select. |
| `sortBy` | string | `score-desc` | Result ordering (Search mode only): `score-desc`, `created-desc`, `created-asc`, `price-asc`, `price-desc`, `num-likes-desc`. |
| `minPrice` | integer | none | Minimum price in JPY. Leave empty for no minimum. |
| `maxPrice` | integer | none | Maximum price in JPY. Leave empty for no maximum. |
| `itemCondition` | array | none (prefill: empty) | Filter by condition (Search mode only). Multiple selectable: `1`=New, `2`=Like new, `3`=No noticeable scratches, `4`=Some scratches, `5`=Damaged, `6`=Poor condition. |
| `shippingPayer` | string | `any` | Who pays shipping (Search mode only): `any`, `seller` (free shipping), `buyer`. |
| `categoryIds` | array | none (prefill: empty) | Category IDs or names (Search mode only): a number from a Mercari URL (`category_id=859` is smartphones) or the Japanese or English category name. Leave empty for all categories. |
| `brandIds` | array | none (prefill: empty) | Brand IDs or names (Search mode only): a number from a Mercari URL (`brand_id=3272` is Apple) or the brand name as Mercari shows it. |
| `excludeKeyword` | string | none | Items matching this keyword are filtered out by the upstream search (Search mode only). |
| `urls` | array | the 10 example links below | Mercari Japan links (URL mode only). Left untouched, URL mode scrapes one example of each shape below (a behaviour change: it used to start from one search link); replace them with your own. Filter-mode fields are ignored. Unrecognised links log a warning. |
| `sellerIds` | array | none (prefill: `["https://jp.mercari.com/user/profile/140382083", "140382083"]`) | Seller IDs or seller-page URLs (Reviews mode only): a bare numeric ID (`"140382083"`) or the full `/user/profile/<id>` / `/user/reviews/<id>` URL both work, and you can mix them in one list. Multi-seller supported; each seller's reviews are surfaced as separate rows. |
| `reviewSubject` | string | `seller` | Whether to fetch reviews left for the user as seller, as buyer, or both (Reviews mode only): `seller`, `buyer`, `both`. |
| `reviewFame` | array | none (prefill: all three) | Rating buckets to include (Reviews mode only): `good`, `normal`, `bad`. Leave empty for all three. |
| `maxPages` | integer | none (prefill: `0` = walk every page) | Optional bound on pages walked per keyword / URL / seller. About 20 listings per page in Search/URL mode; up to 100 reviews per page in Reviews mode. |
| `maxListings` | integer | `20` | Cap across all keywords/URLs/sellers combined. Applies to listings and to review rows in Reviews mode; values above `100000` and `0` are both treated as `100000` (still capped by `maxPages`). Review rows bill as normal result rows. |
| `resumeFromRunId` | string | none | Optional: paste a previous run ID (or dataset ID) from this actor. Rows already collected there are skipped, so this run only returns new ones. |
| `incrementalMode` | boolean | `false` | Turn on for daily or recurring monitoring of the same search/URLs. Classifies every item row as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED. Review rows are not classified. |
| `stateKey` | string | none | Optional. Names a monitoring campaign to keep its state stable, or lets differently-configured runs deliberately share state. Leave empty to auto-derive a key from the search/URL and filter settings. |
| `emitUnchanged` | boolean | `false` | Also return (and bill) items that have not changed since the last run, marked UNCHANGED. |
| `emitExpired` | boolean | `false` | Also return (and bill) items that were present before but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked scope. |
| `ignoreFieldsForChanges` | array | `[]` | Output field names (top-level, for example `photos`) to exclude from UPDATED detection and from `changedFields` in incremental mode. The fields stay in the output; changing the list does not re-bill tracked items. |
| `fetchDetails` | boolean | `false` | If true (Search/URL mode only), the actor visits each listing's detail page to add full description, all photos, comment count, like count and seller rating breakdown. Adds one request per listing. |
| `proxy` | object | none (prefill: Apify Proxy) | Connection settings. |
| `mcpConnectors` | array | none | Optional: send a summary of each record to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | none | Notion connector only: page under which records are created. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live listing.

```json
{
  "id": "m12345678901",
  "url": "https://jp.mercari.com/item/m12345678901",
  "itemType": "marketplace",
  "name": "Nintendo Switch 有機ELモデル 本体 ホワイト",
  "price": 28000,
  "currency": "JPY",
  "status": "on_sale",
  "itemCondition": "no noticeable scratches or stains",
  "itemConditionSubname": "目立った傷や汚れなし",
  "categoryId": "112",
  "categoryName": "家庭用ゲーム本体",
  "categoryPath": "ゲーム・おもちゃ・グッズ > テレビゲーム > 家庭用ゲーム本体",
  "itemBrandId": "1234",
  "itemBrandName": "Nintendo",
  "shippingPayer": "seller",
  "shippingMethodName": "らくらくメルカリ便",
  "thumbnail": "https://static.mercdn.net/thumb/item/webp/m12345678901_1.jpg",
  "photos": [
    "https://static.mercdn.net/item/detail/orig/photos/m12345678901_1.jpg",
    "https://static.mercdn.net/item/detail/orig/photos/m12345678901_2.jpg"
  ],
  "description": "新品未使用に近い状態です。動作確認済みです。箱と付属品すべて揃っています。",
  "numLikes": 12,
  "numComments": 2,
  "hashtags": ["ニンテンドースイッチ", "任天堂"],
  "sellerId": "123456789",
  "sellerName": "サンプル太郎",
  "sellerIntroduction": "フォロー割引あります。よろしくお願いします。",
  "sellerScore": 348,
  "sellerNumRatings": 350,
  "sellerStarRating": 5,
  "sellerFollowerCount": 42,
  "sellerFollowingCount": 10,
  "sellerIsOfficial": false,
  "sellerSmsVerified": true,
  "createdAt": "2026-01-01T00:00:00+00:00",
  "updatedAt": "2026-01-05T00:00:00+00:00"
}
```

A review row (Reviews mode, or a `/user/profile`/`/user/reviews` URL) has a different shape: `id` (`<sellerId>:<pagerId>`), `kind` set to `review`, `subject`, `fame`, `message`, `createdAt`, `raterId`/`raterName`, plus the reviewed seller's profile fields shown in the Data You Get section above.

#### Output views

The dataset has six views in the Console: **Results** (every row), **Listings Overview** (price, status, condition, brand), **Seller Profiles** (seller rating, sell count, follower counts), **Reviews** (review rows only), **Listing Details** (description, photos, comments, hashtags; filled when `fetchDetails` is on) and **Incremental Changes** (`changeType` and `changedFields`).

### Plan Requirement

Mercari Japan loads from Apify datacenter proxies: in our measurements the search, item-detail and seller-review requests all succeeded on a datacenter connection, so residential proxies are not required and a free-plan account can run the actor. Pinning a country is optional. The default connection is tried first; if it is unavailable the actor continues on a backup connection and logs:

- `Served over the backup connection (the default connection was unavailable).`
- For accounts without residential access: `The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable.`

If no page could be loaded at all, the run ends with a status message instead of silently returning nothing:

- `The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required: https://apify.com/pricing. If you entered your own proxy URLs, check that their credentials are valid.`
- `No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Mercari pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again.`
- `Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later.`

### FAQ

#### How much does it cost?

Pay per result: each returned listing or review row is one result event (at the Free plan rate $0.0016 per result, $1.60 per 1,000; higher Apify plans pay less), plus a one-off actor-start event per run. Turning on `fetchDetails` adds an item-detail-enrichment event ($0.0008 at the Free rate) per returned row, never for rows suppressed by incremental mode. A direct `/item/<id>` URL in `url` mode always incurs that same detail event, even with `fetchDetails` off, since fetching the item page is the only way to resolve it. Review rows bill as normal result rows and count toward Max Listings. The **Pricing** tab shows the current rates. Use **Max Listings** to cap the cost of any run.

#### Is it legal to scrape Mercari?

This actor collects only publicly available marketplace data. You are responsible for how you use it: follow Mercari's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Listing prices and conditions are generally facts, but seller photos, bios and review text may be subject to third-party rights.

#### Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. Each run then returns only new, updated, reappeared or expired records against a state the actor keeps for that search, and unchanged ones are not billed unless you opt in with `emitUnchanged`.

#### What's the difference between Resume and Incremental mode?

They solve different problems. **Resume** (`resumeFromRunId`) continues one specific interrupted run so it does not restart from scratch. **Incremental mode** is for running the same search or URLs repeatedly (for example, every day) and getting only what changed each time. Using both together on a search that already has incremental state fails the run, since the actor cannot tell which baseline to use.

#### Why did my run fail instead of returning an empty dataset?

A run fails only when it cannot be trusted to mean anything: an invalid `resumeFromRunId`, or turning on Incremental mode with Resume on a search that already has tracked state. Everything else, including the site rejecting requests, a keyword with no matches, or no keywords/URLs/seller IDs at all, finishes as a normal successful run with an empty (or partial) dataset and a status message explaining why.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

### 🔗 Want more e-commerce data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🛒 <a href="https://apify.com/abotapi/nitori-net-jp-scraper"><b>Nitori Japan Furniture &amp; Home Goods Scraper</b></a><br>Scrape Nitori Japan (nitori-net.jp) furniture and home goods by keyword, category or...</td><td>👗 <a href="https://apify.com/abotapi/zozotown-scraper"><b>ZOZOTOWN</b></a><br>Scrape ZOZOTOWN (zozo.jp), Japan's largest fashion marketplace: name, brand, JPY price...</td></tr>
<tr><td>🛒 <a href="https://apify.com/abotapi/depop-scraper"><b>Depop Scraper</b></a><br>From $1/1K. Scrape Depop search results, listings, shops, and reviews to JSON, CSV, or...</td><td>🧩 <a href="https://apify.com/abotapi/rakuten-ichiba-scraper"><b>Rakuten</b></a><br>Scrape Rakuten Ichiba (rakuten.co.jp): name, JPY price, reference price and discount...</td></tr>
<tr><td>🧩 <a href="https://apify.com/abotapi/suumo-jp-scraper"><b>Suumo.jp Scraper</b></a><br>Scrape Suumo, Japan's largest property portal: rental rooms with rent, management fees...</td><td>🧩 <a href="https://apify.com/abotapi/mistore-jp-scraper"><b>Isetan Mitsukoshi</b></a><br>Scrape the Isetan Mitsukoshi department store online shop (mistore.jp). Search by keyword...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/mercari-jp-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

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

How to find data to scrape. 'search' and 'url' return items; 'reviews' returns one row per review left for the listed seller IDs.

## `queries` (type: `array`):

Keywords to search for (Search mode only). Multi-keyword supported. Japanese and English both work. Each keyword runs its own paginated search; results are combined.

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

Listing availability status (Search mode only).

## `statuses` (type: `array`):

Optional multi-select (Search mode only). Pick any combination of On sale, Sold out and In trade. When set it overrides "Item Status" above; leave empty to use the single select.

## `sortBy` (type: `string`):

Result ordering (Search mode only). Default = relevance score.

## `minPrice` (type: `integer`):

Minimum price in JPY. Leave empty for no minimum.

## `maxPrice` (type: `integer`):

Maximum price in JPY. Leave empty for no maximum.

## `itemCondition` (type: `array`):

Filter by condition (Search mode only). Multiple selectable. 1=New, 2=Like new, 3=No noticeable scratches, 4=Some scratches, 5=Damaged, 6=Poor condition.

## `shippingPayer` (type: `string`):

Who pays shipping (Search mode only).

## `categoryIds` (type: `array`):

Category IDs (Search mode only): the number from a Mercari URL (category_id=859 is smartphones), or the category name in Japanese or English as Mercari shows it (for example Smartphones), looked up in Mercari's own category list. A name that matches nothing, or several categories, stops the run and says which. Leave empty for all categories.

## `brandIds` (type: `array`):

Brand IDs (Search mode only): the number from a Mercari URL (brand_id=3272 is Apple), or the brand name as Mercari shows it (for example Apple or Nike), looked up in Mercari's own brand list. A name that matches nothing, or several brands, stops the run and says which.

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

Items matching this keyword are filtered out by the upstream search (Search mode only).

## `urls` (type: `array`):

Mercari Japan links (URL mode only), one per line. Accepted: search and category links (keyword, category_id, brand_id, status, price, condition, sort, seller_id, page_token), item pages (/item/<id>, /en/item/<id>, /shops/product/<id>, legacy item.mercari.com/jp/<id>/), and seller /user/profile/<id> or /user/reviews/<id> pages (surfaces every review). Filter-mode fields are ignored. Left untouched, URL mode scrapes the example of each shape; replace them with your own links. Unrecognised links log a warning.

## `sellerIds` (type: `array`):

Seller IDs or seller-page URLs (Reviews mode only). Each entry can be a numeric seller ID or a full /user/profile/<id> or /user/reviews/<id> URL; both work. Multi-seller supported; each seller's reviews are surfaced as separate rows.

## `reviewSubject` (type: `string`):

Whether to fetch reviews left for the user as seller, as buyer, or both (Reviews mode only).

## `reviewFame` (type: `array`):

Rating buckets to include (Reviews mode only). 'good' = positive, 'normal' = neutral, 'bad' = negative. Default = all three.

## `maxPages` (type: `integer`):

Optional bound on pages walked per keyword / URL / seller. ~20 listings per page in Search/URL mode; up to 100 reviews per page in Reviews mode. Leave empty to walk every result page.

## `maxListings` (type: `integer`):

Cap across all keywords/URLs/sellers combined; applies to listings and to review rows in Reviews mode. Values above 100000 and 0 are both treated as 100000 (still capped by maxPages).

## `fetchDetails` (type: `boolean`):

If true (Search/URL mode only), the actor visits each listing's detail page to enrich the record with full description, all photos, comment count, like count, and seller rating breakdown (good/normal/bad). Adds one request per listing.

## `proxy` (type: `object`):

Apify Proxy default group is sufficient. Mercari Japan accepts requests from any geo. Country pin is optional.

## `resumeFromRunId` (type: `string`):

Optional: paste a previous run ID (or dataset ID) from this actor. Rows already collected there are skipped, so this run only returns new ones. Leave empty for a normal run. For recurring daily monitoring of the same search, use Incremental mode below instead.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring of the same search/URLs. The first run returns all matching items as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED items. UPDATED means a listing's content changed since the last run (price, status, title, description, photos, condition, shipping and similar fields); changedFields names exactly which. Live counters that move on their own are excluded from the comparison and never cause UPDATED: likes, comments count and the seller's rating/follower/sell-count statistics (they are still shown in the output). You can exclude more with "Ignore fields when detecting changes". Turn on "Emit unchanged" or "Emit expired" only when you also want those items returned (and billed). State is kept separately per search/URL and filter setup; use State key to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from run ID above.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the search/URL and filter settings, so different searches then never mix state with each other.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return items that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have, so leave it off unless you specifically want the full snapshot every run.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return items that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search, not when Max listings/Max pages capped it or when Resume was used. This returns, and bills, extra synthetic rows, so leave it off unless you need expiry tracking.

## `ignoreFieldsForChanges` (type: `array`):

Optional. Output field names (top-level, for example photos or description) to exclude from UPDATED change detection and from changedFields, in addition to the built-in exclusions (likes, comments count and seller statistics). Use this if a field in your setup changes on its own without a real listing change. The fields stay in the output; they just stop counting as a change. Changing this list does not re-bill your tracked items.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON; the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "queries": [
    "nintendo switch"
  ],
  "status": "on_sale",
  "sortBy": "score-desc",
  "itemCondition": [],
  "shippingPayer": "any",
  "categoryIds": [],
  "brandIds": [],
  "urls": [
    "https://jp.mercari.com/search?keyword=iphone&sort=price&order=asc",
    "https://jp.mercari.com/search?category_id=859",
    "https://jp.mercari.com/search?keyword=iphone&page_token=v1%3A1",
    "https://jp.mercari.com/search?keyword=iphone&brand_id=3272&status=on_sale&price_min=1000&price_max=50000&item_condition_id=1",
    "https://jp.mercari.com/item/m98254537705",
    "https://jp.mercari.com/en/item/m10455274260",
    "https://jp.mercari.com/en/search?keyword=iphone",
    "https://jp.mercari.com/user/profile/140382083",
    "https://jp.mercari.com/user/reviews/186383006",
    "https://item.mercari.com/jp/m17042911590/"
  ],
  "sellerIds": [
    "https://jp.mercari.com/user/profile/140382083",
    "140382083"
  ],
  "reviewSubject": "seller",
  "reviewFame": [
    "good",
    "normal",
    "bad"
  ],
  "maxPages": 0,
  "maxListings": 20,
  "fetchDetails": false,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

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

No description

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

No description

## `sellers` (type: `string`):

No description

## `reviews` (type: `string`):

No description

## `detail` (type: `string`):

No description

## `changes` (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 = {
    "mode": "search",
    "queries": [
        "nintendo switch"
    ],
    "itemCondition": [],
    "categoryIds": [],
    "brandIds": [],
    "urls": [
        "https://jp.mercari.com/search?keyword=iphone&sort=price&order=asc",
        "https://jp.mercari.com/search?category_id=859",
        "https://jp.mercari.com/search?keyword=iphone&page_token=v1%3A1",
        "https://jp.mercari.com/search?keyword=iphone&brand_id=3272&status=on_sale&price_min=1000&price_max=50000&item_condition_id=1",
        "https://jp.mercari.com/item/m98254537705",
        "https://jp.mercari.com/en/item/m10455274260",
        "https://jp.mercari.com/en/search?keyword=iphone",
        "https://jp.mercari.com/user/profile/140382083",
        "https://jp.mercari.com/user/reviews/186383006",
        "https://item.mercari.com/jp/m17042911590/"
    ],
    "sellerIds": [
        "https://jp.mercari.com/user/profile/140382083",
        "140382083"
    ],
    "reviewFame": [
        "good",
        "normal",
        "bad"
    ],
    "maxPages": 0,
    "maxListings": 20,
    "proxy": {
        "useApifyProxy": true
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "ignoreFieldsForChanges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/mercari-jp-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 = {
    "mode": "search",
    "queries": ["nintendo switch"],
    "itemCondition": [],
    "categoryIds": [],
    "brandIds": [],
    "urls": [
        "https://jp.mercari.com/search?keyword=iphone&sort=price&order=asc",
        "https://jp.mercari.com/search?category_id=859",
        "https://jp.mercari.com/search?keyword=iphone&page_token=v1%3A1",
        "https://jp.mercari.com/search?keyword=iphone&brand_id=3272&status=on_sale&price_min=1000&price_max=50000&item_condition_id=1",
        "https://jp.mercari.com/item/m98254537705",
        "https://jp.mercari.com/en/item/m10455274260",
        "https://jp.mercari.com/en/search?keyword=iphone",
        "https://jp.mercari.com/user/profile/140382083",
        "https://jp.mercari.com/user/reviews/186383006",
        "https://item.mercari.com/jp/m17042911590/",
    ],
    "sellerIds": [
        "https://jp.mercari.com/user/profile/140382083",
        "140382083",
    ],
    "reviewFame": [
        "good",
        "normal",
        "bad",
    ],
    "maxPages": 0,
    "maxListings": 20,
    "proxy": { "useApifyProxy": True },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/mercari-jp-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 '{
  "mode": "search",
  "queries": [
    "nintendo switch"
  ],
  "itemCondition": [],
  "categoryIds": [],
  "brandIds": [],
  "urls": [
    "https://jp.mercari.com/search?keyword=iphone&sort=price&order=asc",
    "https://jp.mercari.com/search?category_id=859",
    "https://jp.mercari.com/search?keyword=iphone&page_token=v1%3A1",
    "https://jp.mercari.com/search?keyword=iphone&brand_id=3272&status=on_sale&price_min=1000&price_max=50000&item_condition_id=1",
    "https://jp.mercari.com/item/m98254537705",
    "https://jp.mercari.com/en/item/m10455274260",
    "https://jp.mercari.com/en/search?keyword=iphone",
    "https://jp.mercari.com/user/profile/140382083",
    "https://jp.mercari.com/user/reviews/186383006",
    "https://item.mercari.com/jp/m17042911590/"
  ],
  "sellerIds": [
    "https://jp.mercari.com/user/profile/140382083",
    "140382083"
  ],
  "reviewFame": [
    "good",
    "normal",
    "bad"
  ],
  "maxPages": 0,
  "maxListings": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/mercari-jp-scraper --silent --output-dataset

```

## MCP server setup

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