Hotel Pricing API Reference
Programmatic access to real-time hotel pricing data from Google Hotels. Async job-based architecture — submit, poll, retrieve.
https://gumo.co.in/api/v1/scraper/Auth: X-API-Key headerOverview
The ScrapeGuys Hotel Pricing API provides programmatic access to real-time hotel pricing data from Google Hotels. It extracts OTA (Online Travel Agency) booking links, prices, and hotel metadata for any hotel worldwide.
The API uses an async job-based architecture: submit a scrape request and receive a job_id, then poll for results. Jobs are processed by Celery workers using residential proxies for Google Hotels data extraction.
| Property | Value |
|---|---|
| Base URL | https://gumo.co.in/api/v1/scraper/ |
| Authentication | API key via X-API-Key header |
| Architecture | Async job-based (submit → poll → results) |
| Data source | Google Hotels via residential proxies |
| Response format | JSON |
Authentication
All requests require the X-API-Key header. API keys are prefixed with gsk_ and are 68 characters long.
X-API-Key: gsk_your_api_key_hereContact the ScrapeGuys team to obtain an API key.
| Code | Meaning |
|---|---|
| 401 Unauthorized | Missing or invalid API key |
| 403 Forbidden | API key is deactivated |
Rate Limits & Quotas
Default limits are configurable per client. Contact us to adjust limits for your plan.
| Limit | Default | Configurable |
|---|---|---|
| Per-minute rate limit | 10 requests/min | Yes |
| Daily quota | 1,000 requests/day | Yes |
| Monthly quota | 20,000 requests/month | Yes |
429 Too Many Requests with a descriptive message.Lookup Modes
The API supports two lookup modes:
| Mode | Input | Speed | Bandwidth | Reliability |
|---|---|---|---|---|
| Place ID recommended | place_id + hotel_name | ~3–5s | ~25 KB | 100% deterministic |
| Name Search | hotel_name + city | ~8–12s | ~300 KB | ~87% |
place_id and city — the API uses Place ID first and falls back to name search if needed.Endpoints
Request Body
| Field | Type | Required | Default | Constraints |
|---|---|---|---|---|
hotel_name | string | Yes | — | Max 300 chars |
place_id | string | No | "" | Google Place ID |
city | string | No | "" | City for name-based search |
check_in | date | Yes | — | YYYY-MM-DD, not past, <1yr ahead |
check_out | date | Yes | — | After check_in, max 30 nights |
adults | integer | No | 2 | 1–10 |
children | integer | No | 0 | 0–6 |
place_id or city must be provided.Response 202 Accepted
{
"job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "pending",
"poll_url": "/api/v1/scraper/scrape/a1b2c3d4-e5f6-7890-abcd-ef1234567890/"
}Job Statuses
| Status | Meaning | Action |
|---|---|---|
| pending | Job queued, not yet started | Poll again in 2s |
| processing | Scraper is running | Poll again in 2s |
| completed | Results available in result field | Read result |
| failed | Scraper encountered an error | Check error_message |
Response 200 OK
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "completed",
"hotel_name": "Rambagh Palace",
"city": "",
"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, Rajasthan 302005",
"amenities": ["Free breakfast", "Pool", "Spa", "Free Wi-Fi"],
...
},
"pricing": [
{
"platform_name": "Booking.com",
"price": 45000.0,
"price_display": "₹45,000",
"currency": "INR",
"booking_url": "https://www.booking.com/hotel/in/...",
"free_cancellation": true,
"is_official": false,
...
}
],
"navigation_mode": "maps_preview",
"timings": { "total": 3.2 }
},
"error_message": "",
"created_at": "2026-04-08T10:30:00Z",
"completed_at": "2026-04-08T10:30:03.7Z",
"duration_seconds": 3.2,
"bandwidth_kb": 21.5
}Request Body
| Field | Type | Required | Constraints |
|---|---|---|---|
check_in | date | Yes | YYYY-MM-DD |
check_out | date | Yes | After check_in |
hotels | array | Yes | 1–20 items |
hotels[].hotel_name | string | Yes | Max 300 chars |
hotels[].place_id | string | No | Recommended |
hotels[].city | string | No | Fallback for name search |
hotels[].adults | integer | No | 1–10, default 2 |
hotels[].children | integer | No | 0–6, default 0 |
Response 202 Accepted
{
"jobs": [
{
"job_id": "uuid-1",
"hotel_name": "Rambagh Palace",
"city": "",
"poll_url": "/api/v1/scraper/scrape/uuid-1/"
},
{
"job_id": "uuid-2",
"hotel_name": "Taj Lake Palace",
"city": "",
"poll_url": "/api/v1/scraper/scrape/uuid-2/"
}
]
}Request Body
{
"job_ids": ["uuid-1", "uuid-2", "uuid-3"]
}Response 200 OK
{
"results": [
{ "id": "uuid-1", "status": "completed", "result": { ... } },
{ "id": "uuid-2", "status": "processing", "result": null },
{ "id": "uuid-3", "status": "completed", "result": { ... } }
]
}Response 200 OK
{
"client": "Your Company Name",
"lifetime": {
"total_requests": 12450,
"total_bandwidth_kb": 3245678.5
},
"limits": {
"rate_limit_per_minute": 10,
"daily_quota": 1000,
"monthly_quota": 20000
},
"usage": [
{
"date": "2026-04-08",
"request_count": 142,
"success_count": 138,
"failure_count": 4,
"total_duration_seconds": 856.3,
"total_bandwidth_kb": 36890.2
}
]
}Response Schemas
pricing Array
Each entry represents one OTA's offer. Typical count: 12–25 per hotel.
| Field | Type | Description |
|---|---|---|
platform_name | string | OTA name (e.g., "Booking.com", "Agoda") |
price | float | Numeric price |
price_display | string | Formatted price string (e.g., "₹45,000") |
currency | string | ISO currency code (e.g., "INR", "USD") |
price_before_discount | float/null | Original price if discounted, else null |
booking_url | string | Direct OTA booking URL (not a Google redirect) |
free_cancellation | bool | Whether free cancellation is available |
cancellation_deadline | string | Deadline for free cancellation, empty if none |
room_type | string | Room type description |
breakfast_included | bool | Whether free breakfast is included |
tax_included | bool/null | Whether tax is included, null if unknown |
is_official | bool | Whether this is the hotel's official direct site |
logo_url | string | OTA brand logo URL |
hotel_metadata Object
| Field | Type | Always Present | Description |
|---|---|---|---|
name | string | Yes | Hotel name as displayed on Google |
hotel_class | int/null | No | Star rating (1–5) |
user_rating | float/null | No | Google user rating (1.0–5.0) |
review_count | int/null | No | Total Google review count |
address | string | No | Full address |
phone | string | No | Phone number with country code |
website | string | No | Official hotel website URL |
latitude | float | No | GPS latitude |
longitude | float | No | GPS longitude |
check_in_time | string | No | Check-in time (e.g., "14:00") |
check_out_time | string | No | Check-out time (e.g., "12:00") |
amenities | array[string] | No | Hotel amenities list |
images | array[string] | No | Google-hosted image URLs |
neighborhood | string | No | Neighborhood name and description |
Error Handling
HTTP-Level Errors
| Code | Meaning |
|---|---|
| 400 | Invalid input (missing fields, bad dates, no place_id or city) |
| 401 | Missing or invalid API key |
| 404 | Job ID not found or belongs to another client |
| 429 | Rate limit or quota exceeded |
| 500 | Unexpected server error |
Job-Level Errors
Errors in completed jobs appear in the error_message field.
| Error | Meaning | Mode |
|---|---|---|
| Empty place data | Google Maps didn't return data for this Place ID | Place ID |
| Request timed out | Google didn't respond within timeout | Both |
| Hotel "X" not found in listing results | Hotel name didn't match any Google Hotels listing | Name search |
| Listing page is JS-rendered | Google returned a JS-heavy page that couldn't be parsed | Name search |
Code Examples
Python — Place ID Mode (Recommended)
import time
import requests
API_BASE = "https://gumo.co.in/api/v1/scraper"
API_KEY = "gsk_your_key_here"
HEADERS = {"X-API-Key": API_KEY}
# Submit job with Place ID (deterministic, fast)
response = requests.post(f"{API_BASE}/scrape/", json={
"hotel_name": "Taj Mahal Palace",
"place_id": "ChIJbSFzZEzO5zsRgHj0KiJfcoA",
"check_in": "2026-08-01",
"check_out": "2026-08-03",
}, headers=HEADERS)
job_id = response.json()["job_id"]
# Poll for results
while True:
result = requests.get(f"{API_BASE}/scrape/{job_id}/", headers=HEADERS).json()
if result["status"] in ("completed", "failed"):
break
time.sleep(2)
# Use results
if result["status"] == "completed":
for ota in result["result"]["pricing"]:
print(f"{ota['platform_name']}: {ota['price_display']}")Python — Batch Example
# Submit batch — mix of Place ID and name-based lookups
response = requests.post(f"{API_BASE}/batch/", json={
"check_in": "2026-08-01",
"check_out": "2026-08-03",
"hotels": [
{"hotel_name": "Rambagh Palace", "place_id": "ChIJm14which9bDkRXF7ciSSR4eA"},
{"hotel_name": "Taj Lake Palace", "city": "Udaipur"},
]
}, headers=HEADERS)
job_ids = [j["job_id"] for j in response.json()["jobs"]]
# Poll all at once after waiting
time.sleep(5)
results = requests.post(f"{API_BASE}/batch/results/", json={
"job_ids": job_ids
}, headers=HEADERS).json()
for job in results["results"]:
print(f"\n{job.get('hotel_name')} ({job['status']}):")
if job["result"]:
for ota in job["result"].get("pricing", [])[:3]:
print(f" {ota['platform_name']}: {ota['price_display']}")cURL
# Submit with Place ID
curl -X POST https://gumo.co.in/api/v1/scraper/scrape/ \
-H "X-API-Key: gsk_your_key" \
-H "Content-Type: application/json" \
-d '{"hotel_name":"Rambagh Palace","place_id":"ChIJm14which9bDkRXF7ciSSR4eA","check_in":"2026-08-01","check_out":"2026-08-03"}'
# Poll result
curl https://gumo.co.in/api/v1/scraper/scrape/JOB_ID_HERE/ \
-H "X-API-Key: gsk_your_key"How to Get a Google Place ID
Use the Google Places Text Search API with a minimal field mask (free tier). Place IDs are stable — cache them for repeated lookups of the same hotel.
curl -X POST "https://places.googleapis.com/v1/places:searchText" \
-H "Content-Type: application/json" \
-H "X-Goog-Api-Key: YOUR_GOOGLE_API_KEY" \
-H "X-Goog-FieldMask: places.id" \
-d '{"textQuery": "Rambagh Palace Jaipur hotel", "maxResultCount": 1}'
# Response:
# {"places": [{"id": "ChIJm14which9bDkRXF7ciSSR4eA"}]}Performance
| Metric | Place ID Mode | Name Search Mode |
|---|---|---|
| Job completion time | 3–5s | 8–12s |
| Bandwidth per job | ~25 KB | ~300 KB |
| Reliability | 100% (deterministic) | ~87% (name matching) |
| OTAs per hotel | 12–25 | 12–25 |