# Google Hotels Scraper — Prices & Booking Site Comparison (`griffie/google-hotels-prices-scraper`) Actor

Google Hotels prices for any city or hotel and dates: nightly and total price, star class, rating, reviews, amenities, coordinates and links, plus optional Booking.com / Expedia / official-site price comparison and date-by-date price tracking. Pay only for hotels with prices.

- **URL**: https://apify.com/griffie/google-hotels-prices-scraper.md
- **Developed by:** [Dustin Griffie](https://apify.com/griffie) (community)
- **Categories:** Travel, E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 hotel listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 — Prices & Booking Site Comparison

Get **Google Hotels** results for any city, neighbourhood or landmark — nightly price, price with taxes, total stay price, star class, guest rating, review count, amenities, address, coordinates, photos and links — and optionally **every booking site's price** for each hotel (Booking.com, Expedia, Hotels.com, Agoda, Trip.com, the hotel's official site…) with direct booking links.

No browser: the Actor talks to the same data endpoint the Google Hotels page uses, so it is fast (about 1,000 hotels in 4 minutes) and cheap to run, with automatic retries and a residential-proxy fallback.

### What you can do

| Use case | How |
|---|---|
| All hotels in a city for your dates, cheapest first | `locations: ["Lisbon, Portugal"]`, `sortBy: "lowest_price"` |
| 4–5 star hotels rated 4.5+ with a pool under €300 | `hotelClass: [4,5]`, `minRating: "4.5"`, `amenities: ["pool"]`, `maxPrice: 300` |
| Compare Booking.com vs Expedia vs official site | `includeOtaPrices: true` (search) or list hotels in `hotels` |
| Track one hotel's price for every night of a month | `hotels: ["Avenida Palace, Lisbon"]`, `checkIn` + `dateRangeEnd`, `nights: 1` |
| Rate parity / revenue management for your property and competitors | `hotels` = your property + competitor set, `dateRangeEnd`, `dateStepDays: 7` |
| Families | `adults: 2`, `childrenAges: [4, 9]` |
| Any currency / market | `currency: "JPY"`, `country: "jp"` |

### How to scrape Google Hotels

1. Click **Try for free** and enter one or more cities or areas (for example `Austin, TX`), or hotel names or Google Hotels links.
2. Pick check-in and check-out dates, guests and currency. Add filters (stars, rating, price, amenities) if you need them.
3. Turn on **booking-site price comparison** if you want Booking.com, Expedia, the official site and others side by side.
4. Click **Start**. Download the results as JSON, CSV or Excel, or get them through the Apify API, integrations or a schedule.

### Input

- **Cities or areas** – one per line. Each place × stay is a search, paginated up to *Max hotels per location* (Google serves ~20 per page).
- **Hotels to price-check** – names (add the city), Google Hotels links or entity ids. One row per hotel × stay with all booking sites.
- **Dates** – check-in / check-out, or a date sweep: *Check-in* → *Repeat until* with *Nights* per stay and a *Step*.
- **Guests, currency, market**, **filters** (price range, stars, minimum rating, amenities, free cancellation, hotels vs vacation rentals, hotels only) and **sort** (relevance, lowest price, highest rating, most reviewed).
- **Amenity filters:** `free_wifi`, `free_breakfast`, `free_parking`, `pool`, `indoor_pool`, `outdoor_pool`, `fitness_center`, `restaurant`, `bar`, `spa`, `beach_access`, `kid_friendly`, `pet_friendly`, `room_service`, `air_conditioning`, `all_inclusive`, `wheelchair_accessible`, `ev_charger`.

Example:

```json
{
  "locations": ["Austin, TX", "Shibuya, Tokyo"],
  "checkIn": "2026-12-04",
  "checkOut": "2026-12-06",
  "adults": 2,
  "currency": "USD",
  "sortBy": "lowest_price",
  "maxResultsPerLocation": 40,
  "includeOtaPrices": true,
  "maxOtaHotelsPerLocation": 10
}
```

### Output

Every row has a `status` and a human-readable `statusMessage`.

**Hotel row** (`recordType: "hotel"`):

```json
{
  "status": "ok", "location": "Austin, TX", "position": 2, "checkIn": "2026-12-04", "checkOut": "2026-12-06", "nights": 2,
  "name": "HomeTowne Studios Austin", "entityId": "ChcIzo2q98CXwpFGGgsvZy8xdGp6OGM5MRAB",
  "pricePerNight": 37, "pricePerNightWithTaxes": 44, "totalPrice": 74, "totalPriceWithTaxes": 88, "currency": "USD",
  "propertyKind": "hotel", "hotelClass": 2, "rating": 2.8, "reviewCount": 852, "reviewsByStars": {"1": 315, "2": 82, "3": 115, "4": 110, "5": 230},
  "amenities": ["Free Wi-Fi", "Free parking", "Air conditioning", "Fitness center", "Kitchen in rooms"],
  "amenitiesNotAvailable": ["Breakfast"],
  "address": "12621 Hymeadow Dr", "latitude": 30.4577, "longitude": -97.7903, "phone": "(512) 331-4747",
  "website": "https://www.redroof.com/…", "checkInTime": "3:00 PM", "checkOutTime": "11:00 AM",
  "description": "Traditional all-suite hotel with kitchenettes…", "thumbnail": "https://lh3.googleusercontent.com/…", "images": ["…"],
  "nearbyPlaces": [{"name": "Austin Aquarium", "travel": [{"mode": "car", "duration": "4 min"}]}],
  "googleMapsCid": "14130573527917797695",
  "googleHotelsUrl": "https://www.google.com/travel/hotels/entity/…?ts=…",
  "cheapestProvider": "Super.com", "cheapestPricePerNightWithTaxes": 44, "officialSitePricePerNightWithTaxes": 59, "providerCount": 21,
  "providers": [{"provider": "Super.com", "pricePerNight": 37, "pricePerNightWithTaxes": 44, "totalPriceWithTaxes": 88, "isOfficialSite": false, "sponsored": false, "bookingUrl": "https://www.super.com/…"}]
}
```

The `cheapest…` / `providers` fields appear when price comparison is on. Hotel lookups (`recordType: "hotel_prices"`) have the same fields plus `hotelInput`.

**Statuses**

| status | meaning | charged |
|---|---|---|
| `ok` | hotel with a price (and, for lookups, at least one booking-site price) | yes |
| `no_price` | Google lists the hotel but has no price for these dates (sold out / not bookable) | no |
| `no_availability` | search or lookup with no priced result | no |
| `invalid` | unknown location, rejected filters, or dates Google ignored | no |
| `not_found` | no Google Hotels property matches the hotel name | no |
| `failed` | still blocked after all retries | no |

Dataset views: **Hotels**, **Booking-site price comparison**, **Price by date**, **Statuses**. Run statistics (success rate, requests, retries, proxy tier, bytes, timings) are in the `RUN_STATS` key-value record.

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

Pay per event. You pay only for results with prices.

| Event | Free / Bronze | Silver and higher |
|---|---|---|
| `hotel-listing` – one hotel row **with a price** | $0.002 | $0.0015 |
| `hotel-prices` – one hotel × stay with **at least one booking-site price** (price comparison or hotel lookup) | $0.005 | $0.004 |
| Actor start | $0.00005 | $0.00005 |

Example: 1,000 priced hotels with no price comparison cost $2.00 on the Free plan. Adding price comparison for 100 of them costs $0.50 more. Apify's free plan includes $5 of monthly usage, which is enough for about 2,500 priced hotels a month.

Unpriced hotels, duplicates and every non-`ok` row are free. The Actor respects your *Max cost per run*: it stops before starting work it can't pay for.

### Tips & limits

- Write places the way you would on Google: `"Austin, TX"`, `"Lisbon, Portugal"`, `"near Times Square"`. Unknown places return an `invalid` row (Google would otherwise silently show hotels from somewhere else).
- Google only prices stays up to ~11 months ahead and at most 30 nights. Past dates are rejected up front.
- Prices are what Google shows to a signed-out visitor in the chosen market (`country`) — member/mobile-only rates may differ, and the set of booking sites varies by hotel, date and market.
- Hotel lookups by name use Google's own match; add the city or paste the Google Hotels link for exact results.
- Family searches (`childrenAges`) return fewer priced hotels, because many rooms can't fit the whole party (in London, 2 adults + 2 kids got prices for about 40% of hotels, against 95% for 2 adults). Unpriced hotels are still listed with status `no_price` and are free.
- Some hotels never show prices on Google, only "Check availability" (for example The Plaza, New York). These come back as `no_availability` / `no_price` and are not charged.
- **Filters work exactly like Google Hotels' own filters.** Every amenity, star class, guest rating, price range, free cancellation and sort option was checked on 2026-10-23 against the request Google's site sends and against the hotels returned. Amenity filters return hotels that have that amenity (the price range applies to the nightly price before taxes). Google's result counts can jump between searches. That is Google, not the Actor.
- Google mixes some **vacation rentals** into hotel results, especially with amenity filters (for example free parking in Miami Beach). Every row has `propertyKind` (`hotel` / `vacation_rental`). Turn on **Hotels only** (`excludeVacationRentals: true`) to drop rentals. Dropped rentals aren't saved or charged.
- The amenity list comes from Google's card/detail data; amenities Google doesn't label are omitted (`amenityCodes` keeps the raw codes).

### FAQ

**Do I need a proxy?** The default Apify datacenter proxy is used first; the Actor switches to residential automatically if Google starts blocking (keep *Fall back to residential* on).

**Is it legal?** The Actor collects publicly available prices. You are responsible for how you use the data; don't collect personal data without a legal basis.

# Actor input Schema

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

One place per line: a city, neighbourhood, airport or landmark, e.g. <code>Lisbon, Portugal</code>, <code>Shibuya, Tokyo</code>, <code>near JFK airport</code>. Each place × stay is one search; results are paginated up to <b>Max hotels per location</b>. Unrecognised places return an <code>invalid</code> status row and are never charged.

## `hotels` (type: `array`):

Optional. One hotel per line: a name (add the city for precision, e.g. <code>Avenida Palace, Lisbon</code>), a Google Hotels link (<code>google.com/travel/hotels/…/entity/…</code>) or an entity id. Each hotel × stay returns one row with every booking site's price (Booking.com, Expedia, the official site…).

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

YYYY-MM-DD. Defaults to 14 days from today. Past dates are rejected (Google would silently swap in its own dates).

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

YYYY-MM-DD. Defaults to check-in + <b>Nights</b>. Max 30 nights.

## `dateRangeEnd` (type: `string`):

Optional. Turns the run into a date sweep: one stay of <b>Nights</b> nights for every check-in date from <b>Check-in date</b> to this date (every <b>Step</b> days). Use it to track a hotel's or a city's prices across a month. Max 90 stays per run.

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

Length of each stay when Check-out is empty or a date range is used.

## `dateStepDays` (type: `integer`):

Only used with a date range: 1 = every day, 7 = same weekday every week.

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

Number of adults. Prices are for the whole party.

## `childrenAges` (type: `array`):

Optional. One age per line (0–17), e.g. <code>4</code> and <code>9</code> for two children.

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

3-letter ISO code: USD, EUR, GBP, JPY, AUD, CAD, INR, …

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

2-letter country code of the Google market to price from (gl), e.g. <code>us</code>, <code>gb</code>, <code>de</code>. Booking sites and taxes shown can differ by market.

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

Hotels or vacation rentals (Google Hotels "Vacation rentals" tab).

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

Same as the Sort menu on Google Hotels.

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

In the selected currency. Leave empty for no minimum.

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

In the selected currency. Leave empty for no maximum.

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

Optional. Only hotels with these star ratings.

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

Only hotels rated at least this on Google.

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

Optional. Only hotels offering all selected amenities.

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

Only offers with free cancellation.

## `maxResultsPerLocation` (type: `integer`):

Google returns ~18–20 hotels per page; the Actor pages until this many are collected or the results run out.

## `includeHotelsWithoutPrice` (type: `boolean`):

Google also lists sold-out / unbookable hotels. They are saved with status <code>no_price</code> and are <b>never charged</b>. Turn off to keep only priced hotels.

## `excludeVacationRentals` (type: `boolean`):

Google mixes some vacation rentals (apartments, condos) into hotel results, especially when amenity filters are used. Turn on to drop them. Skipped rentals are not saved and not charged. Every row also has <code>propertyKind</code> (<code>hotel</code> or <code>vacation_rental</code>).

## `includeOtaPrices` (type: `boolean`):

For the first <b>Max hotels with price comparison</b> hotels of each search, also fetch every booking site's price (Booking.com, Expedia, Hotels.com, the official site…) with direct booking links. Charged as a separate <code>hotel-prices</code> event only when at least one site has a price.

## `maxOtaHotelsPerLocation` (type: `integer`):

Caps the price-comparison lookups per search to control cost.

## `dedupeHotels` (type: `boolean`):

When locations overlap (e.g. "Manhattan" and "New York"), keep each hotel once per stay. Duplicates are never charged.

## `maxConcurrency` (type: `integer`):

Parallel searches. Higher is faster but more likely to be rate-limited.

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

Blocked or failed requests are retried on a fresh IP; failed searches get one more pass at the end of the run.

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

Default Apify datacenter proxy works for most runs; the Actor switches to RESIDENTIAL automatically if Google starts blocking.

## `fallbackToResidential` (type: `boolean`):

Recommended. Only used when the selected proxy keeps getting blocked.

## `debugLog` (type: `boolean`):

Verbose logging.

## Actor input object example

```json
{
  "locations": [
    "Austin, TX"
  ],
  "nights": 1,
  "dateStepDays": 1,
  "adults": 2,
  "currency": "USD",
  "country": "us",
  "propertyType": "hotels",
  "sortBy": "relevance",
  "minRating": "any",
  "freeCancellation": false,
  "maxResultsPerLocation": 40,
  "includeHotelsWithoutPrice": true,
  "excludeVacationRentals": false,
  "includeOtaPrices": false,
  "maxOtaHotelsPerLocation": 10,
  "dedupeHotels": true,
  "maxConcurrency": 4,
  "maxRetries": 6,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "fallbackToResidential": true,
  "debugLog": false
}
```

# Actor output Schema

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

Search results with prices, ratings, amenities, coordinates and links.

## `prices` (type: `string`):

Per-hotel price comparison across booking sites.

## `runStats` (type: `string`):

Counts per status, charged events, retries, proxy tier, bytes and per-task timings.

# 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": [
        "Austin, TX"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("griffie/google-hotels-prices-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 = {
    "locations": ["Austin, TX"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("griffie/google-hotels-prices-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 '{
  "locations": [
    "Austin, TX"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call griffie/google-hotels-prices-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,griffie/google-hotels-prices-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/nWoqpcSzyh7gys8hg/builds/9SbWbhz8VhrnOJGpV/openapi.json
