# Google Hotels Scraper (`steadyscrape/google-hotels-scraper`) Actor

Hotels and vacation rentals from Google Hotels for any place and stay: price per night and total, rating, reviews, star class, deal label, location, amenities, photos, and optionally each property's address, phone and prices per booking site. Filters, sorting, any currency. No browser, no login.

- **URL**: https://apify.com/steadyscrape/google-hotels-scraper.md
- **Developed by:** [Steady Scrape](https://apify.com/steadyscrape) (community)
- **Categories:** Travel, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 properties

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

## Google Hotels Scraper

Hotels and vacation rentals for any place and stay, straight from the Google Hotels results page: the price per night and the total with taxes and fees, Google's deal label ("31% less than usual"), star class, guest rating with the review count, star distribution and what guests mention, amenities, location, nearby transit and airports, photos, and a link to the property on Google Hotels. Any currency, any market, Google's own filters and sorting, up to 500 results per search. Optionally the property's own page too: street address, phone, one offer per booking site (Booking.com, Expedia, the hotel's own site…) priced for the stay, the review sources and sample reviews. **Every search comes back as rows**, and when Google has nothing the row says why (`no_results`, `invalid`, `blocked`) instead of an empty dataset. You pay only for properties.

No browser, no login, no API key: it reads the page Google serves, paces itself the way Google tolerates, and rotates IPs before Google's wall shows up.

### What you get

One row per property, in Google's order for the sort you chose:

- **The stay's price**: `pricePerNight` and `totalPrice` (with taxes and fees) in `currency` for the exact dates and guests, `priceBeforeTaxes`, `taxesAndFees`, the `deal` label when Google shows one, and `bookingUrl`.
- **The property**: `name`, `type` (hotel or vacation rental), `category` (hotel, hostel, guest\_house, bed\_and\_breakfast…), `hotelClass` (stars), `rating`, `reviewCount`, `ratingDistribution`, `reviewAspects` (what guests mention, with positive and negative counts), `description`, `amenities`, `essentials` (vacation rentals: "Entire apartment", "Sleeps 4", "2 bedrooms"…), `checkInTime`, `website`.
- **Where it is**: `latitude`, `longitude`, `country`, `nearby` (attractions, transit, airport, restaurants with walking, driving and transit times), and `images`.
- **With details** (`includeDetails`): `address`, `phone`, `descriptionLong`, `offers` (provider, per-night and total price, link, whether it is the property's own site) for `offersCheckIn`–`offersCheckOut`, `reviewSources` (Tripadvisor, Trip.com… with their scale and counts) and `reviews` (author, date, rating, text).
- **What was asked**: `searchIndex`, `query`, `place` (the place Google resolved), `propertyType`, `checkIn`, `checkOut`, `nights`, `adults`, `childAges`, `currency`, `market`, `language`, `rank`, `url`, `entityId`, `featureId`, `hotelId`, `scrapedAt`.
- **`status` and `reason`**: `ok`, `no_results`, `invalid` (a stay Google will not price, with the dates it answered instead), or `blocked` (every IP route was refused; unpaid).

### Input

| field | what it does |
|---|---|
| `queries` | One search per entry, as typed on Google Hotels: `hotels in Lisbon`, `Paris 11e`, `near Times Square`. A hotel's name gives that hotel first. |
| `checkIn`, `checkOut` or `nights` | The stay (1–30 nights, up to a year ahead). |
| `adults`, `childAges` | Guests; one age per child. |
| `propertyType` | `hotels` (Google's default tab, which also lists some rentals) or `vacation_rentals`. |
| `sortBy` | `relevance`, `lowest_price`, `highest_rating`, `most_reviewed`. |
| `minRating`, `hotelClass`, `minPrice`, `maxPrice`, `freeCancellation`, `amenities` | Google's own filters, applied in the search. |
| `currency`, `market`, `language` | Prices in this currency for this point of sale; names and labels in this language. |
| `urls` | Searches copied from Google Hotels (links with `q` and `ts`), searched as they are. |
| `maxResultsPerSearch` | Google pages by twenty; the Actor follows the pages up to this many rows (default 20, max 500). |
| `includeDetails` | Fetch each property's own page (one extra request per property). |
| `residentialFallback` | Retry through residential proxies when Google refuses the datacenter IPs. Default on. |

```json
{
    "queries": ["hotels in Lisbon"],
    "checkIn": "2026-11-10",
    "checkOut": "2026-11-13",
    "adults": 2,
    "hotelClass": [4, 5],
    "minRating": "4.0",
    "sortBy": "lowest_price",
    "currency": "USD",
    "maxResultsPerSearch": 40
}
```

### Output example

```json
{
    "searchIndex": 1,
    "status": "ok",
    "reason": null,
    "query": "hotels in Lisbon",
    "propertyType": "hotels",
    "checkIn": "2026-11-10",
    "checkOut": "2026-11-13",
    "nights": 3,
    "adults": 2,
    "childAges": [],
    "currency": "USD",
    "market": "us",
    "language": "en",
    "place": "Lisbon",
    "rank": 1,
    "name": "Iberostar Selection Lisboa",
    "type": "hotel",
    "category": "hotel",
    "hotelClass": 5,
    "hotelClassLabel": "5-star hotel",
    "rating": 4.7,
    "reviewCount": 3815,
    "ratingDistribution": [{ "stars": 5, "percent": 78, "count": 2976 }, { "stars": 4, "percent": 14, "count": 534 }],
    "reviewAspects": [{ "name": "Breakfast", "mentions": 412, "positive": 371, "negative": 27 }],
    "pricePerNight": 128.81,
    "totalPrice": 386.44,
    "priceBeforeTaxes": 338.56,
    "taxesAndFees": 47.88,
    "deal": { "text": "47% less than usual", "level": "great_deal" },
    "bookingUrl": "https://www.google.com/travel/clk/hi?qid=…",
    "latitude": 38.7247, "longitude": -9.1509, "country": "PT",
    "address": "R. Castilho 64, 1250-071 Lisboa, Portugal",
    "phone": "+351 21 585 9000",
    "website": "https://www.iberostar.com/…",
    "checkInTime": "3:00 PM",
    "description": "Polished rooms & suites in a sleek hotel with a rooftop pool, a spa & a restaurant.",
    "descriptionLong": ["A 4-minute walk from Marquês de Pombal metro station…"],
    "amenities": ["Breakfast ($)", "Free Wi-Fi", "Parking ($)", "Pools", "Hot tub", "Air conditioning", "Fitness center", "Spa"],
    "essentials": null,
    "nearby": [{ "name": "Marquês de Pombal", "category": "transit", "times": [{ "mode": "walking", "time": "4 min" }] }],
    "images": ["https://lh3.googleusercontent.com/…"],
    "offers": [{ "provider": "Iberostar Selection Lisboa", "official": true, "perNight": 157.38, "total": 472.14, "url": "https://www.google.com/travel/lodging/clk?…" }],
    "offersCheckIn": "2026-11-10",
    "offersCheckOut": "2026-11-13",
    "reviewSources": [{ "name": "Tripadvisor", "rating": 4.4, "scale": 5, "reviewCount": 943 }],
    "reviews": [{ "source": "Tripadvisor", "author": "…", "when": "2 weeks ago", "rating": 3, "scale": 5, "text": "…" }],
    "entityId": "ChoIy_fo59Ha34akARoNL2cvMTFmeTVnazZ0YxAB",
    "featureId": "0x…:0x…",
    "hotelId": "…",
    "url": "https://www.google.com/travel/hotels/entity/ChoIy_fo59Ha34akARoNL2cvMTFmeTVnazZ0YxAB?hl=en&gl=us&ts=…",
    "scrapedAt": "2026-09-18T12:00:00.000Z"
}
```

### Prices: what to expect

- **`pricePerNight` is the lowest rate Google found for the stay**, as it shows it in the list; `totalPrice` is the whole stay with taxes and fees. Both are for the exact dates and guests you gave.
- **Google prices by point of sale.** Set `market` to the country you would buy from, or the numbers will not match your own browser.
- **A property with no rate for your dates** (sold out, or too far ahead) comes back with its fields and a `null` price, so you still know it exists.
- With details, `offers` lists every booking site Google compares, with the property's own site flagged `official`.

### Use cases

- **Rate monitoring**: schedule a run per place and stay; alert when `pricePerNight` drops or a `deal` appears.
- **Market research**: every hotel of a city with class, rating, review counts and what guests praise or complain about.
- **Hotel leads**: with details, the address, phone and website of every property in an area.
- **Travel apps and content**: feed live prices and photos into a site, a spreadsheet or an agent, with a deep link per property.

### Limits and honesty

- Google's list has about 20 properties per page; the Actor follows the pages (one request each) up to `maxResultsPerSearch`. Google itself stops paging at some point for very large places.
- A query that names one hotel returns that hotel first (unpriced when it has no rate) and its neighbours after it.
- An unknown place makes Google search the `market` country instead: check `place` on the rows.
- Amenities and labels come in the `language` you choose; hotels list the highlights Google shows on their card, vacation rentals their full list.

### Pricing

Pay per event: one `property` event per row with status `ok`, or one `property-with-details` event when `includeDetails` is on. Rows with any other status are free, and so is every request that gave nothing. Set a spending limit on the run and the Actor stops at it.

### Legal

The Actor reads publicly available listings that Google Hotels shows to anyone, without logging in. It stores no personal data beyond the public names on sample reviews. Use the data in line with Google's terms and your local law.

# Actor input Schema

## `queries` (type: `array`):

One search per entry, as you would type it on Google Hotels: a city, an area, a landmark (<code>hotels in Lisbon</code>, <code>Paris 11e</code>, <code>near Times Square</code>). A hotel's name gives that hotel first and its neighbours after it.

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

<code>YYYY-MM-DD</code>. Prices are for this stay.

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

<code>YYYY-MM-DD</code>, after the check-in (up to 30 nights). Or give <b>Nights</b> instead.

## `nights` (type: `integer`):

Instead of a check-out date: the stay's length. 1 when neither is given.

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

No description

## `childAges` (type: `array`):

One age per child (0–17), as Google asks for them.

## `propertyType` (type: `string`):

Google's two tabs. Hotels searches also list some vacation rentals, as the site does.

## `sortBy` (type: `string`):

Google's own sort, applied in the search.

## `minRating` (type: `string`):

No description

## `hotelClass` (type: `array`):

Keep only these classes, e.g. <code>\[4, 5]</code>. Empty: any.

## `minPrice` (type: `integer`):

In the currency below.

## `maxPrice` (type: `integer`):

In the currency below.

## `freeCancellation` (type: `boolean`):

No description

## `amenities` (type: `array`):

Every property must have all of them (Google's own filter).

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

Three-letter code (<code>USD</code>, <code>EUR</code>, <code>GBP</code>).

## `market` (type: `string`):

Two-letter country code (<code>us</code>, <code>de</code>, <code>br</code>). Google prices by point of sale, and an unknown place falls back to this country.

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

Language of names, amenities and deal labels (<code>en</code>, <code>es</code>, <code>pt-BR</code>).

## `urls` (type: `array`):

Searches copied from Google Hotels (links with <code>q</code> and <code>ts</code> parameters). Each is searched as it is, with its own dates, guests, filters and language.

## `maxResultsPerSearch` (type: `integer`):

Google pages by twenty; the Actor follows the pages until this many rows.

## `includeDetails` (type: `boolean`):

One extra request per property: address, phone, the long description, one offer per booking site with per-night and total prices for the stay, review sources and sample reviews. Rows are then charged as <code>property-with-details</code>.

## `residentialFallback` (type: `boolean`):

When Google refuses the run's own IP and the datacenter proxies, retry through residential proxies (included in the price: you pay per row, not per proxy byte). Off: those searches come back with status <code>blocked</code>, unpaid.

## Actor input object example

```json
{
  "queries": [
    "hotels in Lisbon"
  ],
  "checkIn": "2026-11-10",
  "checkOut": "2026-11-13",
  "adults": 2,
  "childAges": [],
  "propertyType": "hotels",
  "sortBy": "relevance",
  "minRating": "any",
  "hotelClass": [],
  "freeCancellation": false,
  "amenities": [],
  "currency": "USD",
  "market": "us",
  "language": "en",
  "maxResultsPerSearch": 20,
  "includeDetails": false,
  "residentialFallback": true
}
```

# Actor output Schema

## `properties` (type: `string`):

No description

## `summary` (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 = {
    "queries": [
        "hotels in Lisbon"
    ],
    "checkIn": "2026-11-10",
    "checkOut": "2026-11-13"
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/google-hotels-scraper").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 = {
    "queries": ["hotels in Lisbon"],
    "checkIn": "2026-11-10",
    "checkOut": "2026-11-13",
}

# Run the Actor and wait for it to finish
run = client.actor("steadyscrape/google-hotels-scraper").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 '{
  "queries": [
    "hotels in Lisbon"
  ],
  "checkIn": "2026-11-10",
  "checkOut": "2026-11-13"
}' |
apify call steadyscrape/google-hotels-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyscrape/google-hotels-scraper"
        }
    }
}
```

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/Xensg0W7ZKrVCcZzE/builds/2eziJzrh0dgXKXXPu/openapi.json
