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

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

## Pricing

from $0.80 / 1,000 results

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?

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

### What does Google Hotels Scraper do?

**Google Hotels Scraper** extracts hotel search results from [Google Hotels/Travel](https://www.google.com/travel/hotels) for any location - **anonymously, no login, no Google account, no browser**. Give it a place (a city, a neighborhood, or a `google.com/travel/hotels` URL) and it returns every hotel and vacation rental Google lists there, with price, star class, rating, review count, and coordinates.

### Why use this Actor?

- **Price comparison** - pull nightly rates for every hotel in a city for your exact stay dates in one shot.
- **Market sizing** - `hotelCount` on the location-summary row tells you how many properties Google lists for a place (often 100+ per city).
- **Multi-city runs** - batch several locations (`locations`) in one run to compare markets side by side.

### How to use it

1. Fill **Location** with a place name (e.g. `"Paris"`, `"Times Square, New York"`) or a full `google.com/travel/hotels/...` URL, or fill **Locations** for a batch.
2. Set **Check-in**/**Check-out** dates (defaults to a rolling 2-night stay starting 2 days out), **Currency**, and **Adults**.
3. Set **Max hotels** to cap the number of rows.
4. Click **Start**.

`locations` wins over `location` when filled; duplicates and blanks are dropped automatically.

### Input

| Field                    | Type           | Description                                                                              |
| ------------------------ | -------------- | ---------------------------------------------------------------------------------------- |
| `location` / `locations` | string / array | A place name or a full `google.com/travel/hotels/...` URL. Batch field wins when filled. |
| `checkIn` / `checkOut`   | string (date)  | `YYYY-MM-DD`. Default to a rolling 2-night stay starting 2 days from today.              |
| `currency`               | string         | 3-letter currency code for returned prices. Default `USD`.                               |
| `adults`                 | integer        | Adult guests per room used for pricing. Default 2.                                       |
| `maxItems`               | integer        | Caps the number of hotel rows produced per run (across all locations). Default 10.       |
| `proxyConfiguration`     | object         | A residential proxy is recommended for reliability at scale (see Limitations).           |

### Output

One flat row per item, distinguished by `kind`:

- `hotel` - one per hotel/vacation rental found for a location.
- `locationSummary` - one per location query, carries the total hotel count found.

Hotel row:

```json
{
    "kind": "hotel",
    "status": "success",
    "query": "New York",
    "name": "The Manhattan at Times Square Hotel",
    "location": "New York",
    "checkIn": "2026-08-31",
    "checkOut": "2026-09-01",
    "propertyType": "hotel",
    "hotelClass": 4,
    "rating": 4.2,
    "reviewCount": 10190,
    "price": "$187",
    "priceAmount": 187,
    "currency": "USD",
    "latitude": 40.7622856,
    "longitude": -73.9826404,
    "mapsUrl": "https://www.google.com/maps/search/?api=1&query=...",
    "propertyToken": "ChkIooCAqvyy0fDgARoML2cvMWhoZ18zbWdzEAE"
}
```

Location summary row:

```json
{
    "kind": "locationSummary",
    "status": "success",
    "query": "New York",
    "location": "New York",
    "checkIn": "2026-08-31",
    "checkOut": "2026-09-01",
    "currency": "USD",
    "hotelCount": 146,
    "hotelsListed": 10
}
```

### How it works

Google's Hotels/Travel UI calls an internal `batchexecute` JSON-RPC endpoint client-side to fetch results. Live-verified 2026-08-28 (with network-traffic logging via a real browser, then replayed from a cold, cookie-less process): a plain HTTP GET of the initial `google.com/travel/hotels/<location>` page returns real, complete HTML with the resolved location's bounding box, display name, and Google place ID (CID) embedded directly in it - no JS execution needed to read them. Those values are then used to build a plain HTTP POST to the same `batchexecute` endpoint Google's own client calls (`rpcids=Ya3XAc`), which returns the full hotel list as nested JSON. This worked with **no cookies, no session, and no BotGuard token** even from a brand-new process, so no browser is used at runtime - this Actor is pure `got-scraping` (the cheapest tier on the escalation ladder). One call typically returns 100+ hotels for a city (146 for New York, 135 for Paris in testing) in a single response.

### Limitations

- **No CAPTCHA/bot-protection was encountered at any point during testing** (unlike this repo's TripAdvisor Actors, which need Camoufox to beat DataDome) - Google's read-only Hotels data endpoint simply doesn't gate on it the way its own client-side BotGuard header would suggest. This could change; a residential proxy is offered as a safety margin but was not required to get real data in testing.
- **Address, amenities, and per-hotel review text are not included.** The `Ya3XAc` list endpoint returns name/price/class/rating/coordinates only - a full address or a paginated review list would need a separate per-hotel detail call this Actor doesn't make.
- **One call per location, not paginated further.** Google's response already returns a large batch (100+ hotels for a major city) in a single call; this Actor does not chase a "load more" continuation token beyond that first batch.
- **Vague or unrecognized locations fail cleanly.** If Google can't resolve the location text to a place (bounding box + CID), the row comes back `status: "error"` with a clear message - it will not silently default to an unrelated location.
- Prices reflect the `currency` you set and Google's own live pricing at fetch time - not guaranteed to match what you'd see at checkout on the booking site Google ultimately routes you to.

### Pricing

This Actor uses pay-per-event pricing - one small run-start charge, then a per-row charge for each hotel row. See the **Pricing** tab for current rates. Failed lookups land as `status: "error"` rows and are never charged.

### FAQ

**Do I need a Google account or API key?** No - it runs entirely against Google's public, logged-out Travel pages and their internal read-only API.

**Why did my location come back `"error"`?** Google couldn't resolve the text you gave it to a specific place. Try a more specific location (e.g. add a country/state) or pass the exact `google.com/travel/hotels/...` URL for that place.

**Can I get individual room rates, not just a headline price?** Not in this version - Google's list endpoint returns one representative nightly price per property, not a full room-type breakdown.

### Disclaimer

This Actor is an independent tool, not affiliated with or endorsed by Google. It only accesses data Google serves publicly, including via its own client-side API calls made from a logged-out browser. Use it in compliance with Google's terms of use and applicable law in your jurisdiction. Found a bug or have a feature request? Use the Issues tab on this Actor's page.

# Actor input Schema

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

A place name (e.g. "Paris", "Times Square, New York") or a full google.com/travel/hotels/... URL. Defaults to a demo location if left blank.

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

Many locations/URLs in one run - e.g. to compare hotel prices across several cities. Wins over "location" when filled.

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

YYYY-MM-DD. Defaults to 2 days from today if left blank.

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

YYYY-MM-DD. Defaults to 4 days from today (a 2-night stay) if left blank.

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

A 3-letter currency code (e.g. USD, EUR, GBP) for the returned prices.

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

Number of adult guests used when pricing each hotel.

## `maxItems` (type: `integer`):

Caps the number of hotel rows produced per run (across all locations). No hard upper limit is enforced beyond what you set here.

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

A residential proxy is recommended for reliability at scale, though this endpoint has been live-verified to work without any proxy at all.

## Actor input object example

```json
{
  "location": "New York",
  "currency": "USD",
  "adults": 2,
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `overview` (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 = {
    "location": "New York",
    "currency": "USD"
};

// Run the Actor and wait for it to finish
const run = await client.actor("mrdoe/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 = {
    "location": "New York",
    "currency": "USD",
}

# Run the Actor and wait for it to finish
run = client.actor("mrdoe/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 '{
  "location": "New York",
  "currency": "USD"
}' |
apify call mrdoe/google-hotels-scraper --silent --output-dataset

```

## MCP server setup

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