kestrel actors docs

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

EventWhat it isPriceCharged for
flightItinerary row$0.005One 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.

FieldTypeDefaultWhat it does
routesarrayRoutes 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.
departDatestringrequiredYYYY-MM-DD, or relative so schedules never go stale: "30 days", "6 weeks", "tomorrow". Past dates are rejected — Google would silently price another day.
returnDatestringLeave 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.
sweepDaysinteger00 = 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.
seatstring (enum)"economy"Cabin to price. Business and first return a different, smaller market than economy. One of: economy, premium_economy, business, first.
adultsinteger1Adult passengers. Prices are the total for everyone travelling. Range 1-9.
childreninteger0Children aged 2 to 11 in their own seat. Range 0-8.
infantsSeatinteger0Infants under 2 travelling in their own seat. Range 0-8.
infantsLapinteger0Infants under 2 travelling on an adult's lap. Range 0-8.
maxStopsstring (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.
maxResultsPerSearchinteger00 = 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.
currencystring"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.
marketstring"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.
sessionsinteger4How many proxy sessions (egress IPs) run in parallel. More is faster; each one is paced separately. Range 1-16.
perIpnumber0.5Pace for each session. Google tolerates about 0.5/s per IP; raising it causes retries, not speed. Range 0.1-2.
proxyConfigurationobject{"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.

FieldTypeWhat it holds
typestringRow type: flight or status.
routestringThe route as given, e.g. "LIS-LHR".
origin_querystringOrigin code as searched.
destination_querystringDestination code as searched.
depart_datestringDeparture date, YYYY-MM-DD.
return_datestringReturn date for round trips, null for one-way.
tripstringone_way or round_trip.
seatstringCabin priced: economy, premium_economy, business or first.
adultsintegerAdults the price covers.
childrenintegerChildren the price covers.
infantsintegerInfants the price covers (seat + lap).
currencystringCurrency of the price (ISO code), as Google actually priced it.
max_stopsintegerStop limit applied to the search, null when unrestricted.
rankintegerPosition in Google's ranking for the search; 1 is its top pick.
pricenumberPrice for all passengers. For round trips this is the total for both legs.
price_displaystringPrice exactly as Google states it, e.g. "127 US dollars".
round_trip_totalbooleanTrue when the price covers both legs of a round trip.
airlinestringOperating airline; the first when several operate the itinerary.
airlinesarrayEvery airline operating the itinerary.
stopsintegerNumber of stops; 0 is nonstop.
depart_timestringDeparture time, local to the origin.
depart_daystringDeparture day as Google states it.
arrive_timestringArrival time, local to the destination.
arrive_daystringArrival day as Google states it — later than the departure day on overnight flights.
depart_airportstringFull name of the origin airport.
arrive_airportstringFull name of the destination airport.
originstringOrigin airport code on the itinerary.
destinationstringDestination airport code on the itinerary.
durationstringTotal travel time as Google states it, e.g. "2 hr 55 min".
duration_minutesintegerTotal travel time in minutes — the sortable form.
layoversarrayEach layover: index, of, minutes, airport, city.
layover_airportsarrayLayover airport names, in order.
overnight_layoverbooleanTrue when Google flags an overnight layover.
co2_kgintegerGoogle's carbon estimate for the itinerary, in kilograms.
emissions_vs_typicalintegerPercent above or below the typical emissions for the route.
google_urlstringThe Google Flights URL for this exact search — opens the same results.
searchesintegerStatus rows: searches run for this route and date.
flightsintegerStatus rows: itinerary rows delivered.
duplicatesintegerStatus rows: itineraries already delivered by an overlapping search, not billed again.
cheapestnumberStatus rows: lowest price found for this route and date.
statusstringStatus rows: ok, no_results or error.
errorstringStatus rows: why the search failed, null when it did not.
fetched_atstringUTC 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. currency and market still 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_total marks 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 runWhat it does
Business Class Fares from Google FlightsNonstop 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 CalendarOne 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 AlternativeGoogle 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 RoutemaxStops 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 FourTwo 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 RoutesLeave 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 EconomyPremium 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 MarketFares 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 RouteFifty 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 AirportsLHR-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 ScheduleA 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.

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