# Suruga-ya Items Scraper (restock & price watch) (`superslowsloth/surugaya-items`) Actor

Search Suruga-ya (駿河屋), Japan's biggest used games, anime and collectibles shop, and get one flat row per product: own new and used prices, time-sale prices, sold-out flag, cheapest marketplace offer, list price, maker, release date and image.

- **URL**: https://apify.com/superslowsloth/surugaya-items.md
- **Developed by:** [Superslow Sloth](https://apify.com/superslowsloth) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 item scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/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

## Suruga-ya Items Scraper (restock & price watch)

Search [Suruga-ya](https://www.suruga-ya.jp) (駿河屋) - Japan's largest shop for
used games, anime goods, figures, trading cards, books and CDs - and get one
flat row per product: Suruga-ya's own new and used prices, time-sale prices,
whether it is sold out, the cheapest marketplace offer from other shops, list
price, maker, release date and image. No nested objects, no HTML to strip.

Built for a restock or price watch: run the same keywords on a schedule and
diff `sold_out` and `price_yen` between runs.

### Input

| field | meaning |
|---|---|
| `keywords` | One or more searches, exactly as typed into Suruga-ya's search box. Each becomes `https://www.suruga-ya.jp/search?category=&search_word=<keyword>` |
| `searchUrls` | Optional. Suruga-ya search URLs copied from your browser, for a category, sort order or view a keyword alone cannot express. Anything that is not a `suruga-ya.jp/search` URL is skipped and logged |
| `inStockOnly` | Hide sold-out products, using the parameters of the page's own 品切れ ON/OFF toggle (`ck=true&inStock=On`). Off by default - a restock watch needs the sold-out rows |
| `maxItems` | Stop after this many products in total, shared by every keyword and URL, in order. Suruga-ya shows 24 per page |
| `proxyConfiguration` | Residential, pinned to Japan, by default - see **Proxy** below |

Paging follows the results page's own "次のページ" (next page) link until there
is none, `maxItems` is reached, or a page brings nothing new. Any query
parameter of your URL that the next-page link leaves out (an `inStock` or
`rankBy` filter, say) is carried over, so a filter cannot quietly fall off on
page 2.

### Output

One Suruga-ya search card can show several prices at once, so each is its own column.

| field | meaning |
|---|---|
| `product_id` | Suruga-ya's product number (`/product/detail/<id>`). Usually digits, occasionally letters (`ZSARO37368`), so always a string |
| `title` | Product name |
| `url` | The card's own link. Usually `/product/detail/<id>`; a product whose only stock is with one marketplace shop links to that shop's offer (`?tenpo_cd=...`), and some sold-out products link to the `/product/other/<id>` offers page |
| `category` | Suruga-ya's product type, e.g. フィギュア, ニンテンドースイッチ2ソフト |
| `badge` | The ribbon over the card: 新入荷 (new arrival), 値下げ (price cut), 人気上昇中 (trending) |
| `conditions` | The conditions Suruga-ya itself sells it in right now: `新品` (new), `中古` (used), both, or empty when sold out |
| `price_yen` | Lowest of Suruga-ya's own prices on the card, after any time sale |
| `price_new_yen`, `price_new_max_yen` | Own new price; `_max` is the top of a printed range |
| `price_used_yen`, `price_used_max_yen` | Own used price; a range ("￥1,120 ～ ￥1,400") means several used copies of different grades are in stock |
| `regular_price_new_yen`, `regular_price_used_yen` | The struck-through regular price while a タイムセール (time sale) runs |
| `time_sale_ends_at` | When that time sale ends, ISO 8601 in Japan time |
| `list_price_yen` | Manufacturer's list price (定価) |
| `sold_out` | `true` when the card says 品切れ (sold out at Suruga-ya itself), `false` when it shows an own price |
| `marketplace_price_yen`, `marketplace_offer_count` | Cheapest offer from Suruga-ya's marketplace (マケプレ) shops, and how many such offers there are |
| `maker` | Maker, publisher or label |
| `release_date` | Release date (発売日), ISO 8601 |
| `image_url` | Product photo |
| `query` | The keyword or search URL this row came from |

A sold-out product is still a row - with `sold_out: true`, no own prices, and
usually a marketplace price. That is what makes a restock watch possible.

#### `null` is not zero

Every column except `product_id`, `title`, `url`, `conditions` and `query` can
be `null`, and is `null` whenever the card simply does not print that value -
never `0` or an empty string, because a `0` would read as a measurement. On the
96 cards the parser was built against (four real search pages, 2026-10-01 and
2026-10-04):

- own prices are null on sold-out (品切れ) cards - 16 of 96;
- `price_*_max_yen` is null unless the card prints a range;
- `regular_price_*_yen` and `time_sale_ends_at` are null unless a time sale is on;
- `marketplace_*` is null when no marketplace shop has an offer - 31 of 96;
- `list_price_yen`, `maker`, `release_date` and `badge` are blank on some cards
  (e.g. promotional goods with no list price or release date).

`sold_out` is `null` only if a card shows neither 品切れ nor an own price, which
did not happen on any card measured.

### Proxy

**Residential pinned to Japan is the default, and the only setting that
works.** Suruga-ya is behind Cloudflare. Measured on three days in a row to
2026-10-04: Apify datacenter exits got Cloudflare's "Just a moment..."
challenge with HTTP 403, and so did *unpinned* residential exits; only
`RESIDENTIAL` with `apifyProxyCountry: "JP"` returned the real results page.

When a challenge does come back - as a 403, or as a 200 carrying the challenge
or no product cards - the actor switches to a new exit address and retries.
A page that is still refused after the retries is logged as a failure and
nothing is charged for it.

### Billing

Pay per event: **$0.0007 per product row**, plus a small fixed **actor-start**
fee per run (see the pricing tab). Platform usage - compute and the
residential proxy - is included. A product id is charged at most once per run,
even when two of your searches both return it. A run that fails on its own
input is not charged at all.

### Limits

- What a genuinely empty search looks like on Suruga-ya has not been captured
  yet; such a search is treated like a refusal - retried, then logged as a
  failure - and costs nothing.
- `inStockOnly` sends the parameters the site's own toggle link uses; its
  effect was not observed in a saved response.

# Actor input Schema

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

One or more searches to run, each exactly as you would type it into Suruga-ya's search box, e.g. "ポケモン" or "nintendo switch". Each becomes https://www.suruga-ya.jp/search?category=\&search_word=<keyword>. Every keyword and search URL shares the maxItems budget below, in order - keywords first. Duplicate spellings that differ only in case are collapsed before anything is fetched.

## `searchUrls` (type: `array`):

Optional. Suruga-ya search result URLs copied from your browser (https://www.suruga-ya.jp/search?...), for a search a keyword alone cannot express - a category, a sort order, the marketplace-first view. Anything that is not a suruga-ya.jp /search URL is skipped and reported in the run log.

## `inStockOnly` (type: `boolean`):

Ask Suruga-ya to hide sold-out (品切れ) products, using the parameters of the site's own 品切れ ON/OFF toggle (ck=true\&inStock=On). Leave it off for a restock watch: sold-out rows are what tell you something came back.

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

Stop after this many products in total, shared across every keyword and search URL. Suruga-ya serves 24 products per page, so up to 24 per search costs a single page request and each further 24 is one more.

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

Residential pinned to Japan is the default, and the only setting that works. Suruga-ya sits behind Cloudflare: on three days in a row (to 2026-10-04) datacenter exits AND unpinned residential exits got its 'Just a moment...' challenge (HTTP 403); only RESIDENTIAL with country JP returned results. Changing this will most likely produce a run with no rows.

## Actor input object example

```json
{
  "keywords": [
    "ポケモン"
  ],
  "inStockOnly": false,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "JP"
  }
}
```

# Actor output Schema

## `items` (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 = {
    "keywords": [
        "ポケモン"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "JP"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("superslowsloth/surugaya-items").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": ["ポケモン"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "JP",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("superslowsloth/surugaya-items").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": [
    "ポケモン"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "JP"
  }
}' |
apify call superslowsloth/surugaya-items --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,superslowsloth/surugaya-items"
        }
    }
}
```

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/xukYDGLkz5efZwfrf/builds/M0CUQuz1yHQLUhTtX/openapi.json
