# Google Hotels Scraper - Prices, Ratings & Amenities (`bao-labs/google-hotel-prices`) Actor

Scrape Google Hotels: nightly and total prices for your dates, rating, review count, star class, amenities, coordinates and website, following Google's result pages (about 20 hotels each) when Google serves them. Pay only for hotels returned. Not affiliated with Google.

- **URL**: https://apify.com/bao-labs/google-hotel-prices.md
- **Developed by:** [Bảo Vương Gia](https://apify.com/bao-labs) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 hotels

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

### What does Google Hotels Scraper do?

**Google Hotels Scraper collects hotel listings and prices from [Google Hotels](https://www.google.com/travel/hotels)** for the locations and dates you choose. Give it a place like `Paris` and a stay like 18-20 November, and get back one row per hotel with the **nightly price, total price for the stay, rating, number of reviews, hotel class (stars), amenities**, coordinates and the hotel's website.

- **More than one page per location**: Google's result pages (about 20 hotels each) are followed automatically when Google serves them. In our tests, 8 of 10 locations reached 100 hotels; two stopped after the first page (see "How reliable is it?").
- **Prices for your dates, number of adults and currency.** Our tests used stays of 1 to 6 nights between November 2026 and February 2027, 16 different currencies and 2 adults. Other numbers of adults have not been tested.
- **You pay only for hotels returned.** A search where Google shows no hotels returns one free notice row.

Run it from Apify Console, call it through the API, schedule it, or connect it to Make, Zapier, Google Sheets and other tools through Apify's integrations.

> This Actor is an independent tool. It is **not affiliated with, endorsed by or sponsored by Google**, and the data is not official Google data: it is what Google Hotels shows publicly on its result pages.

### Who is it for?

- **Rate monitoring and revenue management**: track your own and your competitors' prices for upcoming dates.
- **Travel research and comparison sites**: build hotel lists with prices, ratings and amenities for a destination.
- **Market analysis**: compare price levels, hotel classes and ratings across cities and dates.

### How to scrape Google Hotels

1. Open the **Input** tab.
2. Enter one or more **locations**, e.g. `Paris`, `Shibuya Tokyo` or `hotels near Eiffel Tower`.
3. Pick the **check-in and check-out dates**, the number of **adults** and the **currency**. If you leave both dates empty, the Actor uses a check-in 30 days after the day of the run and a 2-night stay.
4. Set the **country of the location** (recommended, see Tips), e.g. `VN` for Hoi An.
5. Optionally change **Maximum hotels per location** (default 50), then click **Start**. When the run finishes, open the **Output** tab or download the data as JSON, CSV, Excel or HTML.

### Input

| Field | What it does | Default |
|---|---|---|
| `locations` | Where to look for hotels, one per line: a city, an area or a phrase like `hotels near Eiffel Tower`. Required. | – |
| `checkIn`, `checkOut` | Stay dates, `YYYY-MM-DD`; check-out must be after check-in. If both are empty, the Actor uses check-in = 30 days after the day of the run (UTC) and check-out = 2 nights later. Give both or neither: with only one, the search is skipped. | 30 days after the run day, 2 nights |
| `adults` | Number of adult guests; prices depend on it. | `2` |
| `currency` | Currency code for prices, e.g. `USD`, `EUR`, `JPY`. | `USD` |
| `maxResults` | Stop a location after this many hotels (the field accepts up to 1,000; tested up to 100). About 20 hotels per Google page. You may get fewer if Google stops serving pages. | `50` |
| `country` | Two-letter code of the country the locations are in (Advanced, recommended). | empty |
| `language` | Language for texts such as amenities. Tested: `en`, `de`, `es`, `fr`, `it`, `nl`, `pt`, `vi`. | `en` |

Under **Advanced**: `country`, `language`, `maxRetries`, `browserFallback`, `saveFailedPages` and `proxyConfiguration`. The defaults are the recommended settings.

Example input:

```json
{
  "locations": ["Paris", "Rome"],
  "checkIn": "2026-11-18",
  "checkOut": "2026-11-20",
  "adults": 2,
  "currency": "EUR",
  "maxResults": 100
}
```

### Output

Each hotel is one row in the dataset. Download it as **JSON, CSV, Excel or HTML**, or read it through the API.

Example row (a real result from a test run on the Apify platform on 2026-09-29; the list of amenities is shortened here):

```json
{
  "searchQuery": "Paris",
  "checkIn": "2026-11-18",
  "checkOut": "2026-11-20",
  "nights": 2,
  "adults": 2,
  "currency": "USD",
  "position": 1,
  "name": "Bonsoir Madame",
  "priceText": "$289",
  "pricePerNight": 288.64,
  "pricePerNightWithTaxesText": "$336",
  "totalPrice": 671.38,
  "rating": 4.8,
  "reviewCount": 693,
  "hotelClass": 4,
  "hotelClassText": "4-star tourist hotel",
  "amenities": [
    "Breakfast ($)",
    "Free Wi-Fi",
    "Air conditioning",
    "Pet-friendly",
    "Parking",
    "Bar"
  ],
  "amenityCodes": [
    "165",
    "29",
    "2",
    "18",
    "-15",
    "4"
  ],
  "latitude": 48.8469145,
  "longitude": 2.3316855,
  "website": "http://www.bonsoirmadame.paris/",
  "googleEntityId": "ChkI4Juc4da-yqEBGg0vZy8xMWo4emNqNW02EAE",
  "scrapedAt": "2026-09-29T20:25:41.979Z"
}
```

#### Data fields

| Field | Description |
|---|---|
| `name` | Hotel name |
| `priceText` / `pricePerNight` | Nightly price as shown, and as a number |
| `pricePerNightWithTaxesText` | Nightly price with taxes and fees, only when the price Google shows first excludes them (`null` otherwise) |
| `totalPrice` | Price for the whole stay, taxes and fees included, in your currency |
| `rating` / `reviewCount` | Guest rating (out of 5) and number of reviews |
| `hotelClass` / `hotelClassText` | Star class, when the hotel has one |
| `amenities` | Amenities as words, in the language you chose |
| `amenityCodes` | Google's amenity codes, for matching across languages |
| `latitude`, `longitude` | Coordinates |
| `website` | The hotel's own website, when Google lists one |
| `googleEntityId` | Google's id for the hotel |
| `searchQuery`, `checkIn`, `checkOut`, `nights`, `adults`, `currency`, `position` | The search the row came from and the hotel's position in it |
| `notice`, `message` | Only on notice rows (see the FAQ). A notice row is not a hotel. |

### How reliable is it?

Figures from our own test runs on the Apify platform between 2026-09-29 and 2026-10-02. They describe those runs, not a guarantee.

- **50 test runs with 50 different locations** (30 popular, 20 small or remote) in 28 countries and 8 languages: **50 of 50 runs completed without error.** 49 returned hotels (938 hotels in total, 17 to 20 per run, because these runs read only the first Google page). For the 50th, Google Hotels itself shows "no results", also in a normal browser; the run returned a notice. Countries and languages we did not test may behave differently.
- **Depth**: 10 locations with the limit set to 100 hotels: **8 returned 100 unique hotels** (6 or 7 Google pages each). Barcelona returned 20 and Sydney 18, each from a single page, and we have not established why those two stopped early. Later runs went further: with the limit at 50 and default settings (2026-09-30), Barcelona returned 50 hotels over 4 pages and Sydney 50 over 3 pages; with the limit at 40 (2026-10-01/02), Barcelona returned all 40 over 3 pages. When Google stops serving pages the Actor stops without a notice, so a run can return fewer hotels than your limit. We cannot promise that a search always reaches it: Google decides how many pages it serves.
- **Completeness** over the 838 hotels from those 10 locations: price 91%, rating and review count 98%, amenities 94%, star class 69%. Missing values are fields Google did not show, for example a hotel with no availability for your dates or a guesthouse with no star class (see the next point).
- **Checked by eye**: on 10 saved result pages (191 hotels, the first page of each search), every missing price, rating, review count and amenity list (12 values) was also missing from Google's own hotel card. None was misread. Star class, coordinates and website were not checked this way, and the other 747 hotels of those runs were not checked by eye.

### How much does it cost to scrape Google Hotels?

This Actor uses **pay-per-event** pricing: you pay for each hotel returned, plus a fee for each run.

| | Price |
|---|---|
| Per hotel returned | $0.002 ($2 per 1,000 hotels) |
| Per run (start fee) | $0.00005 with the default 1,024 MB of memory |

- A search where Google shows no hotels costs **no hotel fees**: it returns one notice row, and notice rows are never charged.
- The start fee is charged once per GB of run memory (minimum once): $0.00005 per GB. With the default 1,024 MB it is $0.00005 per run.
- You can set a **maximum cost per run** in the run options. The limit includes the start fee. We checked this with automated tests and with real runs on Apify: with a limit of the start fee plus 5 hotels, the run stopped at exactly 5 hotels. When the limit is reached the Actor stops and keeps the hotels already paid for. It can go over by at most 1 hotel, because of how the Apify library counts charges.

### Tips

- **Set the country of the location.** Google places some locations only when asked from inside their country. In our tests "Hoi An" returned no hotels when asked from a US address and 18 hotels when asked from a Vietnamese one. With `country` set, the scraper asks from that country.
- **Be specific** with ambiguous names: `Paris France` or `Paris Texas`.
- Prices are the ones Google shows **for your dates and number of adults**; change them to compare.

### Limitations

- **The location's country matters.** Without the right `country`, some locations come back empty (see Tips).
- **European locations are searched from a non-European address.** Google shows a cookie-consent page instead of results to European addresses, so for locations in the EU, UK, Norway, Iceland, Liechtenstein and Switzerland the scraper asks from the United States. The currency is the one you choose. In our test for Paris, prices seen from the US and from Japan were identical for 7 of 7 hotels; from Canada, 3 of 7 differed by less than 6%. We did not compare other cities.
- **Fields Google does not show are left empty.** Most often this is the price (the hotel has no availability for your dates), the star class, or the rating of a new listing. Nothing is guessed or filled in.
- Street addresses are not included.
- **The browser route reads only the first page.** Pages after the first are followed over plain HTTP. If Google sends a page that loads its hotels with JavaScript, the Actor opens it in a browser and returns only that page's hotels (about 20); it does not follow further pages there. In our tests this happened in 1 of 50 runs, a place where Google showed no results. We have never met a case where the browser was needed to read a real hotel list; when we opened pages in the browser on purpose, it returned 20 of 20 hotels for Tokyo, Paris and Da Nang, and 5 of 5 requested for Hoi An.
- **You may get fewer hotels than your limit.** Google decides how many result pages it serves, and the Actor does not report it when they stop early (see Depth above).
- Each search returns the hotels Google lists for that place and dates. It does not check a specific hotel's own booking site.

### FAQ

**Is it legal to scrape Google Hotels?**
This Actor reads only **publicly available hotel information and prices**: what anyone sees on Google Hotels without logging in. It collects business information about hotels, not personal data about people. You are responsible for using the data in line with the laws that apply to you and with the terms of the sites involved.

**Is this an official Google API?**
No. The Actor is independent and not affiliated with Google. It reads the public Google Hotels result pages.

**Why is `totalPrice` different from `pricePerNight` × nights?**
`totalPrice` includes taxes and fees. `priceText` / `pricePerNight` are the nightly price Google shows first, which in some places excludes taxes and fees. When it does, `pricePerNightWithTaxesText` holds the nightly price with them (for the Paris example above, $336 × 2 nights is about the $671.38 total).

**What does a notice row mean?**
A row with a `notice` field is not a hotel. `GOOGLE_NO_RESULTS` means Google Hotels shows no results for that search. Check the spelling, or set the location's country. Notice rows are never charged.

**Something not working?**
Open an issue in the **Issues** tab with the run link, and we will look into it. For a custom data solution, reach out through the same tab.

# Actor input Schema

## `locations` (type: `array`):

Where to look for hotels, one location per line, as you would type it into Google Hotels: a city ("Paris"), an area ("Shibuya Tokyo") or a phrase ("hotels near Eiffel Tower"). Be specific with ambiguous names, e.g. "Paris Texas". Each location is searched separately.

## `checkIn` (type: `string`):

First night of the stay, in YYYY-MM-DD format, e.g. 2026-11-18. Prices are the ones Google shows for these dates. Leave both dates empty to use 30 days after the day of the run.

## `checkOut` (type: `string`):

Day you leave, in YYYY-MM-DD format, e.g. 2026-11-20. Must be after the check-in date. Leave both dates empty to stay 2 nights from the default check-in.

## `adults` (type: `integer`):

Number of adult guests (1-12). Prices depend on it. Example: 2.

## `currency` (type: `string`):

Three-letter currency code for the prices, e.g. USD, EUR, GBP, JPY, VND.

## `maxResults` (type: `integer`):

Stop a location after this many hotels (1-1000). Google returns about 20 per page; further pages are fetched automatically. We tested up to 100 per location. You pay only for hotels returned.

## `country` (type: `string`):

Two-letter code of the country the locations are in, e.g. VN for Hoi An. Recommended: Google places some locations only when asked from inside their country, and without it such a search can come back empty (in our test, "Hoi An" returned no hotels from a US address and 18 from a Vietnamese one). Leave empty only for well-known places.

## `language` (type: `string`):

Interface language code for texts such as amenities and star class, e.g. en, de, fr, vi. Example: en.

## `maxRetries` (type: `integer`):

How many times (0-10) a blocked or failed page is retried on a new proxy session.

## `browserFallback` (type: `boolean`):

For some places Google sends a loading page and fetches the hotels with JavaScript. Open only those in a real browser (slower, uses more proxy traffic, returns that page's hotels only). Leave on unless you want such searches to fail.

## `saveFailedPages` (type: `boolean`):

Store the raw HTML of pages that could not be read in the run's key-value store, for troubleshooting. Leave off unless support asks for it.

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

Residential proxy. Leave the country empty to let the scraper choose per search: an IP in the location's country, except the EEA, UK and Switzerland, where a US IP is used because those IPs get a cookie-consent page.

## Actor input object example

```json
{
  "locations": [
    "Paris"
  ],
  "adults": 2,
  "currency": "USD",
  "maxResults": 50,
  "language": "en",
  "maxRetries": 3,
  "browserFallback": true,
  "saveFailedPages": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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 = {
    "locations": [
        "Paris"
    ],
    "currency": "USD",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("bao-labs/google-hotel-prices").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 = {
    "locations": ["Paris"],
    "currency": "USD",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("bao-labs/google-hotel-prices").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 '{
  "locations": [
    "Paris"
  ],
  "currency": "USD",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call bao-labs/google-hotel-prices --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bao-labs/google-hotel-prices"
        }
    }
}
```

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/KagPZ7hqorgU2po4c/builds/hNK8thC4OKCZgtWvH/openapi.json
