# Google Travel Hotel Prices (`vittuhy/google-travel-hotel-prices`) Actor

This actor extracts real-time pricing information for a given hotel across multiple dates and provides comprehensive price comparisons from various booking providers.

- **URL**: https://apify.com/vittuhy/google-travel-hotel-prices.md
- **Developed by:** [Vít Tuhý](https://apify.com/vittuhy) (community)
- **Categories:** Travel
- **Stats:** 194 total users, 25 monthly users, 99.9% runs succeeded, 12 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.00 / 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.

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

## Google Travel Hotel Price Scraper

A powerful Apify actor that scrapes hotel pricing data from Google Travel for a specific hotel. This actor extracts real-time pricing information for a given hotel across multiple dates and provides comprehensive price comparisons from various booking providers.

### 🏨 What it does

This actor scrapes Google Travel's hotel pricing data for a specific hotel by:

- **Single hotel focus**: Scrapes pricing data for one specific hotel (identified by entity ID)
- **Multi-date scraping**: Generates price data for consecutive days starting from your check-in date
- **Provider comparison**: Extracts prices from multiple booking providers (OTAs) for the same hotel
- **Real-time data**: Gets current pricing directly from Google Travel's API
- **Comprehensive output**: Provides detailed pricing information including provider names and official vs third-party rates

### 📊 Output Format

The actor outputs one item per booking provider per date. A run over multiple
days for a hotel with many providers therefore produces one row for each
provider/date combination:

```json
{
  "provider": "Booking.com",
  "otaUrl": "https://www.google.com/travel/clk?...",
  "isOfficial": false,
  "price": 150,
  "price2": 180,
  "adults": 2,
  "currency": "USD",
  "checkInDate": "2025-07-20",
  "checkOutDate": "2025-07-21"
}
```

| Field | Description |
|-------|-------------|
| `provider` | Booking provider / OTA name (e.g. `Booking.com`) |
| `otaUrl` | Google click-through link to the provider's offer (session-scoped; expires shortly after the scrape) |
| `isOfficial` | `true` if this is the hotel's official rate |
| `price` | Nightly price, rounded, in the requested currency |
| `price2` | Secondary price for the row when Google returns one (e.g. taxes-in) |
| `adults` | Number of adults the price is for |
| `currency` | ISO 4217 currency code of the prices |
| `checkInDate` / `checkOutDate` | The night the price applies to |

### 🔧 Input Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `checkInDate` | string | ✅ | Check-in date in YYYY-MM-DD format |
| `days` | integer | ✅ | Number of consecutive days to scrape (minimum: 1) |
| `adults` | integer | ✅ | Number of adult guests (minimum: 1) |
| `currency` | string | ✅ | Currency code (e.g., USD, EUR, JPY) |
| `entity` | string | ✅ | A Google Travel hotel entity ID (starts with `Ch`), **or** a hotel name that is auto-resolved to its entity ID (see below) |
| `device` | string | ❌ | Emulated device: `desktop` (default) or `mobile`. Google serves device-specific pricing — mobile often exposes app/mobile-only OTA rates that desktop hides |
| `proxyConfig` | object | ❌ | Proxy configuration settings (see below) |

#### Proxy Configuration

**Recommended: start with datacenter proxies.** They are cheaper and fast, and
work for most hotels/dates. Only switch to residential proxies if datacenter
requests get blocked or return empty pages.

**1. Try datacenter proxies first:**

```json
{
  "useApifyProxy": true
}
```

**2. If that doesn't work, fall back to residential proxies from the country
you're scraping for** (match `apifyProxyCountry` to that market):

```json
{
  "useApifyProxy": true,
  "apifyProxyGroups": ["RESIDENTIAL"],
  "apifyProxyCountry": "US"
}
```

**Automatic residential fallback for country targeting.** Country targeting
(`apifyProxyCountry`) works reliably only on **residential** proxies — the shared
datacenter pool is almost entirely US-based, so datacenter + a non-US country
has no available IPs and every request fails. To keep runs working, if you set a
country on datacenter and the pool has no IPs there, the actor **automatically
switches to `RESIDENTIAL` for that same country and continues** (it logs the
switch). Because residential proxies cost more, this may increase run cost — set
`apifyProxyGroups: ["RESIDENTIAL"]` yourself if you want to opt in explicitly, or
remove `apifyProxyCountry` to stay on datacenter with a US point-of-sale. Note
that the point-of-sale (currency, tax treatment, `otaUrl` locale) follows the
proxy IP's country, so per-country pricing requires a matching residential
country.

### 🆔 How to Find Entity IDs

> **Shortcut:** you can skip this entirely and just pass a **hotel name** as `entity` (e.g. `"Ana Mandara Villas Dalat"`). The actor resolves it to the top-matching hotel's entity ID via Google Travel search. A city or region (e.g. `"Đà Lạt"`) is **not** a single hotel and will fail with a clear message — this actor scrapes one hotel at a time. For an exact hotel, the entity ID is the most precise input.

Entity IDs are unique identifiers for specific hotels in Google Travel. You need to find the entity ID for the exact hotel you want to scrape. Here's how to find them:

#### Method 1: From Google Travel URL

1. Go to [Google Travel](https://www.google.com/travel/hotels)
2. Search for your desired hotel
3. Click on the hotel to view its page
4. Look at the URL - the entity ID is in the path:

```
https://www.google.com/travel/hotels/entity/ChgIw-i9jd_587w3GgwvZy8xcHR4cWI4OTIQAQ
                                                      ↑
                                              Entity ID here
```

**Example**: From the URL `https://www.google.com/travel/hotels/entity/ChgIw-i9jd_587w3GgwvZy8xcHR4cWI4OTIQAQ`, the entity ID is `ChgIw-i9jd_587w3GgwvZy8xcHR4cWI4OTIQAQ`

#### Method 2: Using Browser Developer Tools

1. Open Google Travel in your browser
2. Navigate to a hotel page
3. Open Developer Tools (F12)
4. Go to Network tab
5. Look for API requests containing the entity ID
6. The entity ID will appear in request URLs or response data

#### Method 3: From Google Maps

1. Search for a hotel on Google Maps
2. Click on the hotel listing
3. Look for the "View on Google Travel" link
4. Follow the link to get the entity ID from the URL

### 🚀 Usage Examples

#### Basic Usage

```json
{
  "checkInDate": "2025-07-20",
  "days": 3,
  "adults": 2,
  "currency": "USD",
  "entity": "ChgIw-i9jd_587w3GgwvZy8xcHR4cWI4OTIQAQ"
}
```

#### With Proxy Configuration

```json
{
  "checkInDate": "2025-07-20",
  "days": 5,
  "adults": 1,
  "currency": "EUR",
  "entity": "ChgIw-i9jd_587w3GgwvZy8xcHR4cWI4OTIQAQ",
  "proxyConfig": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "DE"
  }
}
```

### 📈 Use Cases

- **Price monitoring**: Track prices for a specific hotel over time
- **Competitive analysis**: Compare prices across different booking platforms for the same hotel
- **Travel planning**: Find the best rates for your preferred hotel on specific dates
- **Market research**: Analyze pricing trends for individual hotels
- **Revenue optimization**: Help hotels understand their competitive positioning against other providers

### 🔒 Rate Limiting & Best Practices

- **Respectful scraping**: The actor uses proper delays and headers
- **Proxy rotation**: Use Apify Proxy to avoid IP blocks — start with datacenter proxies and only fall back to residential (from the target country) if you hit blocks
- **Session management**: Maintains cookies for better success rates
- **Error handling**: Gracefully handles API errors and timeouts
- **No offers for a date**: If a date has no bookable offers (e.g. it's beyond Google's ~12-month booking window, or the hotel has no live rates), the actor emits **0 items for that date and the run still succeeds** — it is not treated as a failure

### 🛠️ Technical Details

- **Built with**: Apify SDK v3.2.6, Crawlee v3.11.5
- **Target**: Google Travel's internal API endpoints
- **Data format**: JSON with structured pricing information
- **Rate limiting**: Built-in delays and proxy support
- **Error recovery**: Automatic retry logic for failed requests

### 📋 Supported Currencies

The actor supports all major ISO 4217 currency codes including:

- USD (US Dollar)
- EUR (Euro)
- GBP (British Pound)
- JPY (Japanese Yen)
- CAD (Canadian Dollar)
- AUD (Australian Dollar)
- And 70+ more currencies

### ⚠️ Important Notes

- **Entity ID validity**: Ensure your entity ID is current and valid
- **Date ranges**: Avoid scraping too many consecutive days to prevent rate limiting
- **Proxy usage**: Recommended for production use to avoid IP blocks
- **Data accuracy**: Prices are real-time but may vary based on availability

# Actor input Schema

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

The date of check-in in YYYY-MM-DD format (e.g., 2025-07-30).

## `days` (type: `integer`):

Length of stay in days. Must be at least 1.

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

Number of adult guests. Must be at least 1.

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

Currency code. Use ISO 4217 standard codes.

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

A Google Travel hotel entity ID (starts with "Ch", found in the hotel's Travel URL), or a hotel name which is auto-resolved to its entity ID via Google Travel search. Note: this actor scrapes one hotel at a time, so a city or region (e.g. "Đà Lạt") is not a valid entity and will fail.

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

Emulated device (via User-Agent). Google Travel serves device-specific pricing — mobile often exposes app/mobile-only OTA rates that desktop hides. Defaults to desktop.

## `proxyConfig` (type: `object`):

Country targeting (apifyProxyCountry) works reliably only with RESIDENTIAL proxies. The shared datacenter pool is almost entirely US-based, so if you set a non-US country on datacenter and it has no IPs there, the actor automatically switches to RESIDENTIAL for that same country and continues (this may increase run cost). The point-of-sale follows the proxy IP's country, so per-country pricing requires a matching residential country; use datacenter only for the US market.

## Actor input object example

```json
{
  "device": "desktop",
  "proxyConfig": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}
```

# 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 = {
    "proxyConfig": {
        "useApifyProxy": true,
        "apifyProxyGroups": []
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("vittuhy/google-travel-hotel-prices").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 = { "proxyConfig": {
        "useApifyProxy": True,
        "apifyProxyGroups": [],
    } }

# Run the Actor and wait for it to finish
run = client.actor("vittuhy/google-travel-hotel-prices").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 '{
  "proxyConfig": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}' |
apify call vittuhy/google-travel-hotel-prices --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vittuhy/google-travel-hotel-prices"
        }
    }
}

```

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/avuGKFVFOFzyUrXAQ/builds/FHBDhy4O9mRvVs7Gw/openapi.json
