{
  "openapi": "3.0.1",
  "info": {
    "title": "Rakuten Travel Scraper: Japan Hotels, Rates & Reviews",
    "description": "Scrape Rakuten Travel, Japan's largest domestic hotel-booking site, by prefecture, keyword or URL. Every row carries name, rating, review count, lowest price and access, with optional details: address, phone, facilities, policies, photos and reviews. No API key needed.",
    "version": "0.1",
    "x-build-id": "P1Lb3gupOGeohTqt0"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~rakuten-travel-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-rakuten-travel-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/abotapi~rakuten-travel-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-rakuten-travel-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/abotapi~rakuten-travel-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-rakuten-travel-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "Mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "How to start the scrape. 'search' walks the site's own area listing pages for the prefectures you list, and runs the keyword searches you list. 'url' processes the Rakuten Travel URLs you paste: a hotel URL is fetched as a single hotel; an area, keyword-results or day-use listing URL is browsed like a search, its own path deciding the scope.",
            "default": "search"
          },
          "locations": {
            "title": "Prefectures and regions",
            "type": "array",
            "description": "One or more Japanese prefecture names or romaji spellings, for example '東京', '大阪', 'okinawa', '北海道'. Each word is matched against the 47 prefectures of the site's own area listing tree, and every matching prefecture is walked independently. Search mode ONLY: in URL mode the pasted URL decides its own scope. Sub-areas of a prefecture (for example a city page) can be scoped by pasting their URL in URL mode.",
            "default": [
              "東京"
            ],
            "items": {
              "type": "string"
            }
          },
          "keywords": {
            "title": "Keyword searches (optional)",
            "type": "array",
            "description": "One or more search words, for example '新宿 ホテル' or '温泉 箱根'. Each keyword runs the site's own keyword search and follows the results pages the site's own pager declares (about 30 hotels per page). Search mode ONLY: in URL mode the pasted URLs decide their own scope. The keyword pages are served in the site's legacy text encoding, which the actor handles for you.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "urls": {
            "title": "Rakuten Travel URLs",
            "type": "array",
            "description": "Rakuten Travel URLs to process. A hotel URL (travel.rakuten.co.jp/HOTEL/...) or a plan-page URL (hotel.travel.rakuten.co.jp/hotelinfo/plan/...) returns one hotel. An area listing URL (/yado/... or search.travel.rakuten.co.jp/ds/yado/...), a keyword-results URL (kw.travel.rakuten.co.jp/keyword/Search.do) or a day-use listing URL (/dayuse/...) is paginated like a search, its own path deciding the scope. URL mode only.",
            "default": [
              "https://travel.rakuten.co.jp/HOTEL/70818/70818.html",
              "https://travel.rakuten.co.jp/yado/tokyo/"
            ],
            "items": {
              "type": "string"
            }
          },
          "sortBy": {
            "title": "Sort the area listing by",
            "enum": [
              "recommended",
              "price_low",
              "price_high",
              "review"
            ],
            "type": "string",
            "description": "The site's own server-side ordering of each prefecture walk: recommended (the site default), price low to high, price high to low, or review score high to low. Search mode ONLY and area walks only: in URL mode the pasted URL decides its own scope, and keyword results come in the site's own order. For reordering this run's collected rows after the read, use the ordering field under Output and limits.",
            "default": "recommended"
          },
          "minPriceYen": {
            "title": "Minimum price (JPY)",
            "minimum": 0,
            "type": "integer",
            "description": "Only keep listing rows whose lowest rate is at least this many Japanese yen. Narrows listing rows in BOTH search mode and URL mode; a pasted hotel URL always returns its hotel."
          },
          "maxPriceYen": {
            "title": "Maximum price (JPY)",
            "minimum": 0,
            "type": "integer",
            "description": "Only keep listing rows whose lowest rate is at most this many Japanese yen. Narrows listing rows in BOTH search mode and URL mode; a pasted hotel URL always returns its hotel."
          },
          "minRating": {
            "title": "Minimum review score (0 to 5)",
            "type": "string",
            "description": "Only keep listing rows whose guest review score is at least this value, for example 4.0. Rows whose score the listing page does not show are dropped while this filter is set. Narrows listing rows in BOTH search mode and URL mode; a pasted hotel URL always returns its hotel."
          },
          "sortResultsBy": {
            "title": "Order the returned rows by",
            "enum": [
              "site_order",
              "price_asc",
              "price_desc",
              "rating_desc"
            ],
            "type": "string",
            "description": "Arranges the rows this run collected, after they are read, including pasted hotels. This is a local tidy up of one run's output, not a catalogue wide ordering. Applies in BOTH search mode and URL mode.",
            "default": "site_order"
          },
          "fetchDetails": {
            "title": "Fetch full hotel details",
            "type": "boolean",
            "description": "Read each hotel's own detail page for the complete record: address, phone, fax, access, check-in and check-out times, parking, room count, facilities, room amenities, credit cards, meal options, cancellation policies, description and photos. Leave it on for the full record; turn it off for cheap listing rows only (name, rating, review count, lowest price, catch copy, access, thumbnail). Turning it on adds the Hotel detail enrichment charge per hotel actually read this run.",
            "default": true
          },
          "fetchReviews": {
            "title": "Fetch reviews",
            "type": "boolean",
            "description": "Read each hotel's review page as well: the review summary (overall score, per-category averages, star histogram) and review text. The amount is controlled by Max reviews per hotel. Adds review reads covered by the same Hotel detail enrichment charge.",
            "default": false
          },
          "maxReviews": {
            "title": "Max reviews per hotel",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum review rows to return for each hotel when Fetch reviews is on. The default is 20. Set 0 to return all reviews available from the site. Billing starts one Hotel detail enrichment event for each block of 10 review rows returned.",
            "default": 20
          },
          "maxItems": {
            "title": "Max items",
            "minimum": 0,
            "type": "integer",
            "description": "The single cap on this run: stop after collecting this many records across all prefectures, keywords and URLs. Set 0 for unlimited.",
            "default": 20
          },
          "maxPages": {
            "title": "Max listing pages per source",
            "minimum": 0,
            "type": "integer",
            "description": "Safety bound on how many listing pages to walk per prefecture, keyword or pasted area URL. Each page serves about 30 hotels. Leave 0 for no page limit: the run then stops at Max items, or when the site's own pager runs out.",
            "default": 0
          },
          "resumeFromRunId": {
            "title": "Resume from a previous run",
            "type": "string",
            "description": "Paste a previous run ID or dataset ID to continue a large crawl without returning or charging for records already collected there. Use this after an interrupted or capped run. For recurring monitoring of the same search, use Incremental mode below instead."
          },
          "incrementalMode": {
            "title": "Incremental changes for scheduled runs",
            "type": "boolean",
            "description": "Turn this on for daily or weekly recurring monitoring of the same scope, for example a prefecture price watch. The first run returns everything matching as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED records. Rate and score moves ARE reported as UPDATED: on a booking site the rate is the signal, not noise. Turn on Emit unchanged or Emit expired only when you also want those rows returned (and billed). State is kept separately per prefecture, keyword, 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 a previous run above.",
            "default": false
          },
          "stateKey": {
            "title": "State key (optional, incremental mode only)",
            "type": "string",
            "description": "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 prefectures, keywords, URLs and filters, so two different scopes never mix state."
          },
          "emitUnchanged": {
            "title": "Emit unchanged records (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return records 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 a full snapshot every run.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired records (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return records that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked scope: not when Max items capped it, not when Resume was used, and not when the run was refused. This returns, and bills, extra synthetic rows, so leave it off unless you need expiry tracking.",
            "default": false
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a page per record; other connectors get a best-effort write or digest. Each connector receives a condensed summary per record, not the full record; the complete record always stays in the dataset. Leave empty to skip; this never changes the dataset output. 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": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL or id of the Notion page under which record pages are created. Required to enable the Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max items to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on records written to each connector per run. Does not affect the dataset.",
            "default": 50
          },
          "proxy": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Leave the default: the standard Apify proxy serves every page this actor reads, probed live. Prices quoted on each row are Japanese yen.",
            "default": {
              "useApifyProxy": true
            }
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}