# Google Hotels & Vacation Scraper  - Most Comprehensive (`kaix/google-hotels-scraper`) Actor

🔥 ~$0.1/1K hotels 🔥 Scrape Google Hotels and Vacation Rentals with full filter support - price, hotel class, guest rating, amenities, property types, offers, eco-certified. Includes batch searches, booking links, and paginated reviews.

- **URL**: https://apify.com/kaix/google-hotels-scraper.md
- **Developed by:** [Kai](https://apify.com/kaix) (community)
- **Categories:** Lead generation, Travel, Real estate
- **Stats:** 32 total users, 8 monthly users, 67.5% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.09 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Google Hotels & Vacation Rentals Scraper

Collect public Google Hotels and Vacation Rentals search results, property details, prices, reviews, and photos. Run location searches in batches or look up specific Google Hotels entity URLs.

### Why use this scraper?

- Search hotels, vacation rentals, or both
- Run several destinations or stay dates in one Actor run
- Apply hotel price, class, guest-rating, and amenity filters
- Add property details and reviews to search results
- Look up specific hotel entity URLs with details and available gallery photos
- Receive strict dataset records with explicit partial-result status

### Use cases

- Monitor hotel prices across locations and dates
- Compare vacation rental prices across booking platforms
- Build accommodation databases for travel analytics
- Track pricing trends for specific properties or areas
- Feed hotel data into alerting or recommendation pipelines

### How to use

#### Basic hotel search

```json
{
  "searches": [
    { "location": "Hue", "checkInDate": "2026-10-15", "checkOutDate": "2026-10-18" }
  ],
  "type": "hotels"
}
```

#### Vacation rentals only

```json
{
  "type": "vacation_rentals",
  "searches": [
    { "location": "Paris", "checkInDate": "2026-10-15", "checkOutDate": "2026-10-22" }
  ]
}
```

#### Batch searches

```json
{
  "searches": [
    { "location": "Paris", "checkInDate": "2026-10-15", "checkOutDate": "2026-10-18" },
    { "location": "Paris", "checkInDate": "2026-11-12", "checkOutDate": "2026-11-15" },
    { "location": "Tokyo", "checkInDate": "2026-12-03", "checkOutDate": "2026-12-06" }
  ]
}
```

#### With filters

```json
{
  "searches": [
    { "location": "Hue", "checkInDate": "2026-10-15", "checkOutDate": "2026-10-18" }
  ],
  "type": "hotels",
  "maxPrice": 100,
  "currency": "USD",
  "hotelClass": [4, 5],
  "guestRating": "4.0",
  "amenities": ["Pool", "Free Wi-Fi"],
  "sortBy": "price_low",
  "adults": 2,
  "rooms": 1
}
```

#### With details and reviews

```json
{
  "searches": [
    { "location": "Hue", "checkInDate": "2026-10-15", "checkOutDate": "2026-10-18" }
  ],
  "type": "hotels",
  "includeDetails": true,
  "includeReviews": true,
  "maxResults": 10
}
```

#### Lookup specific hotels by URL

```json
{
  "hotelUrls": [
    "https://www.google.com/travel/hotels/entity/ChkIq_atzbv20-8ZGg0vZy8xMXFoMzRoa3pfEAE"
  ],
  "searches": [
    { "location": "Tokyo", "checkInDate": "2026-10-15", "checkOutDate": "2026-10-18" }
  ],
  "currency": "VND",
  "includeReviews": true,
  "maxReviewsPerHotel": 100,
  "reviewSort": "highest_score",
  "maxPhotosPerHotel": 0
}
```

#### Reviews with sorting and search

```json
{
  "hotelUrls": [
    "https://www.google.com/travel/hotels/entity/ChkIq_atzbv20-8ZGg0vZy8xMXFoMzRoa3pfEAE"
  ],
  "searches": [
    { "location": "Tokyo", "checkInDate": "2026-10-15", "checkOutDate": "2026-10-18" }
  ],
  "includeReviews": true,
  "maxReviewsPerHotel": 50,
  "reviewSort": "highest_score",
  "reviewSearch": "breakfast"
}
```

#### Multiple guests

```json
{
  "searches": [
    { "location": "Bali", "checkInDate": "2026-10-15", "checkOutDate": "2026-10-22" }
  ],
  "type": "vacation_rentals",
  "adults": 4,
  "children": 2,
  "rooms": 2
}
```

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `hotelUrls` | string\[] | | HTTPS Google Hotels entity URLs. Starts lookup mode, deduplicated by entity token |
| `searches` | array | | `{ location, checkInDate, checkOutDate }` entries. Required for search mode; lookup uses the first entry's dates |
| `type` | enum | `both` | `hotels`, `vacation_rentals`, `both` |
| `adults` | integer | `2` | Adult guests (1-9) |
| `children` | integer | `0` | Child guests (0-9) |
| `rooms` | integer | `1` | Number of rooms (1-9) |
| `currency` | string | `USD` | Three-letter price currency code, normalized to uppercase |
| `minPrice` | integer | | Minimum price per night in the selected currency |
| `maxPrice` | integer | | Maximum price per night in the selected currency |
| `hotelClass` | integer\[] | | Star levels: `[2, 3, 4, 5]` |
| `guestRating` | enum | | `3.5`, `4.0`, `4.5` |
| `amenities` | string\[] | | `Free Wi-Fi`, `Free breakfast`, `Restaurant`, `Bar`, `Kid-friendly`, `Pet-friendly`, `Free parking`, `Parking`, `EV charger`, `Room service`, `Fitness center`, `Spa`, `Pool`, `Indoor pool`, `Outdoor pool`, `Air-conditioned`, `Wheelchair accessible`, `Beach access`, `All-inclusive available` |
| `sortBy` | enum | `relevance` | `relevance`, `price_low`, `price_high`, `rating` |
| `maxResults` | integer | `50` | Maximum results per location and property type |
| `includeDetails` | boolean | `false` | Add booking links, amenities, descriptions, and related detail data to search results |
| `includeReviews` | boolean | `false` | Add available reviews to each property |
| `maxReviewsPerHotel` | integer | `40` | Maximum reviews per property. `0` continues until no page remains |
| `reviewSort` | enum | `most_helpful` | `most_helpful`, `most_recent`, `highest_score`, `lowest_score` |
| `reviewSearch` | string | | Free-text search within reviews (e.g. `"breakfast"`, `"clean rooms"`) |
| `maxPhotosPerHotel` | integer | `0` | Lookup mode only. `0` continues until no gallery page remains |
| `proxyConfiguration` | object | `{"useApifyProxy":true}` | Optional connection settings managed by Apify |

Hotel-only filters and non-relevance sorting require `type: "hotels"`. Vacation-rental and `both` searches reject those settings instead of ignoring them.

Exact duplicate location-and-date searches are rejected. Non-default guest or room counts are supported for base searches, but cannot be combined with `includeDetails: true` because property-detail prices use the default two-adult occupancy.

When `hotelUrls` is present, lookup mode takes precedence. Property details are required to return a lookup record. After details load, the Actor attempts web results, photo categories, gallery photos, and optional reviews; failures in those optional sections produce a partial record. Search-only filters, sorting, multiple stay entries, occupancy changes, and `maxResults` are rejected in this mode. If `searches` is omitted, lookup uses tomorrow and the following day. Duplicate entity tokens produce one canonical property record.

An empty input is rejected. Provide at least one search or hotel URL.

### Real output

This is the complete, unchanged dataset record from a one-result New York hotel run on July 30, 2026. Property availability and values can change between runs.

```json
{
  "searchType": "hotel",
  "url": "https://www.google.com/travel/hotels/entity/ChYIjrDskJ36j9gtGgovbS8wamtfbnZwEAE",
  "location": "New York",
  "checkInDate": "2026-09-28",
  "checkOutDate": "2026-10-01",
  "name": "Hotel Edison",
  "propertyId": null,
  "placeId": null,
  "starRating": 4,
  "propertyType": null,
  "latitude": 40.7597355,
  "longitude": -73.9861511,
  "distance": null,
  "pricePerNight": 257,
  "totalPrice": 772,
  "currency": "USD",
  "priceLabel": "$257",
  "reviewScore": 3.8,
  "reviewCount": 8462,
  "reviewSource": null,
  "thumbnailUrl": null,
  "photos": [],
  "amenities": [],
  "ecoBadge": false,
  "sleeps": null,
  "bedrooms": null,
  "bathrooms": null,
  "hashId": null,
  "highlights": [],
  "capacity": [],
  "featured": false,
  "phone": null,
  "website": null,
  "countryCode": null,
  "address": null,
  "neighborhood": null,
  "neighborhoodDescription": null,
  "neighborhoodScores": [],
  "ratingDistribution": [],
  "aspectSentiments": [],
  "externalReviewSources": [],
  "bookingLinks": [],
  "description": null,
  "roomTypes": [],
  "checkInTime": null,
  "checkOutTime": null,
  "reviews": [],
  "nearbyHotels": [],
  "sponsoredHotels": [],
  "nearbyVacationRentals": [],
  "nearbyPlaces": [],
  "nearbyBusinesses": [],
  "priceHistory": null,
  "priceBreakdown": null,
  "originalPricePerNight": null,
  "originalTotalPrice": null,
  "reviewSummaryPositive": null,
  "reviewSummaryNegative": null,
  "featuredReviewSnippets": [],
  "locationHierarchy": [],
  "googleCategory": null,
  "inclusivityLabels": [],
  "featuredIn": [],
  "webResults": [],
  "photoCategories": [],
  "dataStatus": "complete",
  "failedSections": []
}
```

### Output

Each property is written to the default dataset as a consistent record. Every top-level field is present. Unavailable values are represented by `null` or an empty array rather than invented values.

`dataStatus` is `complete` when all requested sections finished. It is `partial` when a requested enrichment failed, and `failedSections` names those sections. A complete record can still contain nullable fields when the source has no value.

Search records follow input order. For `type: "both"`, hotels are processed before vacation rentals for each stay. Results within each search use the requested ordering. URL lookups follow the first occurrence of each unique entity token.

#### Core fields

The table summarizes the identity, context, price, and status fields. The Actor dataset schema is the complete machine-readable contract.

| Field | Type | Description |
|---|---|---|
| `searchType` | string | `"hotel"` or `"vacation_rental"` |
| `url` | string | Public Google Hotels property URL |
| `location` | string or null | Search location or resolved lookup location |
| `checkInDate` | string | Check-in date |
| `checkOutDate` | string | Check-out date |
| `name` | string | Property name |
| `propertyId` | string or null | Google property ID when available |
| `placeId` | string or null | Google Place ID when available |
| `starRating` | number or null | Hotel class when available |
| `propertyType` | string or null | Property category |
| `latitude` | number | GPS latitude |
| `longitude` | number | GPS longitude |
| `distance` | string or null | Source-provided distance label |
| `pricePerNight` | number or null | Price per night |
| `totalPrice` | number or null | Total price for the stay |
| `currency` | string | Currency code |
| `priceLabel` | string or null | Source-provided price label |
| `reviewScore` | number or null | Aggregate review score |
| `reviewCount` | integer or null | Aggregate review count |
| `reviewSource` | string or null | Aggregate rating source |
| `thumbnailUrl` | string or null | Property thumbnail |
| `photos` | array | Deduplicated `{ url, label, categoryIds }` entries |
| `amenities` | string\[] | Available amenity names |
| `hashId` | string or null | Source identifier when available |
| `highlights` | string\[] | Source-provided property highlights |
| `capacity` | string\[] | Vacation-rental capacity labels |
| `sleeps` | integer or null | Vacation-rental guest capacity |
| `bedrooms` | integer or null | Vacation-rental bedroom count |
| `bathrooms` | number or null | Vacation-rental bathroom count |
| `featured` | boolean | Featured flag |
| `ecoBadge` | boolean | Eco marker when returned in property details |
| `dataStatus` | string | `"complete"` or `"partial"` |
| `failedSections` | string\[] | Any failed `details`, `reviews`, `webResults`, `photoCategories`, or `photos` sections |

#### Detail and lookup fields

Search mode populates these fields when `includeDetails` is true. Lookup mode always attempts property details. `webResults`, `photoCategories`, and full gallery pagination are lookup-only sections.

| Field | Type | Description |
|---|---|---|
| `address` | string or null | Full street address |
| `phone` | string or null | Phone number |
| `website` | string or null | Hotel website URL |
| `countryCode` | string or null | Country code when available |
| `description` | string or null | Property description |
| `checkInTime` | string or null | Check-in time |
| `checkOutTime` | string or null | Check-out time |
| `amenities` | string\[] | Available amenities with human-readable names |
| `neighborhood` | string or null | Neighborhood name |
| `neighborhoodDescription` | string or null | Short neighborhood description |
| `neighborhoodScores` | array | `{ category, rating }` - 5 neighborhood category scores |
| `ratingDistribution` | array | `{ stars, count }` - star breakdown (5★ through 1★) |
| `aspectSentiments` | array | `{ aspect, score, positive, negative, total }` - e.g. Breakfast, Service, Location |
| `externalReviewSources` | array | `{ source, rating, maxRating, count }` entries |
| `bookingLinks` | array | `{ provider, price, url, logoUrl, isOfficialSite, freeCancellation, freeCancellationDeadline }` |
| `roomTypes` | array | `{ name, price }` - room types with pricing |
| `priceHistory` | object or null | Current and typical price values when available |
| `priceBreakdown` | object or null | Base price, taxes, fees, and total with taxes when available |
| `originalPricePerNight` | number or null | Original nightly price before a displayed discount |
| `originalTotalPrice` | number or null | Original stay total before a displayed discount |
| `reviewSummaryPositive` | string or null | Positive review summary |
| `reviewSummaryNegative` | string or null | Negative review summary |
| `featuredReviewSnippets` | string\[] | Source-provided review snippets |
| `locationHierarchy` | array | Resolved location names and identifiers |
| `googleCategory` | string or null | Source-provided Google category |
| `inclusivityLabels` | string\[] | Source-provided inclusivity labels |
| `featuredIn` | string\[] | Editorial mentions (e.g. `"Featured in Best Hotels in Tokyo with a View"`) |
| `webResults` | array | Related `{ title, url, snippet, domain, favicon }` results |
| `photoCategories` | array | `{ categoryId, name, count, thumbnailUrl }` - photo gallery category summary |
| `nearbyPlaces` | array | `{ name, photoUrl, rating, reviewCount, description, latitude, longitude, category, travelTimes }` - POIs with travel times |
| `nearbyBusinesses` | array | `{ placeId, name, category, rating, reviewCount, phone, website, reservationUrl, photoUrl, priceRange, hours }` |
| `nearbyHotels` | array | Similar hotels (NearbyHotel type) |
| `sponsoredHotels` | array | Sponsored/popular hotels (NearbyHotel type) |
| `nearbyVacationRentals` | array | Nearby vacation rentals (NearbyHotel type) |

#### Review fields

Reviews are populated only when `includeReviews` is true. `maxReviewsPerHotel` applies per property after deduplication.

| Field | Type | Description |
|---|---|---|
| `reviews` | array | Review entries (see below) |

Each review:

| Field | Type | Description |
|---|---|---|
| `source` | string | Review provider |
| `author` | string | Reviewer name |
| `authorUrl` | string or null | Profile URL |
| `avatarUrl` | string or null | Profile photo URL |
| `rating` | number | Rating (1-5) |
| `maxRating` | number | Provider rating scale |
| `text` | string | Full review text |
| `date` | string | Relative date (`"3 months ago"`) |
| `reviewId` | string or null | Provider review ID used for deduplication |
| `reviewUrl` | string or null | Direct review URL when available |
| `subRatings` | array | `{ category, score, maxScore }` entries |
| `photos` | string\[] | Review photo URLs |
| `highlights` | string\[] | Hotel tags (`"Luxury"`, `"Romantic"`, `"Great value"`) |
| `replyText` | string or null | Owner reply text |

### Run outcomes

A valid search with no matches succeeds with an empty dataset. In a batch, one failed search or lookup does not discard successful work; the run logs a warning. The Actor fails when every requested work item fails or when it cannot persist dataset records.

Optional enrichment failures preserve the base property record with `dataStatus: "partial"`. A URL lookup cannot return a record when its required property details are unavailable. Use `failedSections` to decide whether to retry or accept a partial record.

### Responsible use

The Actor collects public accommodation data. Review records can contain names, profile links, photos, and free text. Store only what you need, limit access and retention, and follow the source terms and laws that apply to your use.

# Actor input Schema

## `hotelUrls` (type: `array`):

Google Hotels entity URLs to look up directly. Property details are required; gallery photos are attempted and can be partial.

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

List of location searches to perform. Required unless hotelUrls is provided.

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

What type of properties to search for. Filters and non-relevance sorting currently require Hotels only.

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

Number of adult guests for location searches

## `children` (type: `integer`):

Number of child guests for location searches

## `rooms` (type: `integer`):

Number of rooms for location searches

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

ISO 4217 currency code for prices (e.g. USD, EUR, GBP, VND)

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

Minimum price per night in the selected currency

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

Maximum price per night in the selected currency

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

Star levels to filter by

## `guestRating` (type: `string`):

Minimum guest rating

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

Filter by amenities

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

How to sort search results

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

Maximum results per location and property type

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

Add booking links, amenities, descriptions, and other property details to location-search results. URL lookup requires property details before it can return a record.

## `includeReviews` (type: `boolean`):

Add available reviews to each returned property.

## `maxReviewsPerHotel` (type: `integer`):

Maximum reviews per property. Set to 0 to continue until no more reviews are available.

## `reviewSort` (type: `string`):

How to order collected reviews.

## `reviewSearch` (type: `string`):

Return reviews matching this text.

## `maxPhotosPerHotel` (type: `integer`):

Maximum photos for each hotel URL lookup. Set to 0 to continue until no more photos are available.

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

Optional connection routing settings. Apify Proxy is enabled by default.

## Actor input object example

```json
{
  "hotelUrls": [
    "https://www.google.com/travel/hotels/entity/ChkIq_atzbv20-8ZGg0vZy8xMXFoMzRoa3pfEAE"
  ],
  "type": "both",
  "adults": 2,
  "children": 0,
  "rooms": 1,
  "currency": "USD",
  "sortBy": "relevance",
  "maxResults": 50,
  "includeDetails": false,
  "includeReviews": false,
  "maxReviewsPerHotel": 40,
  "reviewSort": "most_helpful",
  "maxPhotosPerHotel": 1,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Link to the saved hotel and vacation-rental records.

# 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 = {
    "hotelUrls": [
        "https://www.google.com/travel/hotels/entity/ChkIq_atzbv20-8ZGg0vZy8xMXFoMzRoa3pfEAE"
    ],
    "maxPhotosPerHotel": 1,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kaix/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 = {
    "hotelUrls": ["https://www.google.com/travel/hotels/entity/ChkIq_atzbv20-8ZGg0vZy8xMXFoMzRoa3pfEAE"],
    "maxPhotosPerHotel": 1,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("kaix/google-hotels-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "hotelUrls": [
    "https://www.google.com/travel/hotels/entity/ChkIq_atzbv20-8ZGg0vZy8xMXFoMzRoa3pfEAE"
  ],
  "maxPhotosPerHotel": 1,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call kaix/google-hotels-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=kaix/google-hotels-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/H1scmbaCSREtaQDQU/builds/bXsn03YXJ8OLE2zMh/openapi.json
