How to use Google Hotels Scraper
Step by step: in the Apify Store, over the API, from JavaScript or Python, in n8n, and from AI agents through MCP or LangChain.
$4.49 per 1,000 hotel rows on the Free plan, down to $2.69 on higher plans (live Apify price on 2026-10-31).
1. In the Apify Store (no code)
- Open arcadium/google-hotels and sign in to Apify (a free account works).
- Fill in the input form. The fields below are the ones the example uses.
- Set a maximum cost per run in the run options if you want a hard cap.
- Start the run. Rows appear in the Output tab as they arrive.
- Export the dataset as JSON, CSV or Excel, or connect an integration.
| Input field | Type | Description |
|---|---|---|
locations | array | Places to search, for example "Paris", "Times Square New York" or "resorts in Cancun". A plain place name is searched as "hotels in <place>". Each location returns up to 'Max hotels' hotels per check-in date, with Google's lowest price, rating, class, amenities and coordinates. |
maxHotels | integer | Hotels to return for each location and check-in date, 1 to 500, for example 50. Google lists about 20 per page; sort and filters are applied by Google before this cap. |
checkInDates | array | Check-in dates as YYYY-MM-DD, or relative to today such as "+30d", "6 weeks" or "tomorrow". Example: ["2026-12-10", "+45d"]. Up to a year ahead. If this and the range below are empty, one stay 30 days from now is used. |
nights | array | Lengths of stay in nights, for example [1, 3, 7]. Each value gives its own row per hotel and check-in date. 1 to 30 nights; default [1]. |
language | string | Google interface language (hl), for example en, de, fr or pt-BR. Sets the language of descriptions and deal labels. |
country | string | Country of the searcher (gl), two letters, for example us, gb or de. Not the destination: it can change which booking sites appear and whether prices include taxes. |
Example input:
{
"locations": [
"Paris"
],
"maxHotels": 20,
"checkInDates": [
"+30d"
],
"nights": [
2
],
"language": "en",
"country": "us"
}
2. Over the Apify API
The synchronous endpoint runs the actor and returns its rows in one call (for runs up to about five minutes; use the asynchronous run endpoint for longer ones).
curl -X POST "https://api.apify.com/v2/acts/arcadium~google-hotels/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"locations":["Paris"],"maxHotels":20,"checkInDates":["+30d"],"nights":[2],"language":"en","country":"us"}'
3. From JavaScript
// npm install apify-client
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('arcadium/google-hotels').call({
"locations": [
"Paris"
],
"maxHotels": 20,
"checkInDates": [
"+30d"
],
"nights": [
2
],
"language": "en",
"country": "us"
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
4. From Python
# pip install apify-client
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("arcadium/google-hotels").call(run_input={
"locations": ["Paris"],
"maxHotels": 20,
"checkInDates": ["+30d"],
"nights": [2],
"language": "en",
"country": "us",
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
5. In n8n
Paste this node into a workflow (it is a plain HTTP Request node). Create a Header Auth credential with name Authorization and value Bearer <APIFY_TOKEN>; each returned row becomes one item for the next node.
{
"nodes": [
{
"name": "Run arcadium/google-hotels",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
0,
0
],
"parameters": {
"method": "POST",
"url": "https://api.apify.com/v2/acts/arcadium~google-hotels/run-sync-get-dataset-items",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "{\"locations\":[\"Paris\"],\"maxHotels\":20,\"checkInDates\":[\"+30d\"],\"nights\":[2],\"language\":\"en\",\"country\":\"us\"}",
"options": {
"timeout": 300000
}
}
}
],
"connections": {}
}
6. From an AI assistant (MCP)
Add Apify’s MCP server to Claude Desktop, Cursor, VS Code or any MCP client, limited to this actor:
{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com/?tools=arcadium/google-hotels",
"headers": {
"Authorization": "Bearer <APIFY_TOKEN>"
}
}
}
}
More on the MCP page.
7. From LangChain
# pip install langchain-apify (reads APIFY_API_TOKEN from the environment)
from langchain_apify import ApifyActorsTool
tool = ApifyActorsTool("arcadium/google-hotels")
rows = tool.invoke({"run_input": {
"locations": ["Paris"],
"maxHotels": 20,
"checkInDates": ["+30d"],
"nights": [2],
"language": "en",
"country": "us",
}})
# or give `tool` to an agent: create_react_agent(llm, [tool])
Sample output
One row, from the example in the actor’s README. Long text is shortened and lists are cut to two items.
{
"rowType": "hotel",
"platform": "google-hotels",
"entityId": "ChoI_uTZsvz1i6-bARoNL2cvMTFmZHB6eDEwMxAB",
"name": "The Originals Boutique, Hôtel Maison Montmartre, Paris",
"googleUrl": "https://www.google.com/travel/hotels/entity/ChoI_uTZsvz1i6-bARoNL2cvMTFmZHB6eDEwMxAB",
"propertyType": "hotel",
"hotelClass": 4,
"rating": 4,
"reviewCount": 2133,
"latitude": 48.900537,
"longitude": 2.336269,
"amenities": [
"Free Wi-Fi",
"Air conditioning"
],
"checkIn": "2026-11-10",
"checkOut": "2026-11-12",
"nights": 2,
"adults": 2,
"currency": "USD",
"available": true,
"pricePerNight": 81.75,
"totalPrice": 163.5,
"pricesIncludeTaxes": true,
"priceBeforeTaxes": 136.25,
"taxesAndFees": 27.25,
"deal": "30% less than usual",
"dealPercent": 30,
"searchLocation": "Paris",
"searchRank": 1,
"totalResults": 15000
}
| Field | What it holds |
|---|---|
rowType | Kind of row. Filter on this first. 'hotel': one hotel for one stay (charged as 'hotel'). 'offer': one booking site's price for one hotel and stay (charged as 'offer'). 'error': an input or date could not be read; see code and message (free). |
platform | Always 'google-hotels'. |
entityId | Google Hotels entity token of the property (the Ch... id in its link). Use it in 'hotels' to price the same hotel again. |
name | Hotel row: property name as Google shows it. |
hotelName | Offer row: name of the hotel the offer belongs to. |
googleUrl | Google Hotels page of the property. |
propertyType | 'hotel' or 'vacation_rental'. |
hotelClass | Star class 1-5; null when the property has none (hostels, rentals). |
hotelClassLabel | Class as Google words it, e.g. '4-star tourist hotel'. |
rating | Google guest rating out of 5. |
reviewCount | Number of Google reviews behind the rating. |
latitude | Latitude of the property. |
longitude | Longitude of the property. |
address | Street address of a hotel (hotel lookups and includeOffers only; never for vacation rentals). |
countryCode | Two-letter country code of the property. |
description | Google's one-line summary of the property. |
thumbnailUrl | Small photo of the property. |
website | The property's own website link, when Google has one. |
amenities | Amenities Google lists on the result card, e.g. 'Free Wi-Fi', 'Pool', 'Spa'. Empty on hotel lookups. |
amenityCodes | Google's numeric amenity codes behind 'amenities' (some codes have no label yet). |
checkInTime | Hotel check-in time, e.g. '3:00 PM'. |
checkOutTime | Hotel check-out time, e.g. '12:00 PM'. |
checkIn | Check-in date of the stay, YYYY-MM-DD. |
checkOut | Check-out date of the stay, YYYY-MM-DD. |
nights | Length of the stay in nights. |
adults | Adults in the room. |
children | Number of children in the room. |
childrenAges | Ages of the children in the room. |
currency | ISO currency code of every price in the row. |
available | Hotel row: true when Google shows a price for the stay; false = nothing bookable for these dates and guests. |
pricePerNight | Lowest nightly price shown (hotel row) or this booking site's nightly price (offer row). |
pricePerNightText | The nightly price as displayed, e.g. '$134'. |
totalPrice | Price of the whole stay as Google shows it; see pricesIncludeTaxes. |
pricesIncludeTaxes | true when the shown prices include taxes and fees, false when they do not, null when unclear. Google decides this per market and currency. |
totalPriceWithTaxes | Hotel row: stay total including taxes and fees, from Google's price split. |
priceBeforeTaxes | Hotel row: stay total before taxes and fees. |
taxesAndFees | Hotel row: taxes and fees for the stay (totalPriceWithTaxes minus priceBeforeTaxes). |
deal | Google's deal note, e.g. '30% less than usual' or 'GREAT PRICE for a 4-star hotel'. |
dealPercent | The percentage in the deal note, e.g. 30. |
offerCount | Hotel row: booking sites with a price for the stay; null when offers were not read. |
lowestOfferProvider | Hotel row: booking site with the lowest total, when offers were read. |
searchLocation | The location text this row was found with; null for hotel lookups. |
searchRank | Position in Google's result list for the location (1 = first). |
totalResults | Google's estimate of all properties matching the location search. |
input | Hotel lookups: the link, token or name you gave. |
offerRank | Offer row: 1 = cheapest booking site for this hotel and stay. |
provider | Offer row: booking site name, e.g. 'Booking.com', 'Expedia.com', or the hotel itself for its official site. |
providerId | Offer row: Google's numeric id of the booking site (stable across hotels). |
isOfficialSite | Offer row: true when the offer is the hotel's own website. |
featured | Offer row: shown in the highlighted block at the top of Google's price list. |
freeCancellation | Offer row: true / false when Google states it for the site's lowest rate; null when it does not say. |
freeCancellationUntil | Offer row: last day to cancel for free, YYYY-MM-DD. |
freeCancellationUntilTime | Offer row: time of day of the free-cancellation deadline, when given. |
roomName | Offer row: cheapest room of this site, when Google lists rooms (featured sites). |
rateCount | Offer row: room rates Google lists for this site; 0 when it shows only the lowest. |
cheapestFreeCancellationPrice | Offer row: lowest nightly price among this site's free-cancellation rates, when rooms are listed. |
scrapedAt | When the row was read (ISO 8601). |
code | Error row: invalid_input, not_found, no_match, blocked or unavailable. Retry blocked and unavailable later; the others will fail again with the same input. |
message | Error row: what went wrong, in plain words. |
Schedule it
In Apify Console, create a Task from your input and add a Schedule (for example daily). Each run writes a new dataset; integrations can push the rows to Google Sheets, Slack, a webhook or your database.