Free Google Hotels CLI — per-hotel data with deep booking links, agent-native JSON, and local SQLite wishlist. No API key needed.
hotel-goat scrapes Google Hotels' server-rendered data (the same data the Google Hotels web UI shows) without an API key. v1 ships:
hotels <location> <ci> <co> — search with rich filters (brand, hotel-class, max-price, min-rating, amenities, currency)
dates <location> --from --to --nights N — sweep a date window for the cheapest pair per stay
near "<address>" --radius Nmi — geo-radius search around any address (auto-geocoded via OpenStreetMap)
hotel show <token> / hotel reviews <token> — single-property detail + review breakdown
wishlist add/list/remove <token> — local SQLite saves
Brand-loyalty expansion, full month-window scans (cheapest-window), price drift tracking, multi-room family logic, and per-OTA breakdown are deferred to v0.2 — see Known Gaps below.
Known Gaps
This is a focused v1. The following features were scoped in the design but deferred:
cheapest-window — cheapest N-night window across a whole month (in-window date sweep is handled by dates today)
drift — price history per property from local snapshots
brand-loyal --program <hyatt|marriott|hilton|ihg|accor> — search expanded to all sub-brands
compare-cities "<city1,city2,...>" — same nights across multiple cities
family --rooms N --kids M — multi-room search with kid-aware ranking
watch <property> --target-price N — cron-friendly price-drop alert with typed exit codes
bundle <city> --nights N --budget X — best stay under a total budget
- OTA per-source price breakdown — the
prices[] field is populated when Google's per-result OTA data is present, but inconsistent across results today
- Chain brand auto-detection from hotel names — works for some chains, misses independent properties
Learn more at Google Hotels.
Printed by @kothari-nikunj (kothari-nikunj).
Authentication
No authentication required. Google Hotels SSR is publicly accessible. Set Accept-Language via the system locale; pass --currency EUR to get pricing in another currency.
Quick Start
# Headline search: location + dates + filters. Returns booking URLs per result.
hotel-goat-pp-cli hotels "San Francisco" 2026-08-15 2026-08-17 --sort cheapest --max-price 300 --min-rating 4.0
# Agent-friendly: brand filter + nested-field selection.
hotel-goat-pp-cli hotels "Paris" 2026-07-20 2026-07-23 --brand Hyatt,Marriott --agent --select results.name,results.price_per_night,results.booking_urls.primary
# Property detail by Google's property_token from a search result.
hotel-goat-pp-cli hotel show <property-token>
# Save properties locally for later reference.
hotel-goat-pp-cli wishlist add <property-token>
# Confirm network reachability to Google Hotels.
hotel-goat-pp-cli doctor
Unique Features
These capabilities aren't available in any other tool for this API.
Agent-native plumbing
-
hotels — Dotted-path selection through nested results.prices[], results.booking_urls, results.images[]. Returns only the fields the agent needs.
Use when you need only a couple of fields per hotel rather than the full nested response.
hotel-goat-pp-cli hotels "San Francisco" 2026-08-15 2026-08-17 --agent --select results.name,results.rating,results.price_per_night,results.booking_urls.primary
Recipes
Cheapest 4-star+ stay in Paris under EUR 300 for a specific weekend
hotel-goat-pp-cli hotels "Paris" 2026-07-20 2026-07-23 --currency EUR --hotel-class 4,5 --max-price 300 --sort cheapest
The default hotels invocation with a price ceiling, star floor, and explicit currency — the most common single-trip query.
Agent-native: only name + cheapest OTA + booking link, nothing else
hotel-goat-pp-cli hotels "San Francisco" 2026-08-15 2026-08-17 --agent --select results.name,results.rating,results.prices.source,results.prices.price,results.booking_urls.primary
Pairs --agent with --select dotted paths to extract only the fields an agent needs — cuts response size ~10x while keeping the per-OTA price breakdown intact.
Property detail by token
hotel-goat-pp-cli hotel show <property-token>
Full property details (amenities, nearby places, image gallery) from a property_token returned by the hotels search. The token is the value of results[*].property_token in the JSON envelope.
Save and recall properties
hotel-goat-pp-cli wishlist add <property-token>
hotel-goat-pp-cli wishlist list
Local-SQLite wishlist: save properties from searches, list them later. Survives across sessions; exportable to JSON via --agent.
Usage
Run hotel-goat-pp-cli --help for the full command reference and flag list.
Commands
hotels
Hotel search results from Google Hotels for a location + date range
hotel-goat-pp-cli hotels - Search hotels by location and date range. Returns ~30-40 properties per query
with full OTA price breakdown and booking deep-links.
properties
Property detail records cached from Google's property detail pages
hotel-goat-pp-cli properties - Full property detail by Google's property_token
Output Formats
# Human-readable table (default in terminal, JSON when piped)
hotel-goat-pp-cli hotels "San Francisco" 2026-08-15 2026-08-17
# JSON for scripting and agents
hotel-goat-pp-cli hotels "San Francisco" 2026-08-15 2026-08-17 --json
# Filter to specific fields
hotel-goat-pp-cli hotels "San Francisco" 2026-08-15 2026-08-17 --json --select results.name,results.price_per_night,results.booking_urls.primary
# Dry run — show the request without sending
hotel-goat-pp-cli hotels "San Francisco" 2026-08-15 2026-08-17 --dry-run
# Agent mode — JSON + compact + no prompts in one flag
hotel-goat-pp-cli hotels "San Francisco" 2026-08-15 2026-08-17 --agent
Agent Usage
This CLI is designed for AI agent consumption:
- Non-interactive - never prompts, every input is a flag
- Pipeable -
--json output to stdout, errors to stderr
- Filterable -
--select id,name returns only fields you need
- Previewable -
--dry-run shows the request without sending
- Read-only by default - this CLI does not create, update, delete, publish, send, or mutate remote resources
- Offline-friendly - sync/search commands can use the local SQLite store when available
- Agent-safe by default - no colors or formatting unless
--human-friendly is set
Exit codes: 0 success, 2 usage error, 3 not found, 5 API error, 7 rate limited, 10 config error.
Health Check
hotel-goat-pp-cli doctor
Verifies configuration and connectivity to the API.
Configuration
Config file: ``
Static request headers can be configured under headers; per-command header overrides take precedence.
Troubleshooting
Not found errors (exit code 3)
- Check the resource ID is correct
- Run the
list command to see available items
API-specific
- Empty results array on a query that returns hotels in the Google Hotels web UI. — Set --currency to match your locale (e.g. --currency EUR for European cities) — Google Hotels region-shifts inventory by currency. If still empty, run with --no-cache.
- HTTP 429 or 403 from Google after rapid back-to-back calls. — Lower request rate with --rate-limit 0.5 (one request every two seconds), or run from a fresh IP. The scrape uses no anti-bot rotation by design.
- Brand filter --brand Hyatt misses Andaz / Thompson / Park Hyatt properties. — Use brand-loyal --program hyatt instead — it expands to all sub-brands via the local brand_aliases table.
- drift returns 'no snapshots' for a property you've searched before. — drift keys on property_token, not display name. Run hotel-goat-pp-cli resolve "" to get the token, then drift .
- Total cost looks wrong for a multi-room family search. — The hotels command shows per-room price by default. Use the family command instead — it sums across rooms and surfaces the true family budget.
Sources & Inspiration
This CLI was built by studying these projects and resources:
Generated by CLI Printing Press