DEV Community

Gio Rich
Gio Rich

Posted on Fully Autonomous

How to track Google Hotels prices with Python (no browser, no API key)

I built this actor; it's a paid tool on Apify with a free trial credit.

Google Hotels shows you a price for every hotel in a city, but there's no official API for it. If you want to watch how prices move over a few weeks, compare a hotel against its neighbours, or feed prices into a trip planner, you end up copying numbers by hand.

I'm an 18-year-old engineering student, and I wrote a scraper for this called Google Hotels Scraper. This post shows how to call it from Python and Node, what the data looks like, and one small project: logging Charlotte hotel prices to a Google Sheet once a day.

How it works, briefly

Google Hotels pages already carry their result data inside AF_initDataCallback script blobs. The actor fetches the page over plain HTTP (no headless browser), parses those blobs and picks out anything shaped like a hotel record. That's why a 50-hotel query usually finishes in well under a minute.

Python example

pip install apify-client
Enter fullscreen mode Exit fullscreen mode
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")

run = client.actor("rel8ble/google-hotels-scraper").call(run_input={
    "queries": ["hotels in Charlotte"],
    "checkIn": "2026-10-15",
    "checkOut": "2026-10-18",
    "adults": 2,
    "currency": "USD",
    "maxResults": 50,
})

for hotel in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(hotel["name"], hotel["pricePerNight"], hotel["rating"], hotel.get("deal"))
Enter fullscreen mode Exit fullscreen mode

Node example

npm install apify-client
Enter fullscreen mode Exit fullscreen mode
import { ApifyClient } from "apify-client";

const client = new ApifyClient({ token: "<YOUR_APIFY_TOKEN>" });

const run = await client.actor("rel8ble/google-hotels-scraper").call({
  queries: ["hotels in Charlotte"],
  checkIn: "2026-10-15",
  checkOut: "2026-10-18",
  maxResults: 50,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((h) => `${h.name}: $${h.pricePerNight}/night`));
Enter fullscreen mode Exit fullscreen mode

What comes back

One item per property. This is a real row from a test run (Charlotte, 3 nights, 15-18 Oct 2026), trimmed:

{
  "query": "hotels in Charlotte",
  "position": 1,
  "name": "Sonesta Select Charlotte University Research Park",
  "pricePerNight": 75,
  "pricePerNightWithTaxes": 88,
  "totalPrice": 263,
  "totalTaxesAndFees": 54.5,
  "currency": "USD",
  "deal": "DEAL 19% less than usual",
  "nights": 3,
  "rating": 3.9,
  "reviewCount": 915,
  "hotelClass": 3,
  "latitude": 35.3072356,
  "longitude": -80.7534261,
  "checkInTime": "4:00 PM",
  "checkOutTime": "11:00 AM",
  "entityToken": "ChYIl4r5ruWLqpcWGgovbS8wejlfbDlqEAE",
  "googleMapsUrl": "https://www.google.com/maps?cid=16387801168794899843",
  "scrapedAt": "2026-09-23T23:01:40.083Z"
}
Enter fullscreen mode Exit fullscreen mode

You also get amenities, nearby places with travel times, photos, a short description and the official website. Turn on includeDetails and you get the street address and phone number too (one extra request per hotel).

The field I lean on most is entityToken. It stays the same across runs, so it's the key for joining today's price to yesterday's.

Use case: log Charlotte hotel prices to Google Sheets every day

The goal: one row per hotel per day, so after a couple of weeks you can chart how prices move for a fixed stay.

I use gspread with a Google service account (share the sheet with the service account's email first).

pip install apify-client gspread
Enter fullscreen mode Exit fullscreen mode
import datetime
import gspread
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
sheet = gspread.service_account(filename="service-account.json").open("Charlotte hotel prices").sheet1

run = client.actor("rel8ble/google-hotels-scraper").call(run_input={
    "queries": ["hotels in Charlotte"],
    "checkIn": "2026-11-20",
    "checkOut": "2026-11-22",
    "currency": "USD",
    "maxResults": 50,
})

today = datetime.date.today().isoformat()
rows = []
for h in client.dataset(run["defaultDatasetId"]).iterate_items():
    rows.append([
        today,
        h["entityToken"],
        h["name"],
        h.get("pricePerNight"),
        h.get("totalPrice"),
        h.get("rating"),
        h.get("deal") or "",
    ])

sheet.append_rows(rows, value_input_option="USER_ENTERED")
print(f"appended {len(rows)} rows")
Enter fullscreen mode Exit fullscreen mode

Run it once a day with cron, Task Scheduler or a GitHub Actions schedule. You could also skip the script: set up a Schedule in the Apify Console and use the Google Sheets integration there. After a week, a pivot table on entityToken × date shows you which hotels are dropping and which aren't.

Keep the check-in and check-out dates fixed. If you change them, you're comparing different stays, not watching one stay's price move.

What it costs

Pricing is $3.50 per 1,000 results, and one result is one hotel saved. You aren't charged for duplicates or failed requests.

  • The daily job above: 50 hotels × 30 days = 1,500 results ≈ $5.25/month
  • A one-off market scan of 1,000 hotels = $3.50
  • Apify's free plan gives $5 of monthly credit, which covers roughly 1,400 hotels

Limits

These come straight from my testing:

  • About 150-250 unique hotels per query. After that Google only serves vacation rentals or repeats. For a big city, split it up: "hotels in Shinjuku", "hotels in Shibuya".
  • Prices are Google's "from" price: the lowest rate across booking partners for your dates and guests. Properties with no rooms for your dates return pricePerNight: null (about 9% in a 300-hotel test).
  • No per-partner price list (Booking.com vs Expedia vs direct) and no review texts in this version.
  • Address and phone need includeDetails, which is slower.
  • Google reshuffles results between pages, so a page sometimes adds fewer than 20 new hotels after dedup.

If something breaks or a field is wrong, the Issues tab on the actor page reaches me directly.

Google Hotels Scraper on Apify


This article was drafted with AI and published by me.

Top comments (0)