# Yodobashi Scraper: Prices, Points, Specs & Reviews (`abotapi/yodobashi-com-scraper`) Actor

Scrape yodobashi.com electronics and appliances: JPY price, list price and discount, reward points, stock and delivery, images, specifications, variants and customer reviews. Search by keyword with the store's own category, brand, price and sort filters, or paste product, category and search URLs.

- **URL**: https://apify.com/abotapi/yodobashi-com-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Features:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 product 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

## Yodobashi.com Scraper: Prices, Reward Points, Stock & Reviews

Yodobashi.com Scraper turns Yodobashi Camera, Japan's largest electronics and appliance retailer, into structured product data: price, list price and discount, Gold Point reward value, stock and delivery, images, full specifications, variants and customer reviews. Search by keyword with the store's own filters, or paste product, category, brand and search links, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.

### Why This Scraper?

- **Two ways to find products.** Search by keyword with the store's own filters (category, brand, price range, sort), or paste product, category, brand and search links exactly as you copied them.
- **Price and reward points kept separate.** Price, list price, discount and Gold Point reward value are their own fields, never folded together, so a monitoring feed never has to guess what a number includes.
- **Optional per-product enrichment.** Full description, complete specification table, image gallery, per-variant pricing and stock, and customer reviews are switched on only when you need them, and each enriched product adds one enrichment charge no matter how much extra data it carried back.
- **Built for schedules.** Incremental mode returns only new and changed products on recurring runs, and a refused run fails loudly instead of returning an empty dataset.
- **Promoted tiles never bill you.** Advertising slots on search and category pages are excluded from the dataset and never charged, so your row count always matches the store's own result count.
- **Japan-only scope, done honestly.** Every price is JPY and there is no unused country selector, because Yodobashi itself runs a single Japan-only storefront.
- **Detail failures repair instead of erase.** A product whose detail page temporarily fails to load keeps its previous specifications from the prior run instead of being overwritten with blanks.

### Use Cases

- **Price and reward-point monitoring:** track price, list price, discount and Gold Point value changes on the electronics you sell or buy.
- **Catalogue and inventory research:** pull full specifications, images and per-variant pricing for competitive analysis or a product feed.
- **Review and reputation tracking:** collect customer reviews and rating breakdowns for products you manufacture or resell.
- **Availability and stock alerts:** watch store stock counts and availability wording for in-demand or hard-to-find electronics.
- **Category and brand audits:** walk a whole category branch or brand catalogue to check coverage, pricing consistency or new releases.

### Data You Get

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

| Field | Example |
| --- | --- |
| `sku` | `"100000001000045035"` (Yodobashi's own product id) |
| `url` | Yodobashi link to the product page |
| `title` / `brand` / `makerName` / `makerId` | `"Sample Digital Camera XR100"` / `"SampleBrand"` / `"Sample Maker Co."` / `"0000001851"` |
| `currency` | `"JPY"` (always) |
| `price` / `listPrice` | `98000` / `120000` |
| `discountAmount` / `discountPercent` / `discountNote` | `22000` / `18.3` / `"Limited-time price"` |
| `goldPoints` / `goldPointRatePercent` / `goldPointValue` | `980` / `10` / `980` |
| `availability` / `inStock` / `isDiscontinued` | `"In stock"` / `true` / `false` |
| `storeStockCount` / `storePickupMessage` | `3` / `"Available for in-store pickup"` |
| `deliveryMessage` / `deliveryDate` / `deliveryBadge` / `deliveryType` | rolling promised-delivery date and badge text (when available) |
| `thumbnail` / `images` / `mediaGallery` / `videos` | product photo, image list, feature gallery with captions, video links (when enabled) |
| `categoryBreadcrumb` / `categoryUrl` / `categoryCode` | `["Cameras", "Mirrorless Cameras"]` / category link / category code |
| `categoryRankings` | the store's own best-seller position (when enabled) |
| `releaseDate` | `"2026-03-15"` |
| `description` / `specifications` / `specificationsFlat` | full description, `{name, values[]}` spec table, and a flattened spec map (when enabled) |
| `variants[]` / `variantSkus` / `variantCount` | per-variant price, list price, Gold Points, availability, stock and image (when enabled) |
| `rating` / `reviewCount` / `familyReviewCount` / `unratedReviewCount` | `4.3` / `128` / `415` / `2` |
| `ratingBreakdown` | 5 / 4 / 3 / 2 / 1 star counts (when enabled) |
| `reviews[]` / `reviewsReturned` | up to 20 rows with author, rating, posted date, body, helpful votes and stated purchase reason (when enabled) |
| `questionCount` / `customerPhotoCount` | `4` / `9` |
| `sponsored` | whether this result also carried a promoted placement (the record itself is never an advert; see tips below) |
| `scrapedAt` | this run's timestamp |
| `changeType` / `changedFields` / `firstSeenAt` / `lastSeenAt` | `NEW`, `UPDATED`, `UNCHANGED`, `REAPPEARED` or `EXPIRED`, the fields that changed, and first/last-seen timestamps (incremental mode only) |

### How to Use

1. Pick a **mode**: `search` (keyword, with the store's own filters) or `url` (paste product, category, brand or search links).
2. For search mode, fill in your **keywords** and any filters (category, brand, price range, sort); for URL mode, paste the links.
3. Turn on **Fetch full product details** and/or **Fetch customer reviews** if you need them; each adds one enrichment charge per product.
4. Set **Maximum products** to control run size and cost, then click **Start**.

**URL mode: supported link types.** Paste any of these (one or many):

| Link type | Example |
|---|---|
| Keyword search | `https://www.yodobashi.com/?word=カメラ` |
| Keyword search, page 2 | `https://www.yodobashi.com/p2/?word=カメラ` |
| Search inside a category | `https://www.yodobashi.com/category/19055/?word=カメラ` |
| Filtered and sorted search | `...?word=カメラ&lower=10000&upper=50000&sorttyp=SELL_PRICE_ASC` |
| Search incl. discontinued | `...?word=カメラ&discontinued=true` |
| Brand filter on a search | `https://www.yodobashi.com/?mkrbrnds=0000001881&word=カメラ` |
| Category (deep path) | `https://www.yodobashi.com/category/19055/19063/206005/` |
| Category plus brand | `https://www.yodobashi.com/category/19055/m0000001851/` |
| Brand page | `https://www.yodobashi.com/maker/0000001851/` |
| Product page | `https://www.yodobashi.com/product/100000001000045035/` |
| Legacy product link | `https://www.yodobashi.com/ec/product/100000001000045035/` |
| Alternate product link | `https://www.yodobashi.com/product-detail/100000001000045035/` |
| Product link with `#review` | `https://www.yodobashi.com/product/100000001000045035/#review` |

The legacy product link, the alternate product link and the `#review` link resolve to the same product as the plain product link, so together they return that product once (duplicates are removed). The product `/product/<id>/review/` link and the `sp.` mobile host product link are read as the plain product page, so they return that product too. A category page-N link needs a search word to be served (`/category/19055/p2/?word=カメラ`); such a link starts at that page and is a partial scan, so it never produces `EXPIRED` rows. Links that cannot be served (a category page-N link without a search word, an `sp.` mobile listing link, a link on another domain, or an unrecognised shape) are skipped and never fetched: the run log carries an `UNSUPPORTED_URL` warning for each, naming the reason. Pagination is followed automatically from the first-page URL.

**URL-mode default changed:** the `urls` field now ships with one example of each link type above as its default. A URL-mode run started with the field untouched therefore scrapes those examples instead of returning nothing; clear the list or paste your own links to avoid that.

**Search by keyword:**

```json
{
  "mode": "search",
  "queries": ["デジタルカメラ"],
  "maxItems": 20
}
```

**Search with category, brand and price filters:**

```json
{
  "mode": "search",
  "queries": ["カメラ"],
  "categoryPath": "19055/19063/206005",
  "makerId": "0000001851",
  "minPrice": 10000,
  "maxPrice": 100000,
  "sortBy": "price_asc"
}
```

**Paste product, category or brand links, with enrichment:**

```json
{
  "mode": "url",
  "urls": [
    "https://www.yodobashi.com/product/100000001000045035/",
    "https://www.yodobashi.com/category/19055/19063/"
  ],
  "fetchDetails": true,
  "fetchReviews": true
}
```

**Recurring monitoring of one search, changes only:**

```json
{
  "mode": "search",
  "queries": ["ドライボックス"],
  "incrementalMode": true,
  "emitExpired": true,
  "maxItems": 100
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/yodobashi-com-scraper").call(run_input={"mode": "search", "queries": ["カメラ"], "maxItems": 20})
for product in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(product["title"], product["price"], product["currency"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/yodobashi-com-scraper').call({ mode: 'search', queries: ['カメラ'], maxItems: 20 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

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

#### Reviews: two honest limits

Yodobashi server-renders its 20 most recent reviews per product page, so `reviews[]` holds up to 20 rows, `reviewsReturned` says how many you actually got, and the product's real total is always reported separately in `reviewCount`. A colour or capacity variant shares one review wall on Yodobashi, so `reviewCount` stays scoped to the exact SKU you asked for while `familyReviewCount` and `ratingBreakdown` describe the whole variation family; every review row carries its own `productSku` so you can narrow it yourself. A product with no reviews returns `reviews: []`, `reviewsReturned: 0` and a null `ratingBreakdown`.

#### Cap and scope tips, including a known limit

Outside incremental mode, `maxItems` splits its budget evenly across every keyword and every category, brand or search link in the run (pasted product links draw from the same total first), and each of those walks stops once its own share is used. With the default of 50 and two keywords, each keyword gets 25, while one results page carries up to 48 products, so a walk is often cut partway through its first page. When you run **more than one keyword or link that can return the same product** (for example two overlapping keywords, or a keyword and a category that both cover it) and one of those walks is cut before its own natural end, that product can be **silently dropped from the whole run**, not just from the walk that was cut: this actor tracks "already returned this run" and "already looked at this run" in the same set, so a product that sat on the results page where its walk's share ran out, scanned but not pushed, is not reconsidered when a later keyword or link in the same run reaches it too, even if that later walk has room. Incremental mode does not have this problem, because it does not split or slice the budget within a page (see its own limit below). **Workaround:** when precision matters, either raise `maxItems` (or set it to `0` for unlimited) so no walk is cut before its natural end, or keep multiple keywords/URLs in one run disjoint (for example by scoping each to its own `categoryPath` or `makerId`) so they cannot share products. Running overlapping keywords as separate actor runs also avoids it.

#### Resume and recurring updates, including two known limits

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run or dataset ID and the products already collected there are skipped, so you don't pay twice. This genuinely prevents re-pushing and re-billing those products, not just their `EXPIRED` eligibility.
- **Incremental mode** (`incrementalMode`) is for running the same search again and again (for example daily). The actor remembers the previous run itself, keyed on the search and its filters, and marks each product `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED` or `EXPIRED` (only after a run that scanned the whole scope, and only with `emitExpired`). `stateKey` names or shares the stored state. With incremental mode off, output is exactly as before. `UPDATED` means any returned field changed, except the excluded ones listed here. Examples of what counts: price, list price, discount, availability, in-stock flag, store stock count, rating, review count and the rating breakdown, description, specifications, images (including their order), variants, new or edited review text, and the title and brand fields. Deliberately excluded, so they never mark a whole catalogue `UPDATED` on their own: the rolling delivery date, delivery type, delivery message and delivery badge (also inside each variant), the store's own daily category rankings, the sponsored flag, the scrape timestamp, each review's helpful, vote, like and comment counters, and the order in which a review lists its purchase reasons (the store returns them in a different order on every request). The excluded fields stay in every returned row. Changing the excluded set never causes a one-time wave of `UPDATED` rows, because stored products are compared again with the current rules. Pasting a results link that starts at page 2 or later covers only part of a search, so it never produces `EXPIRED` rows.
- **Price and availability monitoring** (incremental mode only). `changeScope` set to *Price and availability only* marks a product `UPDATED` only when its price, list price, discount, availability, in-stock flag or store stock count changed (also per variant), so image, description or rating changes never create a billable row. `compactUpdates` returns `UPDATED` and `EXPIRED` rows as slim rows (id, link, title, current price and availability, plus `priceChanges` and `variantChanges` with old and new values); `NEW` rows stay complete, and a compact row does not add a Detail enrichment charge because it carries no detail data. `expireAfterMissedScans` (default 1) tombstones a product only after it was missing from that many consecutive complete scans; `EXPIRED` means the product was no longer found in the listing, not that it is confirmed unavailable. Use the availability fields for stock. `ignoreFieldsForChanges` lists extra field names (or dotted paths such as `variants.image`) that must not make a product `UPDATED`. None of these starts a new state: stored products are compared again under the current settings, so switching `changeScope` or editing `ignoreFieldsForChanges` neither re-bills the catalogue nor resets the baseline. The automatic state key depends only on the search itself (mode, keywords or links, category, brand, price range, sort, discontinued, details and reviews switches); set `stateKey` to keep one state across changes to those too.
- **`maxItems` is not a hard per-page cap in incremental mode.** Within one page of results, every product that page returns (new, updated or reappeared, plus unchanged ones when `emitUnchanged` is on) is pushed before the run checks the remaining budget; the check only decides whether to fetch the *next* page or start the next keyword. On a search with many changes bunched into one page, a single page can push (and bill) more products than `maxItems` declares, overshooting by up to one page of results (Yodobashi shows up to 48 products per page); the run then stops fetching further pages. The even per-keyword split described above also does not apply here, so the first keyword can use the whole budget and later keywords may not run at all. **Workaround:** treat `maxItems` as an approximate stop point rather than a hard row-count guarantee when incremental mode is on, or scope large searches into smaller `categoryPath`/`makerId` slices so a single page's changes stay small.
- **`EXPIRED` rows are not bounded by `maxItems` at all.** They are only produced once a run has provably scanned its whole tracked scope (never when a cap stopped it early, never when Resume was used, never when part of the search could not be read), but once that condition holds, every product missing from this run's scan is tombstoned, however many that is. If a monitored search or `stateKey` has tracked far more products historically than a given run rescans, that run can return (and bill) many more rows than `maxItems` declares, entirely as `EXPIRED` tombstones on top of the normal results. **Workaround:** expect `EXPIRED` volume to scale with the size of what you are tracking, not with `maxItems`; keep each monitored `stateKey` scoped to a search you expect to stay a stable size, or leave `emitExpired` off if you only want to react to what is new or changed.

#### Output views

The dataset has four views: **Products** (the overview table), **Product details** (descriptions, specifications, variants), **Reviews** (one row per review, unwound from `reviews[]`) and **Changes** (change type and changed fields for incremental runs).

### 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 product pages 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, with the store's own filters) or `url` (paste Yodobashi links). |
| `queries` | array | (empty; the Console pre-fills `カメラ`) | Keywords to search for (Search mode only). Japanese and English both work. Each keyword runs its own search and the results are combined. |
| `categoryPath` | string | (empty) | Restrict the search to one category branch (Search mode only): an id path such as `19055/19063/206005`, a pasted category URL, or the category's exact name as shown on the site, such as `デジタルカメラ` (letter case and full-width or half-width forms do not matter; there is no fuzzy match). A name that matches nothing, or two different categories, stops the run with a `NAME_NOT_RESOLVED` message instead of returning an empty result. |
| `makerId` | string | (empty) | Restrict the search to one brand (Search mode only): the 10-digit maker id such as `0000001851`, a pasted brand URL, or the brand's exact name such as `パナソニック` or `ASUS` (letter case and full-width or half-width forms do not matter; there is no fuzzy match). A name that matches nothing stops the run with a `NAME_NOT_RESOLVED` message instead of returning an empty result. |
| `minPrice` | integer | (empty) | Lowest price to include, in yen (Search mode only). |
| `maxPrice` | integer | (empty) | Highest price to include, in yen (Search mode only). |
| `sortBy` | string | (store default) | `popularity`, `newest`, `price_asc`, `price_desc`, or `release_date_desc` (Search mode only). Leave empty to keep the store's own default ranking. |
| `includeDiscontinued` | boolean | `false` | Off by default, matching the store. Turn on to also return products it no longer sells. |
| `urls` | array | one example per link type | Yodobashi product, category, brand or search links (URL mode only). The filters above are ignored here because your URL already carries its own. |
| `maxItems` | integer | `50` | Cap on the number of products returned across all keywords and URLs combined. `0` = unlimited. |
| `maxPages` | integer | unlimited | Bound on the number of result pages read per keyword or URL. Yodobashi shows up to 48 products per page. `0` or empty = no page limit. |
| `fetchDetails` | boolean | `false` | Adds the full description, complete specification table, image gallery, list price and discount, category rankings, and per-variant price, points and stock. Each enriched product adds one enrichment charge. |
| `fetchReviews` | boolean | `false` | Also returns the product's customer reviews: star breakdown, and per-review author, rating, date, text, helpful votes and stated purchase reason. Counts towards the same enrichment charge. |
| `maxReviewsPerProduct` | integer | `20` | Cap on review rows attached to each product. 20 is the practical ceiling and `0` means no cap (still at most 20); the product's full review count is always reported separately. |
| `resumeFromRunId` | string | (none) | Continue one interrupted run: paste its run or dataset ID and the products already collected there are skipped. |
| `incrementalMode` | boolean | `false` | Return only new and changed products on recurring runs of the same search or URLs. |
| `stateKey` | string | (none) | Name or share an incremental-mode state. Leave empty to derive a key from the search and filters automatically. |
| `changeScope` | string | `all` | `priceAndStock` compares only price, discount and availability fields (incremental mode only). |
| `compactUpdates` | boolean | `false` | Return `UPDATED` and `EXPIRED` rows as slim rows with `priceChanges` and `variantChanges`. |
| `expireAfterMissedScans` | integer | `1` | Complete scans a product must be missing from before it is marked `EXPIRED`. |
| `ignoreFieldsForChanges` | array | (empty) | Ignore fields when detecting changes (incremental mode only). Field names or dotted paths. |
| `emitUnchanged` | boolean | `false` | Also return (and bill) products that have not changed since the last run. |
| `emitExpired` | boolean | `false` | Also return (and bill) products that were present in a previous run but are no longer found. |
| `proxy` | object | Apify Proxy | Connection settings. The default Apify Proxy works for this store; free plans include no Apify Proxy (see Plan Requirement). |
| `mcpConnectors` | array | (none) | Optional: send a summary of each product to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which product pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on products written to each connector per run. Does not affect the dataset. |

### Output Example

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

```json
{
  "sku": "100000001000045035",
  "url": "https://www.yodobashi.com/product/100000001000045035/",
  "title": "Sample Digital Camera XR100",
  "brand": "SampleBrand",
  "makerName": "Sample Maker Co.",
  "makerId": "0000001851",
  "currency": "JPY",
  "price": 98000,
  "listPrice": 120000,
  "discountAmount": 22000,
  "discountPercent": 18.3,
  "goldPoints": 980,
  "goldPointRatePercent": 10,
  "goldPointValue": 980,
  "availability": "In stock",
  "inStock": true,
  "isDiscontinued": false,
  "storeStockCount": 3,
  "deliveryMessage": "Arrives by a promised date",
  "categoryBreadcrumb": ["Cameras", "Mirrorless Cameras"],
  "releaseDate": "2026-03-15",
  "thumbnail": "https://example.com/sample-thumbnail.jpg",
  "rating": 4.3,
  "reviewCount": 128,
  "ratingBreakdown": { "5": 70, "4": 32, "3": 15, "2": 6, "1": 5 },
  "variantCount": 3,
  "scrapedAt": "2026-08-27T00:00:00+00:00"
}
```

### Plan Requirement

Datacenter proxies work for this store, so the default Apify Proxy setting needs no upgrade, and residential proxies are optional. The actor automatically falls back to a backup connection when one connection is refused. Apify free plans do not include any Apify Proxy access: on a free plan the actor continues on its backup connection with a plan notice in the log and some pages may still be unavailable, and if no page can be loaded at all the run stops with a clear message instead of returning an empty dataset. To get proxy access, upgrade your plan or supply your own proxy URLs in the proxy field.

### FAQ

#### How much does it cost?

Billing follows the **Pricing** tab, which shows the live rates. You are charged the actor-start event, the dataset-item event for each product returned, and the detail-enrichment event once per product when you switch on full details or reviews (one enrichment charge no matter how much extra data it carried). Unchanged products in incremental mode are not returned and not billed unless you turn on emitting them. Use **Maximum products** to cap the cost of any run.

#### Is it legal to scrape Yodobashi.com?

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

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

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. Each run then returns only new and updated products, and unchanged ones are not billed by default.

#### Why did a run push more products than the Maximum products I set?

Incremental mode does not apply Maximum products as a hard cap on a single page of results, and `EXPIRED` tombstones (when Emit expired products is on) are limited to the headroom Maximum products leaves after the run's other rows; any further `EXPIRED` products wait for a later run, once that run has provably scanned its whole scope. See the tips under **How to Use** for the exact trigger and a workaround.

#### Why might a product be missing from my results even though it is still on the store?

Outside incremental mode, if a single run uses more than one keyword or URL that can return the same product, and Maximum products cuts one of those searches before its own natural end, that product can be dropped from the whole run rather than being picked up by a later, uncut search. See **Cap and scope tips** under How to Use for a workaround.

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

If the store's answers could not be read at all, the run stops with a clear message so "no matches" is never confused with "nothing could be read". Run it again in a few minutes. If only some products or pages could not be read, you still get what was found.

#### 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 electronics data?

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

<table>
<tr><td>🔌 <a href="https://apify.com/abotapi/biccamera-com-scraper"><b>Bic Camera Scraper</b></a><br>Scrape Bic Camera (biccamera.com) products: JPY price, list price and discount, Bic Point...</td><td>🔌 <a href="https://apify.com/abotapi/dienmayxanh-scraper"><b>Dienmayxanh Scraper</b></a><br>Scrape dienmayxanh.com home appliances and electronics with full specifications, current...</td></tr>
<tr><td>🔌 <a href="https://apify.com/abotapi/pbtech-co-nz-scraper"><b>PB Tech Scraper</b></a><br>Scrape pbtech.co.nz products with full specifications, price, brand, condition, per-store...</td><td>🔌 <a href="https://apify.com/abotapi/appliancesonline-com-au-scraper"><b>Appliances Online Scraper</b></a><br>Scrape appliancesonline.com.au by category, keyword, or URL. Extract title, brand, AUD...</td></tr>
<tr><td>🔌 <a href="https://apify.com/abotapi/casasbahia-com-br-scraper"><b>Casas Bahia Brazil Electronics &amp; Home Goods Scraper</b></a><br>Scrape products from Casas Bahia Brazil by keyword, department, or URL. Filter by brand...</td><td>🏷️ <a href="https://apify.com/abotapi/tutti-ch-scraper"><b>Tutti.ch Scraper</b></a><br>Scrape listings from tutti.ch across all 23 categories, including vehicles, property...</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/yodobashi-com-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 products. 'search' runs keyword searches with the store's own filters; 'url' takes Yodobashi product, category, brand or search URLs exactly as you paste them.

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

Keywords to search for (Search mode only). Japanese and English both work. Each keyword runs its own paginated search and the results are combined. Leave empty if you only want to browse a category or a brand.

## `categoryPath` (type: `string`):

Restrict the search to one category branch (Search mode only). Paste a Yodobashi category URL, its id path (for example 19055/19063/206005 from https://www.yodobashi.com/category/19055/19063/206005/), or the category's exact name as shown on the site, such as デジタルカメラ (letter case and full-width or half-width forms do not matter; no fuzzy match). A name that matches nothing, or two different categories, stops the run with a clear NAME_NOT_RESOLVED message. Leave empty to search the whole store.

## `makerId` (type: `string`):

Restrict the search to one brand (Search mode only). Enter the 10-digit maker id from a Yodobashi brand link (for example 0000001851 from https://www.yodobashi.com/maker/0000001851/), or the brand's exact name as shown on the site, such as パナソニック or ASUS (letter case and full-width or half-width forms do not matter; no fuzzy match). A name that matches nothing stops the run with a clear NAME_NOT_RESOLVED message. Leave empty for all brands.

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

Lowest price to include, in Japanese yen (Search mode only). Leave empty for no minimum.

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

Highest price to include, in Japanese yen (Search mode only). Leave empty for no maximum.

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

Result ordering as offered by the store (Search mode only). Leave on the store default to keep Yodobashi's own popularity ranking.

## `includeDiscontinued` (type: `boolean`):

Off by default, matching the store's own default of hiding products it no longer sells. Turn on to also return discontinued items, which widens the result set considerably.

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

Paste Yodobashi URLs (URL mode only). A product page (/product/<id>/) returns that one product; a category, brand or keyword-search URL returns the products it lists, up to your limits below. The filters above are ignored here because your URL already carries its own. If you leave this field out of the input in URL mode (for example in an API call that omits it), the built-in example of each supported link type runs; an empty list runs nothing. The shipped default list holds one example of each distinct link type, so each example returns its own products (the /p2/ example starts from page 2 of the same keyword search as the page 1 example). The suggestion list also offers the legacy /ec/product/<id>/ form and the /product-detail/<id>/ form, which point at the same product as /product/<id>/ and return it once, and a category page-N link with a search word. Product links in the /review/ and sp. mobile forms are read as the plain product page. Links that cannot be served (a category page-N link without a search word, an sp. listing link, another domain, an unrecognised shape) are skipped and reported with an UNSUPPORTED_URL warning in the run log.

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

Cap on the number of products returned across all keywords and URLs combined. Set 0 for unlimited, bounded only by Max pages and by how many products the store actually has.

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

Optional bound on the number of result pages read per keyword or URL. Yodobashi shows up to 48 products per page. Leave empty or 0 for no page limit.

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

Adds the full description, the complete specification table, the whole image gallery with captions, list price and discount, category rankings, and per-variant price, points and stock. Slower, and each enriched product adds one enrichment charge.

## `fetchReviews` (type: `boolean`):

Also returns the product's customer reviews: star rating breakdown, and per-review author, star rating, posted date, review text, helpful votes and stated purchase reason. A product with no reviews returns an empty list. Counts towards the same per-product enrichment charge.

## `maxReviewsPerProduct` (type: `integer`):

Cap on review rows attached to each product. Yodobashi server-renders its 20 most recent reviews per product page, so 20 is the practical ceiling and 0 means no cap (still at most 20); the product's full review count is always reported separately.

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

Leave the default Apify Proxy setting on: datacenter proxies work for this store, residential is optional, and a country pin is not required. Apify free plans include no Apify Proxy: the run then continues on a backup connection with a notice in the log, or stops with a clear message if no page loads. To get proxy access, upgrade your plan or supply your own proxy URLs here.

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

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

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

Turn this on for recurring monitoring of the same search or URLs. The first run returns everything as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED products. UPDATED means any returned field changed except the excluded ones: for example price, list price, discount, availability, stock count, rating, review count, description, specifications, images, variants, new or edited review text and the title and brand fields. Excluded (still returned in the row, never a reason to mark UPDATED): delivery date, type, message and badge (also inside variants), category rankings, the sponsored flag, the scrape timestamp, each review's helpful, vote, like and comment counters, and the order of a review's purchase reasons. State is kept separately per search (keywords or links, category, brand, price range, sort, discontinued, details and reviews switches); changing Change scope or Ignore fields keeps it. 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 from the search and filter settings, so different searches never mix state with each other.

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

Off by default. Turn on to also return products 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 want the full snapshot every run.

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

Off by default. Turn on to also return products 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, so never when Max products or Max pages capped it, when Resume was used, or when a page could not be read. This returns, and bills, extra synthetic rows.

## `changeScope` (type: `string`):

All fields (default) marks a product UPDATED when any compared field changes. Price and availability only compares just the price, list price, discount, availability, in-stock flag and store stock count (also per variant) so image, description and rating changes never create a billable row.

## `compactUpdates` (type: `boolean`):

Off by default. Turn on to return UPDATED and EXPIRED rows as slim rows: product id, URL, title, current price and availability, plus priceChanges and variantChanges with the old and new values. NEW rows stay complete. A compact row carries no detail-only data, so it does not add a Detail enrichment charge.

## `expireAfterMissedScans` (type: `integer`):

With Emit expired products on, a product is marked EXPIRED only after it was missing from this many consecutive complete scans (default 1). EXPIRED means it was no longer found in the listing; without opening each product page a listing drop and a delisting look the same, so check the availability fields for stock.

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

Field names that must not make a product UPDATED, for example goldPoints or reviewCount. A dotted path such as variants.image ignores that key inside every variant while the rest of each variant is still compared. The fields stay in the returned row. Changing this list keeps your saved state: stored products are compared again under the current list, so it never causes a wave of UPDATED rows.

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

Optionally send the scraped results into 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 product, 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 product pages are created. Required to enable the Notion export; ignored by other connectors.

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

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

## Actor input object example

```json
{
  "mode": "search",
  "queries": [
    "カメラ"
  ],
  "sortBy": "",
  "includeDiscontinued": false,
  "urls": [
    "https://www.yodobashi.com/?word=%E3%82%AB%E3%83%A1%E3%83%A9",
    "https://www.yodobashi.com/product/100000001000045035/",
    "https://www.yodobashi.com/category/19055/19063/206005/",
    "https://www.yodobashi.com/p2/?word=%E3%82%AB%E3%83%A1%E3%83%A9",
    "https://www.yodobashi.com/category/19055/?word=%E3%82%AB%E3%83%A1%E3%83%A9",
    "https://www.yodobashi.com/?word=%E3%82%AB%E3%83%A1%E3%83%A9&lower=10000&upper=50000&sorttyp=SELL_PRICE_ASC",
    "https://www.yodobashi.com/maker/0000001851/",
    "https://www.yodobashi.com/?mkrbrnds=0000001881&word=%E3%82%AB%E3%83%A1%E3%83%A9",
    "https://www.yodobashi.com/category/19055/m0000001851/",
    "https://www.yodobashi.com/?word=%E3%82%AB%E3%83%A1%E3%83%A9&discontinued=true",
    "https://www.yodobashi.com/ec/product/100000001000045035/",
    "https://www.yodobashi.com/product-detail/100000001000045035/",
    "https://www.yodobashi.com/category/19055/p2/?word=%E3%82%AB%E3%83%A1%E3%83%A9"
  ],
  "maxItems": 50,
  "maxPages": 0,
  "fetchDetails": false,
  "fetchReviews": false,
  "maxReviewsPerProduct": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "changeScope": "all",
  "compactUpdates": false,
  "expireAfterMissedScans": 1,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

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

No description

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

No description

## `reviews` (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": [
        "カメラ"
    ],
    "urls": [
        "https://www.yodobashi.com/?word=%E3%82%AB%E3%83%A1%E3%83%A9",
        "https://www.yodobashi.com/product/100000001000045035/",
        "https://www.yodobashi.com/category/19055/19063/206005/",
        "https://www.yodobashi.com/p2/?word=%E3%82%AB%E3%83%A1%E3%83%A9",
        "https://www.yodobashi.com/category/19055/?word=%E3%82%AB%E3%83%A1%E3%83%A9",
        "https://www.yodobashi.com/?word=%E3%82%AB%E3%83%A1%E3%83%A9&lower=10000&upper=50000&sorttyp=SELL_PRICE_ASC",
        "https://www.yodobashi.com/maker/0000001851/",
        "https://www.yodobashi.com/?mkrbrnds=0000001881&word=%E3%82%AB%E3%83%A1%E3%83%A9",
        "https://www.yodobashi.com/category/19055/m0000001851/",
        "https://www.yodobashi.com/?word=%E3%82%AB%E3%83%A1%E3%83%A9&discontinued=true",
        "https://www.yodobashi.com/ec/product/100000001000045035/",
        "https://www.yodobashi.com/product-detail/100000001000045035/",
        "https://www.yodobashi.com/category/19055/p2/?word=%E3%82%AB%E3%83%A1%E3%83%A9"
    ],
    "maxItems": 50,
    "maxPages": 0,
    "proxy": {
        "useApifyProxy": true
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "compactUpdates": false,
    "ignoreFieldsForChanges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/yodobashi-com-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": ["カメラ"],
    "urls": [
        "https://www.yodobashi.com/?word=%E3%82%AB%E3%83%A1%E3%83%A9",
        "https://www.yodobashi.com/product/100000001000045035/",
        "https://www.yodobashi.com/category/19055/19063/206005/",
        "https://www.yodobashi.com/p2/?word=%E3%82%AB%E3%83%A1%E3%83%A9",
        "https://www.yodobashi.com/category/19055/?word=%E3%82%AB%E3%83%A1%E3%83%A9",
        "https://www.yodobashi.com/?word=%E3%82%AB%E3%83%A1%E3%83%A9&lower=10000&upper=50000&sorttyp=SELL_PRICE_ASC",
        "https://www.yodobashi.com/maker/0000001851/",
        "https://www.yodobashi.com/?mkrbrnds=0000001881&word=%E3%82%AB%E3%83%A1%E3%83%A9",
        "https://www.yodobashi.com/category/19055/m0000001851/",
        "https://www.yodobashi.com/?word=%E3%82%AB%E3%83%A1%E3%83%A9&discontinued=true",
        "https://www.yodobashi.com/ec/product/100000001000045035/",
        "https://www.yodobashi.com/product-detail/100000001000045035/",
        "https://www.yodobashi.com/category/19055/p2/?word=%E3%82%AB%E3%83%A1%E3%83%A9",
    ],
    "maxItems": 50,
    "maxPages": 0,
    "proxy": { "useApifyProxy": True },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "compactUpdates": False,
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/yodobashi-com-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": [
    "カメラ"
  ],
  "urls": [
    "https://www.yodobashi.com/?word=%E3%82%AB%E3%83%A1%E3%83%A9",
    "https://www.yodobashi.com/product/100000001000045035/",
    "https://www.yodobashi.com/category/19055/19063/206005/",
    "https://www.yodobashi.com/p2/?word=%E3%82%AB%E3%83%A1%E3%83%A9",
    "https://www.yodobashi.com/category/19055/?word=%E3%82%AB%E3%83%A1%E3%83%A9",
    "https://www.yodobashi.com/?word=%E3%82%AB%E3%83%A1%E3%83%A9&lower=10000&upper=50000&sorttyp=SELL_PRICE_ASC",
    "https://www.yodobashi.com/maker/0000001851/",
    "https://www.yodobashi.com/?mkrbrnds=0000001881&word=%E3%82%AB%E3%83%A1%E3%83%A9",
    "https://www.yodobashi.com/category/19055/m0000001851/",
    "https://www.yodobashi.com/?word=%E3%82%AB%E3%83%A1%E3%83%A9&discontinued=true",
    "https://www.yodobashi.com/ec/product/100000001000045035/",
    "https://www.yodobashi.com/product-detail/100000001000045035/",
    "https://www.yodobashi.com/category/19055/p2/?word=%E3%82%AB%E3%83%A1%E3%83%A9"
  ],
  "maxItems": 50,
  "maxPages": 0,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "compactUpdates": false,
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/yodobashi-com-scraper --silent --output-dataset

```

## MCP server setup

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