✈️🏨 Google Flights & Hotels Scraper (Any Market)
Pricing
from $0.45 / 1,000 flight results
✈️🏨 Google Flights & Hotels Scraper (Any Market)
Scrape Google Flights and Google Hotels from one Actor — switch searchType and go. Fares, airlines, layovers, CO₂ and Google's own fare history; hotel rates, ratings and reviews. Structured search tokens, not text queries, so every market returns results without a country proxy.
Pricing
from $0.45 / 1,000 flight results
Rating
0.0
(0)
Developer
jy-labs
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Google Flights & Google Hotels Scraper
One Actor, two searches. Set searchType to flights or hotels and the
same run scrapes either side of Google Travel.
- ✈️ Flights — fares, airlines, flight numbers, layovers, aircraft, legroom, CO₂, and Google's own fare history, for up to 50 routes in a single run.
- 🏨 Hotels — room rates, stay totals, star ratings, review counts and coordinates, for up to 50 hotel searches in a single run.
No login. No cookies. Datacenter proxy is enough for every market.
One line per route
LAX-JFK 2026-09-22ICN-CDG 2026-10-01..2026-10-10CDG-NRT 2026-09-22
ORIGIN-DESTINATION date for one way, date..date for a return. Paste a column
straight from a spreadsheet. Fifty routes are one run, one job, one result set —
not fifty runs to launch and stitch back together.
Why searches do not come back empty
Most Google Flights scrapers ask Google in prose —
?q=Flights to NRT from CDG on 2026-09-22Measured 2026-08-20, same route, same date, same minute:
| Request | Locale | Itineraries |
|---|---|---|
?q=Flights to NRT from CDG on 2026-09-22 | hl=fr gl=fr | 0 |
?q=Flights to NRT from CDG on 2026-09-22 | hl=en gl=us | 13 |
| structured search (this Actor) | hl=fr gl=fr | 10 |
| structured search (this Actor) | hl=de gl=de | 12 |
| structured search (this Actor) | hl=ko gl=kr | 12 |
| structured search (this Actor) | hl=ja gl=ja | 12 |
This Actor never sends a text query. It builds Google's own structured search token, which carries the route as data and has no language to get wrong.
Across a 14-case sweep — 12 markets, one-way and return, 8 currencies — the structured form returned results 14 out of 14 times; the prose form managed 7 of 8 on the same routes.
Any market without a proxy in that country
market, language and currency are request parameters, not a function of
where your proxy exits. A US datacenter exit asking for market: de,
currency: EUR returned the same fare, 145 EUR, as a residential exit
inside Germany. Residential proxy is never required, so a run costs what
compute costs.
Verified currencies: USD, EUR, GBP, JPY, KRW, CAD, AUD, BRL, SGD, AED and more. Airport and hotel names come back in the language you asked for.
What one flight row looks like
{"query": "LAX-JFK 2026-09-22","origin": "LAX", "destination": "JFK","market": "fr", "currency": "EUR", "price": 145,"airline": "JetBlue", "airlineCode": "B6","stops": 0, "totalDurationMinutes": 330,"departure": "2026-09-22T08:00", "arrival": "2026-09-22T16:30","legs": [{"origin": "LAX", "destination": "JFK","originName": "Aéroport international de Los Angeles","flightNumber": "524", "aircraft": "Airbus A320", "legroom": "84 cm"}],"layovers": [],"emissions": { "grams": 417000, "routeAverageGrams": 344000, "percentVsAverage": 21 },"bookingToken": "CjRIYm1acEdIM3llVzBBQm10MEFCRy0t…","section": "best"}
stops is derived from the legs, never read from Google's own stop field —
that field was observed null on itineraries that plainly had a connection.
Fare history, free
Every route also yields one flight-price-insights row carrying Google's
cheapest current fare, its typical fare, the typical range, and roughly 60
days of fare history as date/price pairs. Useful when you are watching a route
rather than booking today. It is not charged as a result.
{ "searchType": "flight-price-insights", "query": "LAX-JFK 2026-09-22","lowestPrice": 119, "typicalPrice": 136,"typicalRangeLow": 85, "typicalRangeHigh": 165,"priceHistory": [{ "date": "2026-06-21", "price": 134 }, … ] }
Hotels, in the same Actor
Set searchType to hotels and fill queries instead of routes:
{ "searchType": "hotels", "queries": ["hotels in Berlin", "hotels in Seoul"],"checkIn": "2026-09-22", "checkOut": "2026-09-24", "adults": 2,"market": "de", "language": "de", "currency": "EUR" }
Each row carries the hotel name, nightly rate, stay total, guest rating, review count and coordinates. Note that Google's hotel search page serves only sponsored listings to a plain request; this Actor reads the organic list the way the page itself does, so a Berlin search returns well over a hundred properties rather than eight adverts.
Pricing, and what happens when a search finds nothing
| Event | Charged | Free tier | Paid tiers |
|---|---|---|---|
| Search | once per route or hotel query the Actor actually runs | $3.00 / 1,000 | from $2.70 |
| Flight result | per itinerary written to the dataset | $0.50 / 1,000 | from $0.45 |
| Hotel result | per hotel written to the dataset | $0.80 / 1,000 | from $0.72 |
| Fare-history row | never | — | — |
Paid Apify plans get 5–10% off every per-unit price.
A search that returns nothing is charged as a search and nothing else — you are never billed per-result for rows you did not receive. And an empty answer is not taken at face value: the search is retried once on a different exit first, because Google sometimes answers a throttled request with an empty page in well under a second. The search is still charged only once, however many attempts it takes.
If every search in a run comes back empty, the run exits non-zero and shows red, instead of finishing as a green run with an empty dataset.
Platform usage is billed separately, as Apify compute and data transfer on your own plan — the per-unit prices above do not include it. This Actor is built to keep that number small: it runs at 512 MB with no browser and needs only datacenter proxy, so measured runs on the Apify platform cost $0.0003–0.0013 in platform usage for a two- or three-route job. Residential proxy, which is where scraping bills usually go, is never used.
Every run writes a RUN_SUMMARY record to the key-value store listing each
search, its row count, and why it failed if it did — so a disappointing run can
be diagnosed without paying to repeat it.
Limits worth knowing before you buy
- 50 searches per run. Split larger jobs across runs.
- Fares are what Google shows, including the basic-economy fares Google
lists. This Actor does not resolve OTA booking pages;
bookingTokenis provided so you can. - Google's result count varies by route. A busy domestic route returned 30
itineraries; a thin long-haul one returned 8.
maxResultsPerSearchcaps the top end, not the bottom. - Hotel rows carry no OTA price comparison. For per-OTA hotel pricing across 30+ booking sites, use a dedicated Google Hotels Actor.
- A hotel with no rooms left for your dates still returns a row, with its
name, rating, review count and coordinates but a
nullprice. Google itself shows the property without a rate; filter onprice !== nullif you only want bookable ones. - Calling from the API, mind the case.
marketandlanguagetake lowercase codes (de,ko) andcurrencytakes uppercase (EUR,KRW). The Console dropdowns handle this for you; a raw API call withis rejected by the platform before the run starts."market": "DE" - Google changes these payloads without notice. When a field starts arriving empty, that is usually why.
Input reference
| Field | Applies to | Default | Notes |
|---|---|---|---|
searchType | both | flights | flights or hotels |
routes | flights | — | one route line each, max 50 |
queries | hotels | — | one hotel search each, max 50 |
adults / children | both | 1 / 0 | children are flights-only |
cabinClass | flights | economy | economy, premium-economy, business, first |
maxStops | flights | any | 0 for nonstop only |
checkIn / checkOut | hotels | tomorrow, +1 night | YYYY-MM-DD |
market / language / currency | both | us / en / USD | independent of proxy country. market and language are lowercase (de), currency is uppercase (EUR) |
maxResultsPerSearch | both | 50 | caps rows per search |
includePriceInsights | flights | true | the free fare-history row |