kestrel actors › Hotel & flight prices
Google Flights Scraper — Airfare Prices & Price Tracking
A google flights scraper that returns airfare prices straight from Google Flights for the routes, dates and cabin you ask for. Every itinerary comes back as one row: price, airline, departure and arrival times, duration, stops, every layover and the CO2 estimate — a flight price scraper and flight price tracker in one, with no google flights api key, no login and no browser.
Run Google Flights Scraper on Apify →
Google flights scraper pricing: what one row costs
| Event | What it is | Price | Charged for |
|---|---|---|---|
flight | Itinerary row | $0.005 | One flight itinerary for your route, dates and cabin: price, airline, departure and arrival times, duration, stops, layovers and CO2 estimate. Routes with no results are free. |
Pay per event, one event per delivered itinerary row. Searches that return nothing, status rows and failed searches are free, and the same itinerary is billed once per run even when two overlapping searches return it — NYC-LON and JFK-LHR will not bill the same flight twice. maxResultsPerSearch caps rows when you only want the cheapest few.
A single route and date is typically 10–35 rows. A 7-day sweep on 3 routes is about 21 searches — a few hundred rows. Apify platform usage for a run that size is a fraction of a cent; the verified runs behind this listing cost $0.0002–$0.0026 each in compute. Exact per-row pricing is on this page's pricing tab.
Google flights scraper input reference
Every field of Google Flights Prices, straight from the actor's input schema.
| Field | Type | Default | What it does |
|---|---|---|---|
routes | array | — | Routes as airport codes, one per line: "LIS-LHR", "JFK-LAX". Both IATA airport codes and Google's city codes work (NYC-LON searches all New York and London airports). Each route is searched for every date below. |
departDate | string | required | YYYY-MM-DD, or relative so schedules never go stale: "30 days", "6 weeks", "tomorrow". Past dates are rejected — Google would silently price another day. |
returnDate | string | — | Leave empty for one-way. With a date, every row is a round trip and its price is the total for both legs. Same formats as the departure date. |
sweepDays | integer | 0 | 0 = just the date above. N = also the same trip departing on each of the next N days (a return date shifts with it, keeping the trip length). The cheapest-day calendar in one run. Range 0-60. |
seat | string (enum) | "economy" | Cabin to price. Business and first return a different, smaller market than economy. One of: economy, premium_economy, business, first. |
adults | integer | 1 | Adult passengers. Prices are the total for everyone travelling. Range 1-9. |
children | integer | 0 | Children aged 2 to 11 in their own seat. Range 0-8. |
infantsSeat | integer | 0 | Infants under 2 travelling in their own seat. Range 0-8. |
infantsLap | integer | 0 | Infants under 2 travelling on an adult's lap. Range 0-8. |
maxStops | string (enum) | "any" | Limit connections. "Nonstop only" is the filter airlines and revenue teams usually want; "Any" returns everything Google lists. One of: any, nonstop, one_or_fewer, two_or_fewer. |
maxResultsPerSearch | integer | 0 | 0 = every itinerary Google lists for the route and date (usually 10-35). N = only the N cheapest-ranked, which caps what a run can cost. Range 0-200. |
currency | string | "USD" | ISO code for every price, e.g. USD, EUR, GBP. If Google prices in another currency for your market the run fails rather than billing rows in the wrong one. |
market | string | "us" | Two-letter country code for the Google market (gl), e.g. us, de, gb. Fares and available airlines differ by market. Results are always read in English. |
sessions | integer | 4 | How many proxy sessions (egress IPs) run in parallel. More is faster; each one is paced separately. Range 1-16. |
perIp | number | 0.5 | Pace for each session. Google tolerates about 0.5/s per IP; raising it causes retries, not speed. Range 0.1-2. |
proxyConfiguration | object | {"useApifyProxy": true} | Apify Proxy is required: Google blocks datacentre traffic that is not rotated. The default group works. |
Example input
{ "routes": ["LIS-LHR", "LIS-CDG"], "departDate": "30 days", "sweepDays": 6, "currency": "EUR", "market": "pt" }
{ "routes": ["JFK-LHR"], "departDate": "14 days", "returnDate": "21 days", "seat": "business", "maxStops": "nonstop" }
Google flights scraper output fields
Two row types share one dataset: flight (one itinerary for a route, date and cabin) and status (one per route and date; never charged).
Dataset views in the Apify Console: Overview, Flights, Cheapest by day, Run status.
| Field | Type | What it holds |
|---|---|---|
type | string | Row type: flight or status. |
route | string | The route as given, e.g. "LIS-LHR". |
origin_query | string | Origin code as searched. |
destination_query | string | Destination code as searched. |
depart_date | string | Departure date, YYYY-MM-DD. |
return_date | string | Return date for round trips, null for one-way. |
trip | string | one_way or round_trip. |
seat | string | Cabin priced: economy, premium_economy, business or first. |
adults | integer | Adults the price covers. |
children | integer | Children the price covers. |
infants | integer | Infants the price covers (seat + lap). |
currency | string | Currency of the price (ISO code), as Google actually priced it. |
max_stops | integer | Stop limit applied to the search, null when unrestricted. |
rank | integer | Position in Google's ranking for the search; 1 is its top pick. |
price | number | Price for all passengers. For round trips this is the total for both legs. |
price_display | string | Price exactly as Google states it, e.g. "127 US dollars". |
round_trip_total | boolean | True when the price covers both legs of a round trip. |
airline | string | Operating airline; the first when several operate the itinerary. |
airlines | array | Every airline operating the itinerary. |
stops | integer | Number of stops; 0 is nonstop. |
depart_time | string | Departure time, local to the origin. |
depart_day | string | Departure day as Google states it. |
arrive_time | string | Arrival time, local to the destination. |
arrive_day | string | Arrival day as Google states it — later than the departure day on overnight flights. |
depart_airport | string | Full name of the origin airport. |
arrive_airport | string | Full name of the destination airport. |
origin | string | Origin airport code on the itinerary. |
destination | string | Destination airport code on the itinerary. |
duration | string | Total travel time as Google states it, e.g. "2 hr 55 min". |
duration_minutes | integer | Total travel time in minutes — the sortable form. |
layovers | array | Each layover: index, of, minutes, airport, city. |
layover_airports | array | Layover airport names, in order. |
overnight_layover | boolean | True when Google flags an overnight layover. |
co2_kg | integer | Google's carbon estimate for the itinerary, in kilograms. |
emissions_vs_typical | integer | Percent above or below the typical emissions for the route. |
google_url | string | The Google Flights URL for this exact search — opens the same results. |
searches | integer | Status rows: searches run for this route and date. |
flights | integer | Status rows: itinerary rows delivered. |
duplicates | integer | Status rows: itineraries already delivered by an overlapping search, not billed again. |
cheapest | number | Status rows: lowest price found for this route and date. |
status | string | Status rows: ok, no_results or error. |
error | string | Status rows: why the search failed, null when it did not. |
fetched_at | string | UTC timestamp when the row was fetched. |
Example row from a real run
Taken from the actor's README — this is the shape your dataset holds.
{
"type": "flight", "route": "LIS-LHR", "depart_date": "2026-10-05", "return_date": null, "trip": "one_way",
"seat": "economy", "adults": 1, "currency": "USD", "rank": 1,
"price": 127, "price_display": "127 US dollars", "round_trip_total": false,
"airline": "Tap Air Portugal", "airlines": ["Tap Air Portugal"], "stops": 0,
"depart_time": "8:00 PM", "arrive_time": "10:55 PM", "depart_day": "Monday, October 5",
"depart_airport": "Humberto Delgado Airport", "arrive_airport": "Heathrow Airport",
"origin": "LIS", "destination": "LHR", "duration": "2 hr 55 min", "duration_minutes": 175,
"layovers": null, "layover_airports": null, "overnight_layover": false,
"co2_kg": 123, "emissions_vs_typical": -7, "max_stops": null, "page": 1,
"google_url": "https://www.google.com/travel/flights?tfs=..."
}
Google flights scraper in Python, JavaScript and curl
Python
from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("kestrel/google-flights-prices").call(run_input={
"routes": ["LIS-LHR"], "departDate": "30 days", "sweepDays": 6, "currency": "EUR",
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
if row["type"] == "flight":
print(row["depart_date"], row["price"], row["airline"], row["stops"])
JavaScript (Node)
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('kestrel/google-flights-prices').call({
routes: ['JFK-LHR'], departDate: '14 days', seat: 'business', maxStops: 'nonstop',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((i) => i.type === 'flight').map((i) => [i.price, i.airline]));
curl
curl -X POST "https://api.apify.com/v2/acts/kestrel~google-flights-prices/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H 'Content-Type: application/json' \
-d '{"routes":["LIS-LHR"],"departDate":"30 days","maxResultsPerSearch":10}'
The same three calls are runnable files in the examples repository: examples/google-flights-prices.py|.js|.sh.
Limits and honest notes
- Google's list is what you get. This does not book, hold or price seats directly with airlines, and it does not see fares that only appear after login or in a corporate channel.
- Results are read in English. The parser reads Google's own English accessibility labels, which is why there is no language input.
currencyandmarketstill control the fares themselves — those are the two that change prices. - Prices include what Google shows. Taxes and carrier fees as Google presents them; baggage and seat fees are not in the number.
- Round-trip prices are the trip total, not per leg.
round_trip_totalmarks them so you never mix the two. - A currency swap fails the run rather than billing rows priced in something you did not ask for — some markets ignore
curr. - Google renders every itinerary twice on its own page. The run de-duplicates before billing, so you are never charged for its markup.
FAQ
Does it need a Google Flights API key or a Google account?
No. There is no public google flights api to hold a key for, and this uses none. No login, no cookies, no browser — it builds the same tfs query parameter Google puts in its own URLs and reads the page Google returns.
Can I get flight price history from Google Flights?
Not retroactively — Google does not publish history, and neither can this. What you can do is build it: schedule a run daily with a relative departDate, and every row lands timestamped. Two weeks of that is two weeks of flight price history for your routes that is yours to keep.
How do I find the cheapest day to fly?
Set sweepDays. {"departDate": "30 days", "sweepDays": 29} prices the same trip departing on each of the next 30 days; sort the flight rows by price and the answer is the top row. The status row for each date also carries cheapest, if you only want the daily minimum.
Can I set a flight price alert?
Yes, outside the actor. Schedule the run, connect it to n8n, Make or Zapier through Apify's integrations, and fire when price drops below your threshold. Because you keep every row, your alert can be smarter than Google's — "nonstop under $400 on any of these three routes", for example.
Does it support round trips and multi-city?
Round trips yes: set returnDate and every row prices both legs. Multi-city is not exposed as an input in this version — run each leg as its own one-way route if you need one.
Which cabins and passenger mixes work?
economy, premium_economy, business and first, and up to nine passengers across adults, children, infants in a seat and infants on a lap. Business and first return a genuinely different, smaller market — in testing JFK–LHR economy started at $282 and business at $1,469 on the same day.
Why do prices differ from what I see in my browser?
Three usual reasons: your market differs from your browser's country, your currency differs, or the fare simply moved — airline pricing changes through the day. Set market and currency explicitly and re-run to compare like for like; each row also carries the google_url that reproduces the exact search.
How many itineraries does one search return?
Usually 10–35 for a route and date, which is what Google itself lists. maxResultsPerSearch caps it lower when you only want the cheapest handful and want the run to cost less.
Can I use it as an airfare scraper for Skyscanner or Kayak specifically?
No — it reads Google Flights. That said, Google aggregates most of the same carriers and online travel agents those sites do, so for airfare price tracking the numbers are usually comparable, and you get them from one source with one schedule.
Is there a free tier?
Empty searches, failed searches and status rows are always free, so a run that finds nothing costs nothing beyond a fraction of a cent of platform compute. Paid rows start only when an itinerary is actually delivered. Apify's free plan includes monthly platform credit you can spend here.
How to use Google Flights Scraper
Ready-made runs you can open and start
Each one is a saved input on the Apify Store — open it, press Start, and it runs with the fields already filled in. All 163 across the suite.
| Ready-made run | What it does |
|---|---|
| Business Class Fares from Google Flights | Nonstop business class round trips on two transatlantic routes, with airline, cabin price, duration and layovers on every itinerary row. |
| Cheapest Day to Fly: 14-Day Calendar | One route, fourteen consecutive departure days, the return date shifting with each: a price calendar showing which day of the week is cheapest. |
| Google Flights API Free Alternative | Google has no public flights API. Two city-code round trips, 25 itineraries each, returned as JSON with no key and no per-search fee. |
| Nonstop Flight Search on One Route | maxStops nonstop drops every connection before billing, so a transcontinental route returns only the direct itineraries and what each carrier charges. |
| Flight Prices for a Family of Four | Two adults and two children on a fourteen-night half-term trip: every price is the total for the party, not a headline one-adult fare. |
| Scrape Google Flights for 5 One-Way Routes | Leave the return date empty and every row is a one-way fare: five routes out of one hub priced in a single run for a network comparison. |
| Airline Ticket Prices in Premium Economy | Premium economy on three long-haul Asian routes: the cabin sits between economy and business and is priced by a much smaller set of carriers. |
| Google Flights Data for the German Market | Fares and available airlines differ by market: two German transatlantic routes priced on the de market in euros, as a Frankfurt booker sees them. |
| Flight Data API: Who Flies a Route | Fifty itineraries on one Gulf route: every carrier, connection point and duration Google lists, which is a competitive map of the route. |
| Cheap Flights from Three London Airports | LHR-JFK, LGW-JFK and LHR-EWR on the same date: which London and New York airport pair is actually cheapest for the same trip. |
| Flight Price Monitoring on a Schedule | A cheap daily run on one long-haul round trip: relative dates never go stale, so the same query keeps tracking the same trip as it approaches. |
Related scrapers
Run Google Flights Scraper
The actor lives on the Apify Store, where the pricing tab carries the live per-row price and the input form has every field above: apify.com/kestrel/google-flights-prices