Rakuten Travel Scraper: Japan Hotels, Rates & Reviews
Pricing
from $1.20 / 1,000 hotel records
Rakuten Travel Scraper: Japan Hotels, Rates & Reviews
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.
Pricing
from $1.20 / 1,000 hotel records
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
1
Bookmarked
3
Total users
2
Monthly active users
15 days ago
Last modified
Categories
Share
Scrape Rakuten Travel (travel.rakuten.co.jp), Japan's largest domestic hotel-booking site, into clean structured rows. Search by prefecture, run the site's own keyword search, or paste hotel, area, keyword-results or day-use listing URLs you already have. Every row carries name, rating, review count, lowest price, catch copy and access, and can be enriched from the hotel's own pages: address, phone, check-in times, facilities, credit cards, cancellation policies, photos, the review summary and individual review texts.
Built for price monitoring, market research, inventory tracking and review mining across all 47 prefectures. No API key, no application registration, no account needed: the actor reads the site's own public pages directly.
Why This Scraper?
- Around 40 fields per hotel. From the listing card through full detail and review pages
- Two modes, many ways in. Search mode runs a prefecture walk and/or a keyword search together, URL mode processes any pasted hotel, area, keyword-results or day-use listing URL
- Sorts and filters. The site's own server-side price and review sorts, plus client-side price bounds and a minimum rating filter
- Review mining. Overall score, per-category averages (room, service, location, meals, bath), star histogram and review texts
- Built for schedules. Resume and incremental modes for daily scheduled monitoring of the same scope, returning only what changed
- All 47 prefectures. Covers all 47 prefectures of the site's own area tree, with the declared result totals respected page by page
- Bilingual input. Japanese prefecture names (東京, 北海道) and romaji (tokyo, hokkaido) both work
Use Cases
- Revenue managers and OTAs: watch a prefecture's or a hotel group's own lowest rates on a schedule and react to competitor price moves the same day.
- Travel bloggers and itinerary apps: pull hotel names, ratings, catch copy and access details for a region or a keyword search into your own site or app.
- Hospitality market research: compare a property's price and review score against every other hotel in the same prefecture or search result.
- Review and reputation analysis: collect review text, per-category scores and the star histogram to track guest sentiment over time.
- Data science and ML datasets: build labeled datasets of Japanese domestic lodging prices, ratings and facilities for forecasting or recommendation models.
Data You Get
Sample shape: values are illustrative placeholders, not from a live hotel.
| Field | Example |
|---|---|
hotelNo | 0000000 |
name | Sample Seaside Hotel |
url | https://travel.rakuten.co.jp/HOTEL/0000000/0000000.html |
ratingValue | 4.2 |
reviewCount | 1200 |
minPriceYen | 8000 |
minPriceTaxIncludedYen | 8800 |
catchcopy | A sample one line catch copy from the listing card |
access | Sample station: 5 min on foot |
thumbnailUrl | https://trvimg.r10s.jp/share/image_up/0000000/sample.jpg |
address | 〒000-0000 Sample prefecture Sample city 1-2-3 |
phoneNumber | 000-000-0000 |
checkInTime | 15:00〜19:00 |
checkOutTime | 10:00 |
parking | Available, 50 cars |
facilities | ["Restaurant", "Large bath", "Non-smoking rooms"] |
cancellationPolicy | Cancellation terms as printed on the page |
description | Full property description text when details are on |
ratingSummary | {"overallScore": 4.2, "reviewCount": 1200, "categoryAverages": {"ROOM": 4.1}} |
reviews | [{"title": "Sample review title", "comment": "Sample review text", "score": 5}] |
reviewsTotal | 1200 |
changeType | NEW (incremental mode only) |
changedFields | ["minPriceYen"] (incremental mode only, on UPDATED rows) |
Every row also carries recordId, rowType (always hotel), its position in the source page, plansUrl and plans (inline plan boxes from keyword and day-use results), searchSource, sub-area names (areaMiddle / areaSmall), faxNumber, totalRooms, roomAmenities, creditCards, meals, privileges, planCancellationPolicy, photoUrls, scrapedAt, and, in incremental mode, firstSeenAt / lastSeenAt plus a detailCarriedForward flag when a detail field was repaired from a prior run's snapshot instead of freshly read this run.
Output views
The Output tab has Overview, Room rates, Hotel details, Reviews, Plans and (incremental mode) Changes views. Reviews, Plans and Room rates unwind the nested lists into one table row per entry; the dataset itself keeps one row per hotel. A run summary is saved under the OUTPUT key of the key-value store.
Room rates by date (optional)
Set Check-in date, or Start date / End date, or Months ahead, and every hotel row also carries a rates list: one entry per check-in date, room and plan, read from the hotel's own plan page. It needs Fetch full hotel details on, and it is off by default, so existing runs return exactly what they did before.
- Each entry has the room (id, name, category, size, bath and smoking condition, capacity), the plan (id, name, meal plan, room-only flag), availability and remaining rooms, base and selling price with and without tax, discount amount and rate, per-person price, coupon names and amounts (including card-only coupons), point rate and points, net price after points, member discount and the cancellation steps.
- The stay is set with Nights, Adults, Children or Child counts (per age band) and Rooms. Keep sold-out entries adds an entry for plans with no vacancy.
- The row also echoes the stay context:
currency,checkInDate,checkOutDate,nights,leadTimeDays,adults,children, the child-band counts,rooms,propertyId,propertyName,source,sourceUrl,capturedAt. - Limits: at most 62 check-in dates per hotel and 2000 rate entries per hotel row. Rates ride the hotel row: there are no extra dataset rows and no extra charge. The Output tab has a Room rates view that unwinds
ratesto one table row per entry. - Incremental mode treats a changed rate as a change of the hotel row; add
ratesto Ignore fields when detecting changes to track only the hotel facts.
How to Use
- Pick a mode:
searchwalks the prefectures and runs the keyword searches you list;urlprocesses the hotel, area, keyword-results or day-use links you paste. - Add price and rating filters if you want narrower rows; they apply in both modes.
- Turn Fetch full hotel details and Fetch reviews on or off, and set Max items to control run size and cost.
- Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.
Search one prefecture, with full details (default):
{"mode": "search","locations": ["東京"],"maxItems": 20}
Prefecture walk with price sort, keywords and price bounds:
{"mode": "search","locations": ["大阪", "kyoto"],"keywords": ["温泉 箱根"],"sortBy": "price_low","minPriceYen": 6000,"maxPriceYen": 25000,"minRating": "3.5","maxItems": 60}
If you leave urls untouched in URL mode, the run scrapes one example of each supported URL shape (hotel, plan page, reviews page, prefecture and sub-area listings, search-host listings, a paginated listing, keyword results, a paginated keyword page, and the day-use landing page and a day-use prefecture listing); clear the field and paste your own links to narrow it. A pasted listing URL walks exactly that page and onward (a sub-area page stays within the sub-area, a p2, f_next=2 (keyword results) or index2.html (day-use) URL starts at that page and counts as a partial scope). The day-use landing page /dayuse/ is expanded into its prefecture listings, read in site order until Max items is reached. A saved URL-mode incremental task that relied on the old two-URL default keeps its stored state key and baseline; the extra example shapes simply arrive as NEW once.
Paste hotel URLs (reviews included):
{"mode": "url","urls": ["https://travel.rakuten.co.jp/HOTEL/0000000/0000000.html","https://travel.rakuten.co.jp/HOTEL/0000001/0000001.html"],"fetchReviews": true,"maxItems": 10}
Daily price watch of one prefecture (incremental mode):
{"mode": "search","locations": ["沖縄"],"maxItems": 0,"incrementalMode": true,"stateKey": "okinawa-watch"}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/rakuten-travel-scraper").call(run_input={"mode": "search", "locations": ["東京"], "maxItems": 20,})for hotel in client.dataset(run["defaultDatasetId"]).iterate_items():print(hotel["name"], hotel["minPriceYen"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/rakuten-travel-scraper').call({mode: 'search', locations: ['東京'], 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.
How maxItems and maxPages shape a run
maxItems is the single cap on the whole run, split evenly across every prefecture, keyword and pasted URL you list. maxPages additionally bounds how many listing pages each source walks (each page serves about 30 hotels); leave it at 0 to let a source stop only at maxItems or the site's own end of results. Cards a source reads but does not keep, because the price or rating filters excluded them or the per-source budget was already spent, are still counted as scanned internally, so a later scheduled run's incremental EXPIRED check is never fooled into thinking a hotel that simply missed this run's cap or filters has disappeared from the site.
Resume and recurring updates
- Resume (
resumeFromRunId) continues one interrupted or capped run: paste its run or dataset ID and the actor skips every hotel that run already collected, so you don't pay twice. - Incremental mode (
incrementalMode) is for scheduled runs over the same scope. Each hotel is classifiedNEW,UPDATED(withchangedFields, a price or rating move counts as a change),UNCHANGED(suppressed and not billed unlessemitUnchangedis on),REAPPEAREDorEXPIRED(only after a run that scanned the whole scope end to end, and only withemitExpired; a pasted listing URL that starts past page 1 counts as a partial scope and never marks anythingEXPIRED).stateKeynames or shares the stored state.ignoreFieldsForChangeslists extra field names (matched at any depth, so insideplansandreviewstoo) that must not count as a change; they stay in the output. Always ignored for change detection, at any depth (so insideratestoo):scrapedAt,detailCarriedForward,position,searchSource,capturedAt,leadTimeDays,ratesDatesScanned,sourceUrl. Everything else is compared, includingthumbnailUrlandphotoUrls, which were measured identical across two scrapes of the same scope. A field this actor started emitting after your baseline was saved (reviewhelpfulVotesandreplies,rates) never makes a saved hotelUPDATEDby itself; the baseline simply picks it up on the next run. With incremental mode off, output is exactly as before.
Overlapping searches. Hotels already collected by an earlier source in the same run (or by the run you resume from) are skipped, and a page made up only of such hotels no longer ends the walk, so later pages with new hotels are still read. A walk ends early only when a page repeats hotels that same walk already read (the site restarted its list). The run still finishes successfully, and the incremental EXPIRED check refuses to run after an early end like this.
Send results into your apps (MCP connectors)
Optionally pipe this actor's results into the apps you already use with MCP connectors: authorize one under Apify, Settings, API & Integrations, then select it in the mcpConnectors input and set notionParentPageUrl for Notion. Each connector receives a condensed summary per record (a title plus key fields flattened to text, maxNotifyListings per run), not the full record; the complete record always stays in the Apify dataset. Leave the inputs empty and nothing changes: the export never runs and the dataset output is identical.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | select | search | search walks prefecture area pages and keyword results; url processes pasted URLs. |
locations | array | ["東京"] | Prefecture words (Japanese or romaji) matched against the site's 47-prefecture area tree. Search mode only. |
keywords | array | [] | Keyword searches run on the site's own search, following the site's own results pager (about 30 hotels per page). Search mode only. |
urls | array | 11 examples, one per URL shape | Hotel URLs (one hotel each), or area /yado/, /ds/yado/, keyword-results and day-use listing URLs (walked like a search). URL mode only. |
sortBy | select | recommended | The site's server-side order of each prefecture walk: recommended, price low/high, review score. Search mode, area walks only. |
minPriceYen | integer | - | Keep rows at or above this price in yen. Both modes. |
maxPriceYen | integer | - | Keep rows at or below this price in yen. Both modes. |
minRating | string | - | Keep rows whose review score is at least this (for example 4.0). Both modes. |
sortResultsBy | select | site_order | Reorder this run's collected rows after the read. Both modes. |
fetchDetails | boolean | true | Read each hotel's own page for address, phone, check-in times, facilities, policies and photos. Adds the per-hotel detail enrichment charge. |
fetchReviews | boolean | false | Also read the review page: summary, per-category averages and review text. Covered by the same enrichment charge. |
maxReviews | integer | 20 | Maximum review rows per hotel when fetchReviews is on. 0 = all available reviews, up to 10,000 per hotel (maxPages is also capped at 10,000). Each review row also carries helpful votes and any host replies. The first started block of 10 returned review rows is covered by the hotel's one enrichment event, and each further started block adds one more. |
maxItems | integer | 20 | The single output cap across all sources. 0 = unlimited. |
maxPages | integer | 0 | Safety bound on listing pages per source. 0 = no page limit. |
checkInDate | string | - | Single stay date, YYYY-MM-DD (Japan time). Turns on the dated rates list (needs details on). |
startDate | string | - | First check-in date of a range, YYYY-MM-DD. |
endDate | string | - | Last check-in date of the range, inclusive. |
monthsAhead | integer | 0 | Scan this many months of check-in dates (0 = off), at most 62 dates per hotel. |
nights | integer | 1 | Length of stay per scanned check-in date. |
adults | integer | 2 | Adults per room for the rate query. |
children | integer | 0 | Children in the elementary-school upper band; overridden by childCounts. |
childCounts | object | - | Children per age band (for example elementaryUpper, elementaryLower). |
rooms | integer | 1 | Rooms for the rate query. |
includeSoldOut | boolean | false | Keep an entry for plans with no vacancy on a scanned date. |
ignoreFieldsForChanges | array | - | Extra field names that must not count as a change, matched at any depth. Incremental mode only. |
resumeFromRunId | string | - | Continue one interrupted run: skip records that run already collected. |
incrementalMode | boolean | false | Scheduled monitoring: return only NEW, UPDATED and REAPPEARED records against the previous run of the same scope. |
stateKey | string | - | Optional name for an incremental monitoring campaign. |
emitUnchanged | boolean | false | Also return UNCHANGED rows (billed). |
emitExpired | boolean | false | Also return EXPIRED rows after a complete scan (billed). |
mcpConnectors | array | (none) | Optional MCP connector IDs for the condensed result export. |
notionParentPageUrl | string | - | Optional Notion parent page URL for the MCP export. |
maxNotifyListings | integer | 50 | Maximum condensed records sent to MCP connectors per run. |
proxy | object | Apify Proxy | Proxy configuration (Proxy & connection section): the connection used to read the site. If it is refused the actor falls back to other connections (see Plan Requirement). |
Output Example
Sample shape: values are illustrative placeholders, not from a live hotel.
{"recordId": "0000000","hotelNo": "0000000","rowType": "hotel","url": "https://travel.rakuten.co.jp/HOTEL/0000000/0000000.html","name": "Sample Seaside Hotel","ratingValue": 4.2,"reviewCount": 1200,"minPriceYen": 8000,"minPriceTaxIncludedYen": 8800,"catchcopy": "A sample one line catch copy from the listing card","access": "Sample station: 5 min on foot","thumbnailUrl": "https://trvimg.r10s.jp/share/image_up/0000000/sample.jpg","position": 3,"searchSource": "東京","address": "〒000-0000 Sample prefecture Sample city 1-2-3","phoneNumber": "000-000-0000","faxNumber": "000-000-0001","checkInTime": "15:00〜19:00","checkOutTime": "10:00","parking": "Available, 50 cars","totalRooms": 120,"facilities": ["Restaurant", "Large bath", "Non-smoking rooms"],"roomAmenities": ["TV", "Refrigerator", "Hair dryer"],"creditCards": ["VISA", "Master Card"],"meals": ["[Breakfast] Restaurant"],"cancellationPolicy": "Sample cancellation terms from the hotel page","description": "Sample full property description.","photoUrls": ["https://trvimg.r10s.jp/share/image_up/0000000/sample.jpg"],"ratingSummary": {"overallScore": 4.2,"reviewCount": 1200,"categoryAverages": {"ROOM": 4.1, "BREAKFAST": 4.3},"starHistogram": {"FIVE": 500, "FOUR": 400}},"reviews": [{"reviewId": "000000","title": "Sample review title","comment": "Sample review text.","postedAt": "2026-01-01T00:00:00Z","score": 5,"nickname": "SampleNick","stayDate": "2026-01-01","planName": "Sample plan name"}],"reviewsTotal": 1200,"scrapedAt": "2026-01-01T00:00:00Z","changeType": "NEW","changedFields": [],"firstSeenAt": "2026-01-01T00:00:00Z","lastSeenAt": "2026-01-01T00:00:00Z"}
Plan Requirement
Measured: the standard Apify proxy (datacenter) and a residential connection with country JP both served every page type this actor reads (hotel, plan, review, area, keyword and day-use pages), so a paid plan with the default proxy is all that is needed. The actor tries the standard Apify proxy first, then moves to a residential connection and finally to backup connections, keeping the first one that serves the page (each page gets a 25 second budget). Apify free plans include no Apify proxy at all: on a free plan the run continues on a backup connection and logs "Apify free plans do not include residential proxies", and some pages may still be unavailable. A paid plan (or your own proxy URLs in the Proxy configuration field of the Proxy & connection section) is the reliable choice. Per-event pricing (actor start, hotel record, hotel detail enrichment) is shown on the actor's Pricing tab before a run.
- Prices are the site's publicly displayed lowest rates for its default availability window, in Japanese yen; a rate move between scheduled runs classifies as UPDATED in incremental mode.
- Keyword searches and prefecture area walks each follow the site's own results pager, about 30 hotels per page.
- The keyword results page is served in the site's own legacy Japanese text encoding; the actor encodes your keywords and decodes the page for you.
- A run needs no account and no API registration on any surface it reads.
FAQ
How much does it cost?
Three events are charged. One hotel record per row delivered. One detail enrichment per hotel whose own pages were actually read, covering the first started block of 10 review rows returned, plus one more for each further started block of 10 (so 25 reviews bill 3 enrichment events for that hotel). One actor start event per GB of run memory. Suppressed (UNCHANGED), refused or unread hotels are not charged for enrichment. Rates ride the hotel row at no extra charge. The Pricing tab shows the current rates. Use Max items to cap the cost of any run.
Is it legal to scrape Rakuten Travel?
This actor collects only publicly available hotel and pricing data. You are responsible for how you use it: follow Rakuten Travel's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Hotel names, prices and availability are generally facts, but photos and guest review text may be subject to third-party rights.
Can I get only new or changed hotels on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Later runs then return only NEW, UPDATED and REAPPEARED hotels; unchanged ones are suppressed and not billed unless you turn on Emit unchanged. A price or review score move is reported as UPDATED, since on a booking site the rate is the signal being watched, not noise.
What's the difference between Resume and Incremental mode?
Resume (resumeFromRunId) continues ONE specific interrupted or capped run: paste its run or dataset ID and this run skips every hotel that run already collected, so you never pay twice for the same page. Incremental mode is for scheduling the SAME search again and again (daily, weekly) and getting back only what changed since the last scheduled run. Use Resume to finish a single large crawl; use Incremental mode for ongoing monitoring.
Why did my run return fewer hotels than I expected?
Three reasons cover almost every case. Max items or Max listing pages capped the run before the site's own pager ran out (raise them, or set Max items to 0 for the full scope). The price or rating filters narrowed the rows this run kept. Or, if this run combined several prefectures, keywords or pasted URLs whose hotel lists overlap, one of those sources may have ended its own walk early: after bringing new hotels, it reached a page made up only of hotels another source had already collected, and it skipped the pages after it (see the tip under How to Use). Running overlapping searches as separate runs avoids this.
Why did my run fail instead of returning an empty dataset?
If every source this run started was refused or could not be read, the run stops with a clear message so "no hotels matched" is never confused with "nothing could be read". The message says either that the proxy connection was refused for the account (a paid plan or your own proxy URLs are needed), that residential proxies are unavailable and the backup connection could not load the pages, or that no results page could be loaded (a connection problem, not an empty search). Run it again in a few minutes, or check the Proxy configuration field in the Proxy & connection section. If some sources served pages while others were refused, the run still succeeds quietly and the status message names the refused count.
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 Rakuten data?
Pair this actor with these related scrapers from the same team:
| 🧩 Rakuten Scrape Rakuten Ichiba (rakuten.co.jp): name, JPY price, reference price and discount... | 🏨 Booking.com Scraper Scrape booking.com hotels, apartments, villas and hostels. Search any destination with... |
| 🏨 Wego Scraper Scrape Wego hotels by city or search URL. Get rates, providers, booking links... | 🏨 Traveloka Hotel Scraper Scrape Traveloka hotels across Singapore, Malaysia, Indonesia, Thailand, Vietnam and the... |
| 🏨 Hostelworld Scraper Scrape Hostelworld hostels, hotels, guesthouses, B&Bs, apartments and campsites by city... | 🏨 Rover Pet Care Scraper Scrape Rover.com pet-care providers: sitter search by city, rates per stay type, ratings... |
💬 Support
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. 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.