# Google Hotels Scraper - $1.50 / 1000 Hotels (`scrapeunblocker/google-hotels-scraper`) Actor

Scrape Google Hotels as clean JSON: hotel and rental prices per night and total with taxes, rating, reviews, stars, amenities, deals, location and photos for any city and dates, plus every booking site's offer per hotel. No login. $1.50 per 1000 hotels.

- **URL**: https://apify.com/scrapeunblocker/google-hotels-scraper.md
- **Developed by:** [Scrapeunblocker](https://apify.com/scrapeunblocker) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 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

## Google Hotels Scraper

Scrape **Google Hotels** as clean, structured JSON - every hotel and vacation rental Google lists for a search, with the **price for your dates** (per night and for the whole stay, before and after taxes), Google's **deal badges**, the **rating** with its **star breakdown** and what guests talk about, the **hotel class**, **amenities**, **location**, **nearby places** and **photos**. Turn on booking-site offers to also get **every booking site's price** for each hotel - the official site, Booking.com, Expedia, Agoda and more - with **room rates** and **free-cancellation deadlines**. Any city, dates, guests, currency and market. No Google account, API key or proxies to set up.

### Features

- **Any search** - a city or area ("hotels in Paris"), a landmark ("hotels near Times Square") or a hotel name; hotels in Google's order (`position`), up to 100 per search.
- **Your stay** - check-in and check-out dates, adults and children's ages. Leave the dates empty for Google's default dates.
- **Prices you can compute with** - `price.perNight`, `price.perNightWithTaxes`, `price.total`, `price.totalWithTaxes` and `price.taxes` as numbers, `currency` as an ISO 4217 code, plus Google's own price text.
- **Deals** - Google's badge (`great_deal` or `deal`) with how far below the usual price it is.
- **Ratings** - rating, review count, the 5-to-1 star breakdown and review topics (what guests mention, with positive and negative counts).
- **Hotel facts** - class and stars, amenities, description, website, coordinates, nearby places with travel times, photos and a Google Maps link.
- **Booking-site prices** - with `includeOffers`, or by property token: the price on every booking site for the stay, the hotel's official site flagged, a link to book, room-level rates and free-cancellation deadlines.
- **Any market and language** - `currency`, `country` (market) and `language`.

### Use cases

- **Rate shopping** - track your hotel's and your competitors' prices on Google for future dates, on a schedule.
- **Rate parity checks** - compare the official-site price with Booking.com, Expedia and the other sites for the same stay.
- **Travel products** - feed comparison sites and apps with hotels, prices, ratings and photos.
- **Market research** - price levels, ratings and supply by city, star class and season.
- **Lead lists** - hotel names, websites, phone numbers and addresses for a destination.

### Input

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `searches` | array | - | Google Hotels searches, e.g. `hotels in Paris` (one search each). An empty input runs one example search. |
| `propertyTokens` | array | - | `propertyToken` values from earlier results: one item per hotel with every booking site's price and room rates. |
| `checkIn` | string | - | Check-in date, `YYYY-MM-DD`. Set together with `checkOut`. |
| `checkOut` | string | - | Check-out date, `YYYY-MM-DD` (stays of up to 30 nights). |
| `adults` | integer | `2` | Number of adults (1-10). |
| `children` | string | empty | Children's ages, comma-separated, e.g. `7,10` (up to 6). |
| `currency` | string | `USD` | Price currency, ISO 4217. |
| `language` | string | `en` | Language of names, amenities and price texts. |
| `country` | string | `us` | Market, as an ISO-2 code. |
| `maxResultsPerSearch` | integer | `20` | Hotels to collect per search (1-100). |
| `includeOffers` | boolean | `false` | Also fetch every booking site's price and the room rates for each hotel found by a search. |
| `concurrency` | integer | `3` | Calls run at the same time (1-5). |

#### Example input

```json
{
  "searches": ["hotels in Lisbon", "hotels near Times Square"],
  "checkIn": "2026-12-04",
  "checkOut": "2026-12-06",
  "adults": 2,
  "children": "7",
  "currency": "EUR",
  "maxResultsPerSearch": 40,
  "includeOffers": true
}
```

### Output

One dataset item per hotel (trimmed):

```json
{
  "position": 1,
  "search": "hotels in Paris",
  "source": "search",
  "name": "Courtyard by Marriott Paris Gare de Lyon",
  "type": "hotel",
  "propertyToken": "ChkIh_ig59yqmq16Gg0vZy8xMWY2Y3IybmpqEAE",
  "hotelClass": "4-star tourist hotel",
  "stars": 4,
  "rating": 4.4,
  "reviews": 1748,
  "price": {
    "display": "$177",
    "displayIncludesTaxes": false,
    "perNight": 176.89,
    "perNightWithTaxes": 192.67,
    "total": 176.89,
    "totalWithTaxes": 192.67,
    "taxes": 15.78,
    "perNightWithTaxesDisplay": "$193",
    "totalWithTaxesDisplay": "$193"
  },
  "deal": null,
  "currency": "USD",
  "checkIn": "2026-11-01",
  "checkOut": "2026-11-02",
  "nights": 1,
  "adults": 2,
  "children": [],
  "amenities": ["Breakfast ($)", "Wi-Fi ($)", "Parking ($)", "Air conditioning", "Fitness center", "Bar", "Restaurant", "Full-service laundry"],
  "amenityCodes": [165, 30, 17, 2, 8, 4],
  "description": "Modern hotel featuring streamlined quarters, some with city views, plus dining & a fitness center.",
  "website": "https://www.marriott.com/en-us/hotels/pargl-courtyard-paris-gare-de-lyon/overview/",
  "latitude": 48.8450789,
  "longitude": 2.3712402,
  "country": "FR",
  "ratingsBreakdown": [
    {"stars": 5, "percent": 67, "count": 1144},
    {"stars": 4, "percent": 21, "count": 372}
  ],
  "reviewTopics": [
    {"name": "Transit", "fullName": "Public transit", "mentions": 164, "positive": 132, "negative": 8, "sentiment": 0.551},
    {"name": "Service", "fullName": "Service", "mentions": 341, "positive": 274, "negative": 52, "sentiment": 0.504}
  ],
  "nearbyPlaces": [
    {"name": "Gare de Lyon", "kind": "transit", "travel": [{"mode": "walking", "duration": "4 min"}]},
    {"name": "Aéroport de Paris-Charles de Gaulle", "kind": "airport", "travel": [{"mode": "taxi", "duration": "36 min"}, {"mode": "public_transport", "duration": "45 min"}]}
  ],
  "thumbnail": "https://lh3.googleusercontent.com/grass-cs/AABkmLfAu90-EOyWr0kxX5i3BCDM792e...",
  "images": ["https://lh3.googleusercontent.com/grass-cs/AABkmLfAu90-EOyWr0kxX5i3BCDM792e..."],
  "mapsCid": "8816475037762075655",
  "mapsUrl": "https://maps.google.com/?cid=8816475037762075655",
  "hotelId": "11395465993892876298",
  "url": "https://www.google.com/travel/hotels/entity/ChkIh_ig59yqmq16Gg0vZy8xMWY2Y3IybmpqEAE?hl=en&gl=us",
  "market": "us",
  "language": "en"
}
```

With `includeOffers`, each hotel also carries its booking options (trimmed):

```json
{
  "name": "River Palace Hotel",
  "search": "hotels in Rome",
  "offersCollected": 20,
  "address": "Via Flaminia, 33, 00196 Roma RM",
  "phone": "06 830011",
  "offers": [
    {
      "provider": "River Palace Hotel",
      "official": true,
      "link": "https://www.google.com/travel/lodging/clk?pc=AA80Osxi8m4pjzo...",
      "partnerUrl": "https://www.blastnessbooking.com/GoogleBooking.php?order=asc...",
      "perNight": 198.5,
      "total": 397.0,
      "perNightDisplay": "€199",
      "totalDisplay": "€397"
    },
    {
      "provider": "Amimir.com",
      "official": false,
      "link": "https://www.google.com/travel/lodging/clk?pc=AA80Osy5inbrK4M...",
      "partnerUrl": "https://www.amimir.com/en/book/?start=04%2F12%2F2026&end=06%...",
      "perNight": 133.5,
      "total": 267.0,
      "perNightDisplay": "€134",
      "totalDisplay": "€267"
    }
  ],
  "rooms": [
    {
      "name": "Classic Double Room",
      "rates": [
        {"provider": "Booking.com", "perNight": 195.5, "total": 391.01, "totalDisplay": "€391", "freeCancellation": false, "freeCancellationUntil": null}
      ]
    }
  ]
}
```

An item from `propertyTokens` has the same hotel fields plus `address`, `phone`, `about`, `placeId`, `offers`, `rooms`, `offersCollected` and the token in `input`.

Searches and property tokens that return nothing or cannot be run go to the `ERRORS` record in the run's key-value store, with the reason. They are not billed. A hotel whose booking options cannot be fetched is still delivered, with an `offersError` field, and is not charged for offers.

### Pricing

**$1.50 per 1000 hotels** (pay per result) - one dataset item is one hotel from a search, or one hotel from a property token. With `includeOffers`, each hotel that gets its booking-site prices is also charged the `hotel-offers` event: **$2.00 per 1000** ($3.50 per 1000 hotels in all). Failed searches, unknown tokens and failed offers calls are free.

### Notes

- Google Hotels shows about 20 hotels per results page; a `maxResultsPerSearch` above 20 reads the following pages, up to 100 hotels per search.
- A search naming one hotel returns just that hotel, marked `matchedProperty: true`.
- A search Google cannot place falls back to hotels around the request's origin; such items carry a warning in `warnings`, so name the city or area in the search.
- The `WithTaxes` price fields are null when Google shows a single price (in many markets prices already include taxes); `price.displayIncludesTaxes` says what Google's headline price includes.
- Booking sites follow the market (`country`): for example a `us` market lists Expedia.com and a `ca` market Expedia.ca.
- Room rates are listed for the hotels where Google shows them.
- Powered by [ScrapeUnblocker](https://www.scrapeunblocker.com).

# Actor input Schema

## `searches` (type: `array`):

What to search on Google Hotels, one search per line: a city or area ('hotels in Paris', 'Lisbon'), a landmark ('hotels near Times Square') or a hotel name (that one hotel). Each search returns up to 'Max hotels per search' hotels and vacation rentals.

## `propertyTokens` (type: `array`):

Optional. The propertyToken of hotels from earlier results: one item per hotel with every booking site's price (official site, Booking.com, Expedia...) and room rates for your dates. Clear the searches above if you only want these hotels.

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

YYYY-MM-DD. Set together with the check-out date. Leave both empty for Google's default dates (one night that Google picks).

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

YYYY-MM-DD, after the check-in date. Stays of up to 30 nights, starting within 330 days.

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

Number of adults (1-10).

## `children` (type: `string`):

Ages of the children, comma-separated, e.g. '7,10' (up to 6 children, ages 0-17). Leave empty for none.

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

Price currency as an ISO 4217 code, e.g. USD, EUR, GBP, JPY.

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

Language of names, amenities and price texts, e.g. 'en', 'de', 'fr', 'ja'.

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

Market as an ISO-2 country code, e.g. 'us', 'gb', 'de'. Google lists the booking sites of this market.

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

How many hotels to collect for each search (1-100). Google shows about 20 per results page; more are read page by page.

## `includeOffers` (type: `boolean`):

For every hotel found by a search, also fetch its booking options: the price on every booking site Google lists (official site, Booking.com, Expedia...) and the room rates. One extra call per hotel, charged as the hotel-offers event.

## `concurrency` (type: `integer`):

How many calls to run at the same time (1-5).

## Actor input object example

```json
{
  "searches": [
    "hotels in Paris"
  ],
  "adults": 2,
  "children": "",
  "currency": "USD",
  "language": "en",
  "country": "us",
  "maxResultsPerSearch": 20,
  "includeOffers": false,
  "concurrency": 3
}
```

# Actor output Schema

## `results` (type: `string`):

One item per hotel or vacation rental with prices for the stay, rating, class, amenities and location; with booking-site offers when asked for

## `errors` (type: `string`):

Searches and property tokens that returned nothing or could not be run, and hotels whose offers could not be fetched, with the reason (not billed)

# 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 = {
    "searches": [
        "hotels in Paris"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapeunblocker/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 = { "searches": ["hotels in Paris"] }

# Run the Actor and wait for it to finish
run = client.actor("scrapeunblocker/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 '{
  "searches": [
    "hotels in Paris"
  ]
}' |
apify call scrapeunblocker/google-hotels-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapeunblocker/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/pvXDanE6xJV2yVMsr/builds/j6hkJgSLstMrdchhn/openapi.json
