Google Hotels Scraper
Return a full multi-OTA price comparison plus rich metadata for any hotel and date range worldwide. Submit a job by Google Place ID (recommended) or hotel name + city, then poll for the result.
Base URL: https://gumo.co.in ยท Auth: X-API-Key: gsk_โฆ with the gmaps scope ยท See the Overview for shared concepts.
Submit a job
Provide either a place_id (recommended โ deterministic) or a hotel_name. When searching by name (no place_id), city is also required. A place_id-only request is valid; if both are given, place_id is used first with name+city as fallback.
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
hotel_name | string | Optional | "" | โค 300 chars. Required only when no place_id is given. Also used for logging & fallback search. |
place_id | string | Optional | "" | โค 200 chars. Google Place ID โ deterministic & fastest lookup. Provide this or hotel_name. |
city | string | Optional | "" | โค 200 chars. Required when using name search (no place_id). |
check_in | date | Required | โ | YYYY-MM-DD. Not in the past; โค 1 year ahead. |
check_out | date | Required | โ | After check_in; โค 30 nights. |
adults | int | Optional | 2 | 1โ10. |
children | int | Optional | 0 | 0โ6. |
curl -X POST https://gumo.co.in/api/v1/scraper/scrape/ \
-H "X-API-Key: gsk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"hotel_name": "Rambagh Palace",
"place_id": "ChIJm14which9bDkRXF7ciSSR4eA",
"check_in": "2026-04-10",
"check_out": "2026-04-12",
"adults": 2
}'
{
"job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "pending",
"api_version": 1,
"poll_url": "/api/v1/scraper/scrape/a1b2c3d4-e5f6-7890-abcd-ef1234567890/"
}
Poll for results
Poll the poll_url every ~2 seconds until status is completed or failed. Statuses: pending โ processing โ completed | failed.
import requests, time
API = "https://gumo.co.in/api/v1/scraper"
H = {"X-API-Key": "gsk_your_api_key"}
job = requests.post(f"{API}/scrape/", headers=H, json={
"hotel_name": "Rambagh Palace",
"place_id": "ChIJm14which9bDkRXF7ciSSR4eA",
"check_in": "2026-04-10", "check_out": "2026-04-12",
}).json()
while True:
res = requests.get(f"{API}/scrape/{job['job_id']}/", headers=H).json()
if res["status"] in ("completed", "failed"): break
time.sleep(2)
for offer in res["result"]["pricing"]:
print(offer["platform_name"], offer["price_display"])
Response schema
A completed job returns the job envelope with a result object. Top-level fields: id, status, api_version, hotel_name, city, place_id, check_in, check_out, adults, children, result, error_message, created_at, started_at, completed_at, duration_seconds, bandwidth_kb.
{
"id": "a1b2c3d4-...",
"status": "completed",
"api_version": 1,
"hotel_name": "Rambagh Palace",
"place_id": "ChIJm14which9bDkRXF7ciSSR4eA",
"check_in": "2026-04-10", "check_out": "2026-04-12",
"adults": 2, "children": 0,
"result": {
"hotel_metadata": {
"name": "Rambagh Palace", "hotel_class": 5, "user_rating": 4.7,
"review_count": 8234, "address": "Bhawani Singh Road, Jaipur...",
"phone": "+91 141 221 1919", "website": "https://www.tajhotels.com/...",
"latitude": 26.8982, "longitude": 75.8092,
"check_in_time": "14:00", "check_out_time": "12:00",
"amenities": ["Free breakfast", "Pool", "Spa", "Free Wi-Fi"],
"images": ["https://lh5.googleusercontent.com/..."]
},
"pricing": [
{
"platform_name": "Booking.com", "price": 45000.0,
"price_display": "โน45,000", "currency": "INR",
"price_before_discount": 52000.0,
"booking_url": "https://www.booking.com/hotel/in/rambagh-palace...",
"free_cancellation": true, "cancellation_deadline": "8 Apr",
"room_type": "Palace Room", "breakfast_included": true,
"tax_included": false, "is_official": false
},
{
"platform_name": "Rambagh Palace", "price": 48000.0,
"currency": "INR", "is_official": true,
"room_type": "Palace Room", "breakfast_included": true
}
],
"matched_hotel": "Rambagh Palace",
"navigation_mode": "maps_preview",
"timings": { "total": 3.2, "response_size_kb": 21.5 }
},
"error_message": "",
"duration_seconds": 3.2, "bandwidth_kb": 21.5
}
Fields โ pricing[] (per OTA)
| Field | Type | Description |
|---|---|---|
platform_name | string | OTA or official-site name (e.g. Booking.com, Agoda). |
price | number | Numeric nightly price. |
price_display | string | Localized formatted price, e.g. โน45,000. |
currency | string | Currency code as localized by Google. |
price_before_discount | number | Struck-through pre-discount price, when shown. |
booking_url | string | Direct deep link to the offer. |
free_cancellation | bool | Whether free cancellation is offered. |
cancellation_deadline | string | Free-cancellation cut-off, when present. |
room_type | string | Rate's room description. |
breakfast_included | bool | Board indicator. |
tax_included | bool / null | Whether taxes are included, when detectable. |
tax_amount | number / null | The taxes-and-fees amount, when Google itemizes it. |
tax_source | string | Provenance of the tax read (e.g. maps_preview, ghotel_http). |
logo_url | string | OTA logo image URL, when shown. |
source | string | Present on non-panel offers: sponsored, entity or entity_featured. |
is_official | bool | True for the hotel's own direct rate. |
Fields โ hotel_metadata
name, hotel_class (stars), user_rating, review_count, description, address, neighborhood, phone, website, latitude, longitude, check_in_time, check_out_time, amenities[], images[].
navigation_mode tells you which pipeline produced the result (maps_preview for Place-ID scrapes; direct/fallback/name_only/http for name search). Metadata keys that could not be parsed may be absent rather than null on the name-search path, and Place-ID results can include extra arrays such as similar_hotels, nearby_vacation_rentals and onsite_venues. Treat unknown keys as additive and every key as optional.status: "failed" with a human-readable error_message (e.g. "Hotel not found in listing results", "Request timed out").Batch scraping
Scrape up to 20 hotels that share the same check-in/check-out in one call. Each hotel becomes its own job.
{
"check_in": "2026-04-10",
"check_out": "2026-04-12",
"hotels": [
{ "place_id": "ChIJm14which9bDkRXF7ciSSR4eA" },
{ "hotel_name": "The Oberoi", "city": "New Delhi", "adults": 2 }
]
}
# Per-hotel fields: place_id, hotel_name, city, adults, children (same rules as single submit)
# โ 202: { "jobs": [ { "job_id": "...", "hotel_name": "...", "city": "...", "poll_url": "..." }, ... ] }
{ "job_ids": ["uuid-1", "uuid-2"] }
# โ 200: { "results": [ <job result>, <job result> ] } (1โ20 IDs)
API versions
Pass an optional X-API-Version header (1 or 2; default 1). The chosen version is echoed back as api_version. Unrecognized values fall back to the default silently โ they do not error. The header is read on /scrape/ and /batch/ only.
| Version | Behaviour |
|---|---|
v1 | Standard resolution & OTA extraction. |
v2 | Server-side Place ID resolution with broader OTA coverage (incl. MakeMyTrip) and lower bandwidth. Adds to result: resolution {place_id, source: "client"|"cache"|"places_text_search"|"unresolved"}, match_verification {match_confidence: "high"|"medium"|"low"|"unknown", name_score, locality_match, matched_name}, and v2_retry {triggered, added_platforms?} when a thin OTA panel triggered the targeted retry. |