# Google Hotels Scraper & Price Intelligence (`azzarilabs/google-hotels-price-intelligence`) Actor

Scrape public Google Hotels prices, ratings, reviews, property identifiers, and explainable price intelligence without user API keys.

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

## Pricing

$5.00 / 1,000 hotel 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 Hotels Scraper & Price Intelligence

Turn a destination into a clean hotel Dataset with public nightly prices, ratings, review counts, property identifiers, and explainable price intelligence. Enter only a destination; no Google API key, login, private token, paid API, or residential proxy is required.

### What you get

- Valid, deduplicated hotel records from public Google Travel data.
- Nightly price and the currency actually displayed by Google.
- Rating, review count, star class, coordinates, property ID, and Google Travel URL when available.
- Median and price range when at least three comparable prices exist.
- Deterministic `price_position`, `value_score`, `deal_signal`, and `coverage_confidence`.
- Typed Dataset, machine-readable `OUTPUT`, and a responsive `REPORT.html`.
- Clean empty or partial results when Google returns no usable evidence.

Typical uses include hotel rate research, destination price snapshots, travel market analysis, accommodation lead lists, and comparison of public hotel positioning.

### Quick start

The smallest useful input is:

```json
{
  "destination": "Miami"
}
```

If dates are omitted, every run calculates them dynamically:

- `checkIn`: run date + 14 days
- `checkOut`: check-in + 1 day

The ADWIC/default input uses Miami, 2 adults, and 10 results without hard-coded dates:

```json
{
  "destination": "Miami",
  "adults": 2,
  "maxResults": 10
}
```

An explicit example:

```json
{
  "destination": "Madrid",
  "adults": 2,
  "currency": "EUR",
  "maxResults": 20
}
```

The prefilled and sample inputs never embed a fixed date. Add future ISO dates only when a specific stay window is required.

### Input

| Field | Required | Default | Limits |
|---|---:|---:|---|
| `destination` | Yes | Miami in the UI | 2–120 characters |
| `checkIn` | No | Today +14 days | ISO `YYYY-MM-DD`, not in the past |
| `checkOut` | No | Check-in +1 day | After check-in; maximum 30 nights |
| `adults` | No | 2 | 1–10 |
| `currency` | No | Google-displayed currency | Three-letter ISO request |
| `maxResults` | No | 20 | 1–50 |

Google can localize currency by network location even when a currency is requested. The Actor never relabels a price: it returns the observed currency and emits `requested_currency_not_honored` when appropriate.

### Dataset fields

Stable public fields are returned when present: `hotel_name`, `price_per_night`, `currency`, `rating`, `review_count`, `star_rating`, `latitude`, `longitude`, `property_id`, and `google_travel_url`.

Detail-only or volatile fields are opportunistic: `address`, `phone`, `provider_prices`, `availability`, `room`, `cancellation`, and `promotion`. Missing evidence is represented as `null`, never guessed. Every row also includes destination, dates, source strategy, price intelligence, outlier state, and warnings.

### Price intelligence

Price intelligence is computed only when at least three positive, same-result prices remain after outlier filtering.

1. Compute the preliminary median of positive nightly prices.
2. With at least three prices, mark values below 25% or above 400% of that median as outliers.
3. Exclude those outliers from the final benchmark.
4. Require at least three remaining prices; otherwise median, Value Score, price position, and Deal Signal are `N/A`/`null`.

For a comparable hotel:

- `price ratio = hotel price / median price`
- `price component = clamp(50 + (1 − price ratio) × 100, 0, 65)`
- `quality component = rating / 5 × 25`, or 0 when rating is unavailable
- `review component = min(log10(review count + 1) / 4, 1) × 10`, or 0 without reviews
- `value_score = price component + quality component + review component`, capped at 100

`price_position` is Below median at ≤90%, Near median between 90% and 110%, and Above median at ≥110%.

`deal_signal` rules:

- `Strong`: price ≤85% of median, rating ≥4.0, and at least 20 reviews
- `Expensive`: price >115% of median
- `Fair`: sufficient evidence but neither Strong nor Expensive
- `N/A`: insufficient sample, missing price, or price outlier

No “best value” claim is produced from an insufficient sample.

### Acquisition and resilience

The Actor uses one public architecture:

`Input → HTTP acquisition → selective browser fallback → normalization → identity/dedup → price intelligence → Dataset + OUTPUT + REPORT`

- Direct HTTP structured acquisition is attempted first with a 25-second timeout per isolated alternative.
- Three safe Google Travel URL variants are attempted independently.
- CAPTCHA/unusual-traffic pages and HTTP 403/429 responses are rejected.
- The browser fallback has a 35-second cap and is used only when HTTP is empty or cannot verify requested date/currency state.
- If browser acquisition fails, usable HTTP evidence is retained with explicit warnings.
- If every strategy fails, the run returns a clean empty result without fabricated hotels.
- Worst-case acquisition timeout is bounded to approximately 110 seconds before normal output work.

Hotels are deduplicated first by Google property ID and then by normalized name plus coordinates/address. Explicit vacation rentals, holiday homes, and entire-apartment records are excluded when source evidence identifies them.

### OUTPUT and REPORT

`OUTPUT` summarizes status, query, destination, dates, hotels found, valid price sample, median/min/max, observed currency, coverage confidence, warnings, report URL, acquisition attempts, and identity statistics.

`REPORT.html` provides a responsive destination summary, price range, hotel table, ratings, Value Scores, Deal Signals, Google Travel links, methodology, and warnings.

### Billing preparation

The prepared pay-per-event name is `hotel-result`. A billing event is emitted only after a valid deduplicated hotel has been written to the Dataset and outputs have been delivered. Errors, timeouts, discarded candidates, and empty results are never billable.

The commercial event price is intentionally unset in this candidate. It must be chosen after the first Cloud cost/speed smoke and before commercial publication.

### Real acquisition evidence

Research performed on 2026-09-10 recovered public data without a proxy for Miami, New York, and Madrid. Each raw HTTP capture contained 18 organic property records; browser verification displayed 20 accommodation cards per destination and future-date prices. The deterministic source captures, normalized fixtures, hashes, and browser observations are included under `tests/fixtures`.

### Limitations

- Google Travel structured payloads are undocumented and may change.
- Ranking, availability, and provider prices are volatile.
- Requested currency may be replaced by IP-localized currency.
- Exact address and booking-provider offers may require additional browser/detail evidence and can remain `null`.
- A small no-proxy sample cannot guarantee that scaled traffic will never be rate-limited.
- This Actor is not affiliated with or endorsed by Google. Users are responsible for compliant usage.

# Actor input Schema

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

City, district, airport, or destination, for example Miami, New York, or Madrid.

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

ISO date YYYY-MM-DD. If omitted, the Actor uses the run date plus 14 days.

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

ISO date YYYY-MM-DD. If omitted, the Actor uses one night after check-in.

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

Number of adult guests.

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

Requested ISO 4217 currency such as USD or EUR. Google may localize currency by network location; the observed currency is always returned transparently.

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

Maximum valid hotel records to deliver.

## Actor input object example

```json
{
  "destination": "Miami",
  "adults": 2,
  "maxResults": 10
}
```

# Actor output Schema

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

No description

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

No description

## `report` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("azzarilabs/google-hotels-price-intelligence").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("azzarilabs/google-hotels-price-intelligence").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 '{}' |
apify call azzarilabs/google-hotels-price-intelligence --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,azzarilabs/google-hotels-price-intelligence"
        }
    }
}
```

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/JOaHgffiBejq1ZqKX/builds/wAdWTZaAIgeVg4UVl/openapi.json
