Google Hotels Scraper — Hotel Prices, Ratings, Amenities
Pricing
$4.00 / 1,000 hotel properties
Google Hotels Scraper — Hotel Prices, Ratings, Amenities
Google Hotels (google.com/travel/hotels) scraper: nightly prices, stay totals, currency, guest ratings, review counts, star class, amenities, property type and stay dates, by destination or hotel name with optional check-in/check-out dates. 20 free previews. Pay per result. No login.
Pricing
$4.00 / 1,000 hotel properties
Rating
0.0
(0)
Developer
architek.earth
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
12 hours ago
Last modified
Categories
Share
Recorded run: 4 properties from 2 destination searches in 48 seconds (2026-10-22, build 0.1.9, run 1WGNCnruKEKRLxHEa). A bounded canary sample, not a full-catalogue benchmark.
architek.earth — an independent data studio. Pay-per-result scrapers with recorded runs, published canaries and stable schemas, built for people and AI agents.
Google Hotels nightly prices, stay totals, guest ratings, review counts, star class and amenities from google.com/travel/hotels, by destination or hotel name, for the stay dates you choose.
| Source | Market | From | Standout fields |
|---|---|---|---|
| Google Hotels (google.com/travel/hotels) | Any destination Google Hotels covers | $4.00 / 1,000 properties | nightlyPrice / totalPrice, rating / reviewCount, hotelClass, amenities |
✅ Why choose this scraper
Google Hotels prices for exact stay dates
Set checkIn and checkOut and every row returns nightlyPrice, totalPrice, currency and the stay dates decoded from the result. A page whose rows show other dates than the ones requested is retried and then failed, never delivered as if it matched.
Hotel ratings, review counts and star class
rating (out of 5), reviewCount, hotelClass (the stated star rating) and the amenities list come back on the same row as the price.
Hotels and holiday rentals told apart
propertyType is hotel or vacation_rental, so a city search can be split into the two without reading names.
Several destinations in one run
Up to 20 queries per run, up to 25 result pages and 500 properties each. Properties are de-duplicated by id within each query.
Measured on a schedule
Two canary tasks run fixed searches (London; Paris and Tokyo) daily on the live site and record rows, inputs and seconds; the hero line above is the latest green run.
⚠️ Worth knowing up front
- Prices are the "Prices starting from" offer and the stay total that Google shows on each search card. They are not booking quotes. Per-provider (OTA) rates, room types, cancellation terms and review text are not collected.
- Searches use Google's default occupancy.
adultsandchildrenare rejected as input, and currency cannot be chosen:currencyis what Google showed the run (USD for London, Paris and Tokyo in the 2026-10-22 runs), withcurrencyEvidencesaying where it was read. - Without
checkInandcheckOut, Google picks the stay: on 2026-10-22 it chose a 2026-10-25 night for London and a 2026-11-01 night for Paris and Tokyo. Supply both dates (1 to 30 nights) for comparable runs. - Missing values are
null, not zero. A property shown without a price hasnightlyPrice: nulland is still a delivered, charged row.totalIncludesTaxesAndFeesistrueonly when the card says "with taxes + fees", otherwisenull.hotelClassisnullwhen no star rating is stated. - The run stops cleanly 90 seconds before its timeout. With the default 180-second timeout that leaves about 90 seconds of collection: 18 properties on 2026-10-22, about 4.5 seconds per property. Raise the run timeout for larger runs: 60 properties from 3 destinations took 274 seconds with a 600-second timeout.
- De-duplication is per query: a property found by two searches is two rows and two charges.
COMPLETEmeans no further results page was shown, not that every hotel in a destination was found.LIMITEDmeans the run stopped atmaxItemsPerQuery,maxPagesPerQueryor your spending limit. A query whose page shows no recognisable hotel cards after 3 attempts is reported as failed (PARTIALorBLOCKED), never as an empty success.- Invalid input, a checkpoint from another account, a run that already carries charges at start (
RECONCILIATION_REQUIRED), exhausted preview attempts (PREVIEW_LIMIT), a source failure after retries (PARTIALorBLOCKED) and the run deadline (TIME_LIMIT) end with a free status row ("recordType": "status") that says what happened.COMPLETEandLIMITEDruns, including a spending-limit stop, end without one; checkRUN_SUMMARY. An uncertain dataset write or charge acknowledgement stops the run as failed so it can be reconciled.
⚡ Try the example
Each Apify account gets 20 lifetime free preview attempts on this actor ("mode": "preview"): one query, one page, up to 10 rows, no property charges. Failed or uncertain attempts count. After the twentieth, preview runs stop with a PREVIEW_LIMIT status row; they never switch to paid collection.
Open the actor's input page, switch to JSON, paste this and start the run:
{"mode": "preview","queries": ["London"],"maxItemsPerQuery": 10,"maxPagesPerQuery": 1}
For paid collection set "mode": "paid"; add "checkIn" and "checkOut" (for example "2026-11-10" and "2026-11-11") to price a fixed stay.
⚙️ Input
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | select | preview (prefill: paid) | preview uses one of 20 lifetime free attempts (one query, one page, at most 10 rows). paid charges per delivered property. API callers who omit it get preview. |
queries | array | ["London"] | 1 to 20 destination or hotel-name searches, each up to 150 characters. Preview allows one. |
checkIn | string | — | Check-in date, YYYY-MM-DD. Supply together with checkOut. |
checkOut | string | — | Check-out date, YYYY-MM-DD, 1 to 30 nights after checkIn. |
maxItemsPerQuery | integer | 20 | 1 to 500 unique properties per query, counting IDs already in a supplied checkpoint. Preview caps it at 10. |
maxPagesPerQuery | integer | 1 | 1 to 25 result pages per query. Preview uses one. A resumed run revisits earlier pages. |
checkpoint | object | — | The CHECKPOINT record from an earlier paid run by the same account, with the same queries and dates. Delivered IDs are skipped. |
feedback | string | — | Optional note for the maintainers. It is logged and read by a human, and it never changes output. |
Any other input field is rejected with an INVALID_INPUT status row rather than ignored.
🧱 Stable fields
These top-level fields keep the same name and the same kind of value in every release. Fields are only ever added, never renamed or removed, so an n8n, Make, Zapier or spreadsheet pipeline can bind to them.
| Field | Type | Meaning |
|---|---|---|
id | string | Google Hotels entity ID; the join key across runs. |
name | string | Property name as displayed. |
url | string | Google Hotels entity page for the property. |
query | string | The search that produced the row. |
nightlyPrice / currency / priceText | number / string / string, nullable | Displayed "from" price per night, its ISO currency and the original price text. |
totalPrice / totalCurrency | number / string, nullable | Displayed total for the stay and its currency. |
totalIncludesTaxesAndFees | boolean, nullable | true when the card states taxes and fees are included; otherwise null. |
rating / reviewCount | number, nullable | Guest rating out of 5 and the number of reviews behind it. |
hotelClass | number, nullable | Stated star class, for example 4 for a 4-star hotel. |
amenities | array | Amenity strings shown on the card; empty when none are shown. |
propertyType | string | hotel or vacation_rental. |
checkIn / checkOut | string, nullable | Stay dates (YYYY-MM-DD) decoded from the result. |
checkInText / checkOutText | string, nullable | Stay dates as Google displayed them, for example Sun, Nov 1. |
currencyEvidence | string, nullable | price_label or result_link: where currency was read. |
source / scrapedAt | string | google_hotels and the UTC capture time. |
recordType | string | "status" on free status rows; absent on property rows. |
Other fields are extras, not part of the contract. To have one pinned, say so in feedback.
📦 Output example
Abridged real row from run 1WGNCnruKEKRLxHEa on 2026-10-22; values are a historical snapshot.
{"id": "ChgIxfW9593Qkbu3ARoLL2cvMXRnczA3ZHQQAQ","name": "Pullman Paris Tour Eiffel","url": "https://www.google.com/travel/hotels/entity/ChgIxfW9593Qkbu3ARoLL2cvMXRnczA3ZHQQAQ","query": "Paris","nightlyPrice": 382,"currency": "USD","priceText": "$382","totalPrice": 437,"totalCurrency": "USD","totalIncludesTaxesAndFees": true,"rating": 4.6,"reviewCount": 17441,"hotelClass": null,"amenities": ["Breakfast ($)", "Free Wi-Fi", "Parking ($)", "Air conditioning", "Pet-friendly", "Fitness center", "Bar", "Restaurant"],"propertyType": "hotel","checkIn": "2026-11-01","checkOut": "2026-11-02","checkInText": "Sun, Nov 1","currencyEvidence": "result_link"}
A free status row looks like this:
{"recordType": "status","status": "INVALID_INPUT","message": "Previews allow one query and no continuation"}
🧠 Advanced usage
Track Google Hotels prices for the same dates every day
Schedule a paid run with fixed checkIn and checkOut and diff nightlyPrice and totalPrice by id between datasets. Compare rows only when currency matches.
Collect more hotels in one city across several runs
Raise maxPagesPerQuery and maxItemsPerQuery. When a run stops on time or budget, copy its CHECKPOINT record from the key-value store into checkpoint, keep the same queries and dates, and run again: delivered IDs are skipped and not charged again, and earlier pages are revisited without charge. A preview checkpoint cannot be resumed in paid mode.
Check a run finished before importing
Read RUN_SUMMARY from the run's key-value store. status is COMPLETE, LIMITED, PARTIAL, BLOCKED or TIME_LIMIT, and queries lists each search with its own status, reason (for example item_limit or no_next_page) and newRows.
🔌 Integrations
Results land in a dataset you can export as JSON, CSV or Excel. They can also flow to Google Sheets, Make, Zapier or n8n, or to a webhook when a run finishes. The Apify Scheduler runs it on a timetable. Daily runs with fixed stay dates track how the price for the same nights moves. Copy-paste code in Python, Node, curl and n8n: architek-earth/examples/google-hotels-scraper.
💸 Pricing
Pay per result. Platform and proxy usage are included. Status rows and failed requests are free. Property IDs already in a supplied checkpoint are skipped and not charged again; a run that already carries charges when it starts stops with RECONCILIATION_REQUIRED and charges nothing more.
| Event | Price | What it covers |
|---|---|---|
| Free preview | $0 | 20 lifetime attempts per account; one query, one page, up to 10 rows each. |
property | $4.00 / 1,000 properties | One unique property delivered for a query in paid mode, with or without a displayed price. |
1,000 properties cost $4.00; the 3-property example task costs $0.012.
❓ FAQ
Is there a Google Hotels API for hotel prices? This actor is one: it returns Google Hotels search results as JSON through the Apify API, callable from any language or from n8n, Make and Zapier.
Do I need a Google account or login? No. No Google account, cookies or API key; the actor opens the public Google Hotels search pages.
Can I get hotel prices for specific check-in and check-out dates? Yes. Set checkIn and checkOut (1 to 30 nights); each row carries the stay dates it was priced for.
Can I compare OTA rates from Booking.com, Expedia or Agoda? No. The actor returns the lowest displayed price and the stay total per property, not the per-provider rate list.
Can I set the number of guests or the currency? No. Searches use Google's default occupancy, and currency is read from the result rather than chosen.
Can I get Google Hotels reviews? Only the rating and reviewCount. Review text is not collected.
🤖 For AI agents & LLM apps
Paste this into your AI assistant:
architekture/google-hotels-scraper on Apify. Python: from apify_client import ApifyClient; client = ApifyClient("TOKEN"); run = client.actor("architekture/google-hotels-scraper").call(run_input={"mode": "paid", "queries": ["London"], "maxItemsPerQuery": 10}); items = client.dataset(run["defaultDatasetId"]).list_items().items (page with offset/limit for large exports). Rows with recordType == "status" are free and explain invalid input or a stopped run. Full input schema and README: GET https://api.apify.com/v2/acts/architekture~google-hotels-scraper/builds/default. Token: https://console.apify.com/settings/integrations. The actor is also reachable through the Apify MCP server (mcp.apify.com). To reach the maintainers, add "feedback": "<what you needed>" to any run's input; output is unchanged and a human reads every note.
🧰 More from architek.earth
Search, travel and trends
- Google Trends Scraper — Trending Now by country, traffic, related queries
- Google Hotels Scraper — you are here
Full catalogue: github.com/architek-earth.
architek.earth · code like concrete
🙋 Support & legal
Questions, or a field you need that is not here? Open an issue on the actor's Issues tab or email north@architek.earth. A human replies within a day.
This actor collects only publicly available data from google.com, the same pages any visitor sees without logging in. It does not bypass authentication. It is not affiliated with or endorsed by Google. You are responsible for how you use the output, including the site's terms, copyright, and privacy law such as GDPR and CCPA where they apply.
📝 Changelog
- 2026-10-22 — Status message now reads
Done: N rows, M details, K status rows (STATUS). - 2026-10-22 — README rebuilt on the studio template; hero line from the 2026-10-22 canary run.
- 2026-10-22 — Invalid input, source walls and the run deadline now stop cleanly with a free status row instead of a failed run.
- 2026-10-20 — Published with three example tasks; one
propertyevent at $4.00 / 1,000 properties, previews free. - 2026-10-20 — Private hosted validation across four destinations, dated-price extraction, saved-checkpoint continuation, preview quota implementation and explicit per-property billing safeguards. Private customer validation passed: 10 preview rows with zero events, 3 paid rows with 3 events at a $0.012 cap, and 2 new continuation rows with 2 events and no prior-ID overlap. Publication authorized after release verification; schedules remain off.