# Tabelog Restaurant List Scraper (`superslowsloth/tabelog-restaurants`) Actor

Scrape a Tabelog area restaurant list - new openings, ranking or most-reviewed - and get one flat row per restaurant: id, name, rating, review and save counts, genres, nearest station and distance, dinner/lunch budget bands, holiday, opening date and thumbnail.

- **URL**: https://apify.com/superslowsloth/tabelog-restaurants.md
- **Developed by:** [Superslow Sloth](https://apify.com/superslowsloth) (community)
- **Categories:** Travel, 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 restaurant 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

## Tabelog Restaurant List Scraper

Scrape a [Tabelog](https://tabelog.com) area restaurant list - Japan's dominant
restaurant review site - and get one flat row per restaurant. Built for a
new-openings / rating feed per area: point it at any area, pick a sort, and it
walks every page Tabelog will hand out.

### Input

Give it one or more Tabelog area URLs - a plain area page
(`https://tabelog.com/tokyo/A1301/`), a prefecture page, or an already-built
list URL in any sort or page. Every URL is normalised to that area's `rstLst`
listing and walked from page 1; the **Sort order** input controls the sort,
not whatever the pasted URL happened to be on.

| Sort order | Tabelog's own label | What it changes |
|---|---|---|
| `new_openings` (default) | ニューオープン | The only sort with an opening date on the card, and the one where `rating` is almost always null - a restaurant that just opened has no reviews to average yet. |
| `rating` | ランキング | Sorted by score; `rating` is populated. |
| `review_count` | 口コミが多い順 | Sorted by review count. |

### What one row contains

| Field | Notes |
|---|---|
| `restaurant_id`, `url` | Tabelog's own numeric id and its detail page. |
| `name` | The restaurant name, as printed. |
| `rating` | 1.0-5.0. Null, never `0.0`, until Tabelog has scored the restaurant - which needs a handful of reviews, so the freshest rows on the new-openings sort are reliably null while an older row in that same feed can already carry one (measured: page 1 of a new-openings feed was 0/20 rated, page 2 was 7/20). |
| `review_count`, `save_count` | 口コミ人数 (review count) and 保存人数 (bookmark count). `review_count` is null when the card prints "-" (zero reviews), not a hidden number. |
| `genres` | Every genre tag on the card, in Tabelog's own order - the first is its primary genre. |
| `station`, `station_distance_m`, `area_station_text` | Nearest station and distance in metres, plus the raw text ("新橋駅 348m"). A restaurant with no nearby station is tagged by its ward instead ("中央区") and carries no distance. |
| `dinner_budget`, `dinner_budget_min_yen`, `dinner_budget_max_yen` | The dinner budget band, Tabelog's own text and both ends parsed to yen. One end is null on an open-ended band ("～￥999" has no minimum; "￥100,000～" has no maximum) - that is Tabelog's own text, not a parsing gap. |
| `lunch_budget`, `lunch_budget_min_yen`, `lunch_budget_max_yen` | Same shape, for lunch. |
| `holiday_text` | 定休日. Null when Tabelog has nothing to report - whether the card omits the line outright or prints "-" for it, both mean the same thing. |
| `open_date`, `open_date_text` | The new-openings sort's own opening date, as ISO (`2026-10-23`) and as Tabelog printed it (`2026年10月23日オープン`). Both null on every other sort, which does not print one at all. |
| `thumbnail_url` | The card's photo. Null when the card carries no photo markup at all; set to Tabelog's own shared "no photo" image when that is genuinely what the card shows. |
| `list_url` | The exact `rstLst` URL this row was read from - which area, sort and page - so a dataset built from several areas or sorts splits back apart. |

### Paging

Tabelog serves exactly 20 restaurants per page. This actor stops an area
either when a page returns fewer than 20 (the last page) or when Tabelog
answers with its own "no matching restaurants" page - which it also uses,
confusingly, once a legitimate area or genre filter runs out of rows before
page 60. Tabelog refuses to serve page 61 or beyond for any single area
(measured: HTTP 400, "60ページ以降は表示できません") regardless of how many
restaurants it claims to have, so no area here is ever walked past 1,200 rows.
**Max restaurants** is a budget across every area URL supplied, not per area.

### Proxy

**Residential, pinned to Japan, is required.** Measured 2026-09-28 (pick-phase
probe, five areas - Ginza, Shibuya, Osaka, Kyoto, and the new-openings sort
itself): a datacenter address and an unpinned residential address were both
answered with Cloudflare's "Just a moment" challenge on every attempt; pinning
`apifyProxyGroups: ["RESIDENTIAL"]` and `apifyProxyCountry: "JP"` cleared it
6/6. That pin is the default here.

A 30-minute durability re-check was scheduled for the same measurement (the
lesson from a different actor in this family: Yelp's DataDome served three
clean 200s in five minutes, then blocked 126 of 126 across nine fingerprints
half an hour later - an early run of successes is not evidence a route holds).
That re-check's result was never posted, so treat the 6/6 figure above as
**measured at one point in time, not confirmed durable**. If runs start
failing on a Cloudflare challenge that used to succeed, this is the first
place to look, not a sign the parser broke - the contract test for this actor
watches for exactly that shape and fails loudly on it rather than reporting an
empty success.

### Billing

Pay per event, all-in: **$0.0007 per restaurant** row written, plus
**$0.002 actor-start per run** (charged only after your input parses, so a run
that fails on bad input costs nothing). Platform usage - compute, dataset
storage, the residential proxy - is included in that price; you are never
billed for it on top, and nothing here is metered and passed through.

For comparison, on the Apify Store: [piquno's Tabelog actor](https://apify.com/piquno)
leads the category on runs at $0.0025 per result, and `jungle_synthesizer`'s
lists $0.001 per result. This actor's $0.0007 per restaurant is 30% under the
cheaper of the two ($0.001) - undercutting only the runs leader would still
leave it the most expensive listing next to `jungle_synthesizer`.

# Actor input Schema

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

One or more Tabelog area pages - a plain area page (https://tabelog.com/tokyo/A1301/), a prefecture page, or an already-built list URL in any sort or page (https://tabelog.com/tokyo/A1301/rstLst/?SrtT=rt). Every URL is normalised to its area's rstLst listing and walked from page 1 regardless of what page or sort the URL you pasted was on - the Sort order field below controls that instead.

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

How Tabelog should order each area's restaurants before this actor pages through them. "New openings" is the only sort that prints an opening date; its rating is usually empty on the freshest rows (no reviews yet) but can appear further down the feed once a restaurant has picked up a few.

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

Stop after this many restaurants in total, across every area URL supplied. Tabelog serves 20 per page and refuses to page past its 60th page for any single area (1,200 restaurants), so a wide area asked for more than that returns everything it has rather than failing.

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

Residential, pinned to Japan, is required. Measured 2026-09-28: Tabelog answered a datacenter address and an unpinned residential address with Cloudflare's "Just a moment" challenge on every attempt, and only cleared with apifyProxyGroups RESIDENTIAL plus apifyProxyCountry "JP" (6/6 across 5 areas at pick time). A same-day durability re-check was scheduled but never confirmed - if you see repeated challenge failures, that is the open question, not a new bug.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://tabelog.com/tokyo/A1301/"
    }
  ],
  "sort": "new_openings",
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "JP"
  }
}
```

# Actor output Schema

## `restaurants` (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 = {
    "startUrls": [
        {
            "url": "https://tabelog.com/tokyo/A1301/"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "JP"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("superslowsloth/tabelog-restaurants").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 = {
    "startUrls": [{ "url": "https://tabelog.com/tokyo/A1301/" }],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "JP",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("superslowsloth/tabelog-restaurants").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 '{
  "startUrls": [
    {
      "url": "https://tabelog.com/tokyo/A1301/"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "JP"
  }
}' |
apify call superslowsloth/tabelog-restaurants --silent --output-dataset

```

## MCP server setup

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

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/9FBnTVLKu9U1BD7bW/builds/W6dfiV9gdRAvo87UG/openapi.json
