# Nintendo eShop Price & Sale Scraper (US, Canada, Japan) (`superslowsloth/nintendo-eshop-prices`) Actor

Nintendo eShop scraper for sale and price-drop alerts: Switch and Switch 2 games, DLC and bundles from the US, Canada and Japan stores, one row per item with price now, regular price, sale price, percent off, sale end date, platform, publisher and store link.

- **URL**: https://apify.com/superslowsloth/nintendo-eshop-prices.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 $1.04 / 1,000 game 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

## Nintendo eShop Price & Sale Scraper (US, Canada, Japan)

Get the **Nintendo eShop sale list** for the United States, Canada and Japan as
one flat table: every Switch and Switch 2 game, DLC and bundle that is on sale
right now, with the **price now, regular price, sale price, percent off and the
date the sale ends**, plus platform, publisher, release date and the store link.
Run it on a schedule and diff the dataset for **eShop sale and price-drop
alerts**: which games just went on sale, how deep the cut is, and how the same
sale compares across USD, CAD and JPY.

No account, no API key, no login, no browser. It reads the same search services
nintendo.com and nintendo.com/jp query from your browser.

### Input

| Field | Notes |
|---|---|
| `regions` | `US`, `CA`, `JP`, any mix. All three by default. Each region is read on its own. |
| `onSaleOnly` | `true` by default: only items the store has reduced right now (the US/Canada Deals list, Japan's sale flag). Set `false` for the full price list. |
| `searchQuery` | Optional title or word (`zelda`, `mario kart`, `ゼルダ`). Japan matches romaji and Japanese alike. Empty = the whole list. |
| `maxItems` | Items to return **per region** (default 100, up to 50,000). |
| `proxyConfiguration` | Apify datacenter proxy by default. |

Example input:

```json
{
  "regions": ["US", "CA", "JP"],
  "onSaleOnly": true,
  "maxItems": 5000
}
```

That returns every item on sale in all three regions: on 2026-10-18 it returned
12,304 rows (US 4,118, Canada 4,088, Japan 4,098) in about 35 seconds.

### Output

One row per item and region. Prices are numbers in the region's currency:
dollars and cents for `USD`/`CAD`, whole yen for `JPY`.

| Field | Notes |
|---|---|
| `region`, `currency` | `US`/`USD`, `CA`/`CAD`, `JP`/`JPY`. |
| `query`, `position` | Your search query (null without one) and the item's place in the order it was read for that region (1 is first). |
| `nsuid`, `sku` | Nintendo's eShop id for the item in that region, and the US/Canada SKU (null for Japan, which sends none). The same game has a different nsuid in each region. |
| `title`, `url`, `image_url` | As the store shows them. `url` is the www.nintendo.com product page for US/Canada and the store-jp.nintendo.com page for Japan, built from the nsuid the way nintendo.com/jp builds it. |
| `platform` | `Nintendo Switch` or `Nintendo Switch 2` (the US/Canada list has a handful of `iOS/Android` items too). |
| `product_type` | `game`, `dlc` (an add-on) or `bundle`. |
| `publisher`, `developer` | As sent. `developer` exists only in the US/Canada data and is often empty there. |
| `release_date` | `YYYY-MM-DD` as the store sends it. A far-future date such as `2027-12-31` is the store's own placeholder for "not announced". |
| `genres` | Genre labels as printed (Japanese for Japan). Empty list when none. |
| `price` | The price **now**, sale or not. `0.0` for a free item. Null for an item with no price yet. |
| `regular_price` | The undiscounted price. |
| `on_sale`, `sale_price`, `amount_off`, `percent_off` | Whether the item is reduced, its sale price, how much comes off and the store's percent (two decimals: `34.02`; Japan's unrounded `19.999999999999996` becomes `20.0`). All null when not on sale, never 0. |
| `sale_start`, `sale_end` | The sale window, ISO 8601 with offset: UTC for US/Canada (`2026-10-29T23:59:59Z`), Japan time for Japan (`2026-12-02T23:59:59+09:00`). Null when not on sale. |
| `preorder` | True for an item that can be pre-ordered and is not out yet. |

Example row (real values, 2026-10-18):

```json
{
  "region": "CA",
  "currency": "CAD",
  "query": null,
  "position": 1,
  "nsuid": "70010000009921",
  "sku": "7100009921",
  "title": "Undertale",
  "url": "https://www.nintendo.com/en-ca/store/products/undertale-switch/",
  "image_url": "https://assets.nintendo.com/image/fetch/q_auto/f_auto/https://atum-img-lp1.cdn.nintendo.net/i/c/0ef5d86e09a843aeb8ef19f1b3d11051_1024",
  "platform": "Nintendo Switch",
  "product_type": "game",
  "publisher": "8-4",
  "developer": "8-4, Ltd.",
  "release_date": "2018-09-18",
  "genres": ["Role playing"],
  "price": 12.53,
  "regular_price": 18.99,
  "on_sale": true,
  "sale_price": 12.53,
  "amount_off": 6.46,
  "percent_off": 34.02,
  "sale_start": "2026-10-10T16:00:00Z",
  "sale_end": "2026-11-01T15:59:59Z",
  "preorder": false
}
```

#### Honest nulls

A field a region does not send is `null`, never `0` or `""`: Japan has no SKU
and no developer; an item that is not on sale has null sale price, percent off
and sale window; a coming-soon item has a null price. `0.0` in `price` means
free, because the store says so.

### Pricing

Pay per event:

- **$0.002** per run (`actor-start`), charged only after your input is
  validated, so a run that fails on bad input costs nothing.
- **$0.00104** per item row written (`game-scraped`), i.e. $1.04 per 1,000
  rows. A row that is not written is not charged.

A full daily sale list of all three regions (about 12,300 rows) costs about $12.80.

### How it fetches, and its limits

US and Canada come from the Algolia index behind the nintendo.com store search,
using the public search-only key nintendo.com ships to every visitor. Japan
comes from search.nintendo.jp, the search behind nintendo.com/jp/software. A
refusal (403, 429, 5xx), a 200 that is not the service's answer, or a dropped
connection is treated as the address being blocked: the actor rotates to a fresh
one and retries.

Things worth knowing, all measured on 2026-10-18:

- **Up to 1,000 items per region come in the store's own order** (most popular
  first in the US and Canada). The US/Canada index serves at most 1,000 hits per
  query, so a larger `maxItems` reads the list in price slices of at most 1,000
  each, **cheapest first**, until every item is read. A slice of one single
  price that still holds more than 1,000 items is split by platform, age rating,
  DLC flags and publisher; the run log reports any items that could still not be reached.
- **Items with no price are not part of a sweep.** About 1,055 US items have no
  price yet (coming-soon games, add-ons not sold on their own). A price slice can
  never select them, so a full-list sweep with `onSaleOnly` off leaves them out
  and says how many in the log. A search that matches 1,000 items or fewer
  returns them. None of them is ever on sale.
- **Japan covers Switch and Switch 2 only**, like the US and Canada lists. Its
  search also lists 3DS, Wii U and amiibo items; those are left out. Japanese
  entries without an eShop id (accessories, Nintendo Switch Online classics,
  retired listings) are skipped and counted.
- **The Japanese store page can show a waiting room.** store-jp.nintendo.com
  sometimes queues visitors when it is busy; the link is still the item's page.
- **A few US/Canada deals carry no sale window.** The store marks them reduced
  but sends no start or end date (7 of 2,780 US deals under $5 on 2026-10-18);
  their `sale_start` and `sale_end` are null.
- **Japan lists a few items twice** (a Switch 2 game card next to its download,
  same nsuid and price: 3 of 4,101 sale entries). Each is returned once.
- **"On sale" is the store's own rule.** In the US and Canada it is the Deals
  list; in Japan the sale flag, and only when the price now differs from the
  regular price, which is how nintendo.com/jp decides it.
- **The key is public but can rotate.** If nintendo.com changes it, the US and
  Canada stop answering with HTTP 403 "Invalid Application-ID or API key"; the
  run says so plainly in its log and status, does not retry it, and still reads
  Japan.

### Use it from the API

```bash
curl -X POST "https://api.apify.com/v2/acts/<your-username>~nintendo-eshop-prices/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"regions": ["US", "JP"], "searchQuery": "zelda", "onSaleOnly": false, "maxItems": 50}'
```

# Actor input Schema

## `regions` (type: `array`):

Which Nintendo eShop stores to read: US (USD), Canada (CAD) and Japan (JPY). All three by default, so one run gives the same sale seen in every region. Each region is read on its own and gets its own maxItems.

## `onSaleOnly` (type: `boolean`):

Return only items the store has reduced right now (the store's own Deals list in the US and Canada, its sale flag in Japan). Turn it off to read the full price list, sale or not.

## `searchQuery` (type: `string`):

Optional. A title or word to search for, as you would type it into the eShop search (for example zelda, mario kart or ゼルダ). The Japanese store matches romaji and Japanese alike. Leave empty for the whole list.

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

Return at most this many items from each region. Up to 1,000 per region come in the store's own order (most popular first in the US and Canada); a larger number reads the whole list, cheapest first in the US and Canada. About 4,100 items are on sale in each region on a normal day.

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

Use Apify's automatic datacenter proxy (the default). Both Nintendo search services answered every request from datacenter and residential addresses alike; a refused request is retried from a fresh address when a proxy is on.

## Actor input object example

```json
{
  "regions": [
    "US",
    "CA",
    "JP"
  ],
  "onSaleOnly": true,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "regions": [
        "US",
        "CA",
        "JP"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("superslowsloth/nintendo-eshop-prices").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 = {
    "regions": [
        "US",
        "CA",
        "JP",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("superslowsloth/nintendo-eshop-prices").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 '{
  "regions": [
    "US",
    "CA",
    "JP"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call superslowsloth/nintendo-eshop-prices --silent --output-dataset

```

## MCP server setup

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

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/mam1Ee3oqO4ju6tUZ/builds/h4vxiQfyZ78szeOR0/openapi.json
