Google Flights Scraper – Airfare Data, $0.80/1,000 Flights
Pricing
from $0.50 / 1,000 flights
Google Flights Scraper – Airfare Data, $0.80/1,000 Flights
Turn a list of routes into a sheet of live Google Flights fares. Every row is one flight with its price, airline, flight number, local times, stops, layover airports and CO2. Pair origins with destinations, scan up to 60 departure dates, pull return legs. Searches with no fares cost nothing.
Pricing
from $0.50 / 1,000 flights
Rating
0.0
(0)
Developer
Dustin Griffie
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Security
Limited permissionsShare
Google Flights Scraper: airfare data at $0.80 per 1,000 flights
Give this Actor a few routes, or a few hundred, and it hands back Google Flights results as tidy rows you can sort, filter and chart. Each flight comes with what you would check before booking: the fare, the airline and flight number, when it leaves and lands in local time, how long it takes, where it stops and how much CO2 it burns compared with the usual flight on that route. Times come in local and UTC, and each flight lists its codeshare numbers, onboard Wi-Fi and power, and a link to its Google Flights booking page. A price calendar mode prices every departure day for up to 330 days in a single call per route. It runs on plain HTTP with no browser, and you pay only when a flight lands in your dataset.
What does this Google Flights scraper do?
You describe trips; the Actor asks Google Flights about each one and writes down what comes back.
A search is one route on one departure date (plus a return date for round trips). You can feed searches in three ways, and mix them:
- Routes such as
SEA-LAX,JFK-LHRorNYC-TYO. City codes (NYC,LON,PAR,TYO) cover every airport in that metro area. - Origins × destinations. List 3 origins and 4 destinations and you get all 12 pairs without typing them out.
- Date ranges. Pick a first date (a fixed day or "N days from today"), how many dates to try (up to 60) and the gap between them. A 30-day scan of one route is 30 searches.
For every search the Actor:
- Asks Google Flights' own data feed (the one its web app uses) for the whole flight list of that trip. On our test routes that is 70–200 flights in about half a second.
- If Google declines that request, it tries again from a fresh IP a few times, then falls back to reading the results page plus one airline-filtered page per carrier and merging them. That fallback is slower and finds fewer flights (35–60 on busy routes). Each row's
sourcefield says which way it was collected. Duplicates are dropped either way, so a flight never appears (or bills) twice. - For round trips, picks the cheapest outbound options and fetches the return flights that pair with them.
- Writes one row per flight, plus one free summary row per search with the cheapest fare, Google's verdict on the price, the usual price band and Google's daily fare history for roughly the last two months.
Switch mode to calendar and the job changes: each route returns one row per departure day with the cheapest fare Google knows for that day, up to 330 days ahead, and round trips use a fixed stay length.
Rows come out as JSON, CSV, Excel, XML or HTML from the dataset tab, or straight through the Apify API.
Which flight data do I get?
There are three kinds of rows, told apart by recordType.
Flight rows (recordType: "flight", billed)
| Field | What it holds |
|---|---|
price, currency, priceType | Total fare for all passengers you entered. priceType says whether it is a one-way or round-trip total. |
airlines, flightNumbers | Every carrier and flight number on the itinerary, e.g. ["UA 1833", "UA 1583"]. |
departureAirport, arrivalAirport | IATA codes of the first and last airport. |
departureTime, arrivalTime | Local times at each airport, ISO format without offset (2026-12-04T08:00). |
departureTimeUtc, arrivalTimeUtc, departureUtcOffset, arrivalUtcOffset, departureTimeZone, arrivalTimeZone | The same moments in UTC, with each airport's offset and IANA zone, worked out offline from a built-in table of about 7,900 airports (daylight saving included). null for the rare airport missing from the table. |
durationMinutes, duration | Door-to-door time, as minutes and as text. |
stops, layoverAirports, layovers | Stop count, the connecting airports and each layover's length. |
emissionsKg, typicalEmissionsKg, emissionsDiffPercent | Google's CO2 estimate for this itinerary and for a typical one on the route. |
aircraft, operatedBy | Plane types and the carrier actually flying the plane, when it differs. |
codeshareFlightNumbers | Other airlines' numbers sold on the same flights, e.g. ["AF 9656", "DL 5996"]. |
wifiOnAllLegs, powerOnAllLegs, inSeatVideoOnAllLegs | true when Google lists Wi-Fi, seat power or a seatback screen on every segment. false means Google did not list it, not that the plane surely lacks it. |
bookingUrl | Opens this exact itinerary on Google Flights' booking page, where the airline and agency offers are listed. Filled on one-way rows and round-trip return rows (both directions are known there). |
pricePerAdult | price divided by the number of adults, when every passenger is an adult; otherwise null. |
legs | One entry per flight segment with airport names, local and UTC times, airline code, aircraft, legroom, codeshares, an amenities object (wifi: free/paid, power: outlet/USB, video, seatType) and segment CO2 (turn off with includeLegs). |
resultRank, isBestFlight | Position in Google's order, and whether Google flagged it as a "best" pick. |
source, listSource | How the row was collected: api (Google's full list, listSource: "full_list"), page or page_airline_fanout (results page, listSource results_page or airline_filter). |
priceLevel, lowestPriceForSearch, typicalPriceLow, typicalPriceHigh | Google's price insight for this search, copied onto every row so a flat CSV is still useful. |
legType, returnDate, outboundFlightNumbers, outboundPrice | For round trips: outbound or return, and on return rows the outbound flight (numbers, airlines, times, stops) they pair with. |
googleFlightsUrl | Opens the same search on Google Flights. |
| search inputs | origin, destination, departureDate, cabinClass, passengers, country, scrapedAt. |
Here is a real nonstop row from a run on 4 Nov 2026 (legs trimmed to one):
{"recordType": "flight","route": "JFK-LHR","price": 300,"currency": "USD","priceType": "one way total for 1 passenger(s)","resultRank": 1,"isBestFlight": true,"source": "api","listSource": "full_list","pricePerAdult": 300,"airlines": ["Virgin Atlantic"],"flightNumbers": ["VS 26"],"codeshareFlightNumbers": ["AF 9656", "DL 5996", "KL 2505"],"departureTime": "2026-12-04T08:00","arrivalTime": "2026-12-04T20:10","departureTimeUtc": "2026-12-04T13:00:00Z","arrivalTimeUtc": "2026-12-04T20:10:00Z","duration": "7 hr 10 min","stops": 0,"emissionsKg": 369,"typicalEmissionsKg": 434,"emissionsDiffPercent": -15,"aircraft": ["Airbus A330-900neo"],"wifiOnAllLegs": true,"powerOnAllLegs": true,"legs": [{ "flightNumber": "VS 26", "aircraft": "Airbus A330-900neo", "legroom": "31 inches","amenities": { "wifi": "paid", "power": "outlet_and_usb", "video": "on_demand", "seatType": "average" } }],"priceLevel": "typical","typicalPriceLow": 170,"typicalPriceHigh": 470,"bookingUrl": "https://www.google.com/travel/flights/booking?tfs=…","cabinClass": "economy","departureDate": "2026-12-04"}
Search summary rows (recordType: "search", never billed)
One per search, turned on by includeSearchSummary. Searches that fail, find nothing or are invalid always get one, so you can see what happened to every search in the same table.
| Field | What it holds |
|---|---|
status, statusMessage | ok, no_results, invalid, failed, or a max-cost stop, with a plain-English reason. |
flightsFound, flightsSaved, nonstopFlights, airlinesFound | How big the route is. |
cheapestPrice, cheapestAirlines, cheapestFlightNumbers, cheapestDepartureTime, cheapestStops | The best fare in one place. |
priceLevel | Google's label: low, typical or high. |
usualPrice, typicalPriceLow, typicalPriceHigh | The price band Google considers normal for this trip. |
priceHistory | About 61 daily points ({date, price}) for the lowest fare on this exact search over the last two months. |
priceHistoryMin, priceHistoryMax, priceHistoryDays, priceHistoryFirstDate, priceHistoryLastDate | That history condensed into numbers you can filter on. |
source, apiAttempts, extraPagesFetched | Which method served the search, how many data-feed requests it took, and how many airline-filtered pages the fallback opened. |
From the same run, trimmed to the last three history points:
{"recordType": "search","route": "JFK-LHR","departureDate": "2026-12-04","status": "ok","flightsFound": 108,"nonstopFlights": 19,"cheapestPrice": 298,"cheapestAirlines": ["Aer Lingus"],"cheapestFlightNumbers": ["EI 104", "EI 152"],"priceLevel": "typical","usualPrice": 298,"typicalPriceLow": 170,"typicalPriceHigh": 470,"priceHistoryDays": 61,"priceHistoryMin": 291,"priceHistoryMax": 321,"priceHistory": [{ "date": "2026-11-02", "price": 298 },{ "date": "2026-11-03", "price": 298 },{ "date": "2026-11-04", "price": 298 }],"source": "api","apiAttempts": 1,"charged": false}
Price calendar rows (recordType: "calendar-day", calendar mode)
Set mode to calendar and calendarDays to how many departure days you want (1–330). Each route then gives one row per day that Google has a price for, plus a summary row with cheapestDate, cheapestPrice, highestPrice, medianPrice and daysWithPrice. It works for single journeys and for return trips, which keep the stay fixed at tripLengthDays. Stops, airline, cabin and passenger filters apply. A 330-day calendar took a few seconds per route in our runs. Each saved day costs $0.0001, so 60 days is $0.006 and a full 330 days $0.033 per route; days Google has no price for are not saved and cost nothing. Google's calendar stops about 330 days from today, and the exact last day can shift by one around midnight. If your range runs past it, the Actor ends the range on Google's last day instead of failing, and the summary row shows rangeShortenedToGoogleLimit: true with the dates it covered.
A real row from 4 Nov 2026:
{"recordType": "calendar-day","route": "JFK-LHR","tripType": "one_way","departureDate": "2026-11-25","dayOfWeek": "Wed","price": 304,"currency": "USD","isCheapestDay": false,"priceVsCheapestPercent": 18.8,"charged": true}
The same run's summary row found the cheapest day 144 days out: $256 on 29 March 2027, against a median of $300 across the 330 days.
The dataset has five views: Flights (one line per flight), Search summary & price history, Price calendar, Price by date (handy for date scans) and Legs, layovers & price insights (segments, UTC times, codeshares, amenities, booking links). Filter on recordType when you export if you want only one kind.
Ready-to-run examples
Each of these is a saved task you can open, tweak and run. All of them use relative dates, so they keep working on a schedule.
| Task | What it shows |
|---|---|
| Cheapest departure day: scan 30 days of fares on one route | One route for each of the next 30 days, cheapest flights plus a daily summary |
| Transatlantic round trips priced with their return flights | NYC and Boston to London, Paris and Dublin, ten nights, with return legs |
| Long-haul business class fares to watch every week | Four long-haul business routes with aircraft and legroom per segment |
| Nonstop flights for every origin × destination pair | Three origins × three destinations, nonstop only |
| Fares from one home airport to a dozen popular cities | One home airport to 12 cities; cheapest fare and usual band per city |
| Seven-night round trips, one departure a week for 8 weeks | Eight weekly departure dates for a week-long round trip |
| Cheapest fare calendar: every day for the next 6 months | Lowest one-way fare for every day over six months on three routes |
| Cheap flights under a set price from one city | Only fares under a set price from one city to several destinations |
| Round-trip fares for two adults and two kids | Two adults and two kids as one booking, with return flights |
| Lowest round-trip fare for every departure day, 11 months out | Lowest round-trip fare for every departure day, 11 months out |
A minimal input of your own looks like this:
{"routes": ["SEA-LAX", "JFK-LHR"],"departureInDays": 21,"numberOfDates": 7,"maxStops": "1","maxResultsPerSearch": 100}
That is 14 searches: two routes on seven consecutive dates, three weeks out, at most one stop.
Scraping Google Flights in three steps
- Say where and when. Fill in
routes(ororiginsanddestinations), then either adepartureDateordepartureInDays. Round trip? SwitchtripTypetoround_tripand add areturnDateor atripLengthDays. - Narrow it down if you like.
maxStops,cabinClass(from economy up to first),airlines(two-letter codes to keep),maxPrice, passengers (adults,children,infantsInSeat,infantsOnLap),currencyandcountry. Country matters: Google shows a slightly different market forgbthan forus. - Run it and export. Press Start, wait for the status line to count up, then download from the Output tab or read the dataset through the API.
A few settings change what you get back:
modepicksflights(default) orcalendar;calendarDayssets the calendar's length.completeResults(default on) asks for the route's full list. Turn it off to get only the shortlist on Google's first results page, which also keeps each search to a single page request.searchMethodisauto(data feed first, page fallback) orpage(always the slower results-page method).maxResultsPerSearch(default 100, max 500) caps flight rows per search. Rows follow Google's order, so a cap of 20 keeps the 20 Google ranks highest. Busy routes often have more than 100 flights in the full list; raise the cap to get them all, or lower it to pay for fewer.returnFlightsForCheapestOutbound(1 to 10) decides how many outbound picks get their return flights looked up.includeSearchSummaryadds the free summary row;includeLegsadds the per-segment detail.
Watching airfare on a schedule
Fares move several times a day, and the useful question is usually "is this cheaper than it was?". Two features make that easy.
Relative dates. Use departureInDays instead of a fixed date. A daily schedule with departureInDays: 30 always checks the trip a month out, so the series compares like with like.
History in every run. The summary row already carries about 60 days of Google's own price history for that search, plus the low / typical / high label. A single run tells you whether today's fare is near the bottom of its recent range, without you having collected anything beforehand.
To set it up, save your input as a task, open Schedules in Apify Console and pick a cron (daily at 06:00, every Monday, whatever suits). Point a webhook or an integration at the run's dataset and you can push new rows to Google Sheets, Slack, a database or email. A simple alert rule: notify when cheapestPrice is below typicalPriceLow, or when priceLevel turns low.
Scheduling costs nothing extra. Each scheduled run is billed like any other, by flights saved.
What a run costs
You pay per flight row saved to the dataset, per day saved in calendar mode, and a tiny fee each time the Actor starts. Summary rows, empty searches, invalid searches, failed searches and failed calendars are free.
| Your Apify plan | Per flight row | Per 1,000 flights | Per calendar day | Actor start |
|---|---|---|---|---|
| Free | $0.0008 | $0.80 | $0.0001 | $0.00005 |
| Starter | $0.0007 | $0.70 | $0.0001 | $0.00005 |
| Scale | $0.0006 | $0.60 | $0.0001 | $0.00005 |
| Business | $0.0005 | $0.50 | $0.0001 | $0.00005 |
Some sums, on the Free plan:
- One domestic route on one date at the default cap of 100 flights (our busy test routes all reached it): about 8 cents. With
maxResultsPerSearch: 40, about 3 cents. - A price calendar for one route: 60 days $0.006, the full 330 days $0.033.
- The same route checked for 30 dates with
maxResultsPerSearch: 10: 300 flights, about 24 cents. - A daily watch of 5 routes keeping the top 20 each: 100 flights a day, about $2.40 a month.
You stay in control of the bill. maxResultsPerSearch caps every search. Max cost per run in the run options is respected too: when the budget runs low, the Actor stops early, saves only what fits and marks the affected searches or calendars partial_max_cost or stopped_max_cost in their summary rows. Rows that weren't saved are never charged. Proxy traffic and compute are included in the price.
Calling it from code, n8n, Make or an AI agent
Anything you can click in Console you can also script. A Python example:
import osfrom apify_client import ApifyClientapify = ApifyClient(os.environ["APIFY_TOKEN"])payload = {"routes": ["BOS-SAN"], "departureInDays": 21, "maxResultsPerSearch": 50}finished = apify.actor("griffie/google-flights-scraper").call(run_input=payload)rows = apify.dataset(finished["defaultDatasetId"]).list_items().itemsflights = [r for r in rows if r["recordType"] == "flight"]summary = next(r for r in rows if r["recordType"] == "search")print(len(flights), "flights; cheapest", summary["cheapestPrice"], summary["priceLevel"])
The JavaScript client (apify-client) works the same way. For a one-shot HTTP call, POST your input JSON to https://api.apify.com/v2/acts/griffie~google-flights-scraper/run-sync-get-dataset-items with your token, and the response body is the result rows.
No-code tools. n8n, Make and Zapier all have Apify modules: choose "Run Actor", pick this one, paste your input and map the dataset fields onward. AI agents. Apify's MCP server exposes this Actor as a tool, which lets an assistant such as Claude or Cursor run it ("find me nonstop fares from SFO to Tokyo next month") and read the rows back. Keep maxResultsPerSearch modest for agents so the answer fits in context; the summary row alone is often enough.
Planning the hotel too? The sister Actor Google Hotels Prices Scraper returns nightly rates for the same kind of bulk city and date list.
Limits worth knowing
- The data feed is not always available. Google answers it from some IPs and declines from others. The Actor retries on fresh IPs with pauses between tries, and if Google keeps declining across a run it stops asking and uses the results-page method for the rest. That keeps the run going, at about 20 times the time per search and with fewer flights. Calendar mode has no page fallback, so a calendar that is still declined after several tries gets a
failedsummary row and costs nothing. - Speed. In our 20-search tests on 4 Nov 2026 (512 MB) every search was served by the data feed. A run of 7 one-way searches took 4–16 seconds, depending on how often Google declined the first try, and 6 round trips with their returns took 8–12 seconds. A fallback search takes 15–60 seconds.
- Booking links, not seller prices.
bookingUrlopens Google's booking page for the itinerary, where the airline and agencies are listed. The Actor does not read those individual offers. - City codes. Common metro codes (
NYC,LON,PAR,TYO,CHI,WASand about 15 more) go through the data feed. Other city codes use the results-page method. - Children and infants. On some routes Google returns fewer fares, or none, once children or lap infants are added. Try adults only if a search comes back empty.
- No multi-city yet. One-way and round trips only.
- Prices are a snapshot. Fares can change between the run and a booking, and Google sometimes shows slightly different prices by country and currency.
FAQ
Are prices per person?
price is the total for everyone you entered, as Google shows it, and priceType says so. When all passengers are adults, pricePerAdult gives the per-person figure. With children or infants their fares differ, so it is left empty.
How do round trips work? Outbound rows carry the round-trip total. The Actor then takes the cheapest outbound options (how many is up to you) and fetches the returns for each. Each return row repeats the full itinerary's total and names its outbound flight.
How do I find the cheapest day to fly?
Use calendar mode: "mode": "calendar" with calendarDays: 90 gives up to 90 rows, one per day, for $0.009, and the summary row names the cheapest. Sixty days costs $0.006 and the full 330 days $0.033 per route. When you also want the flights behind each day, use a date range instead (numberOfDates: 30, dateStepDays: 1) and sort the summary view by cheapestPrice.
How many flights per search?
Up to maxResultsPerSearch, which is 100 unless you change it. In our 4 Nov 2026 test of 20 searches with the cap raised to 200, domestic routes averaged about 155 flights per search, long-haul ones about 118 and round trips about 91 (outbound plus returns). With the page method alone the same routes gave 37–44.
Does it need residential proxies? No. It runs on Apify's datacenter proxy by default and retries on fresh IPs when Google hesitates. A residential fallback switch exists for unusually strict runs.
Can I change currency and market?
Yes. currency takes any ISO code (EUR, GBP, JPY) and country a two-letter market (de, gb, jp).
Are times local?
departureTime and arrivalTime are local at each airport, as Google shows them, so a red-eye can arrive "earlier" than it left. departureTimeUtc and arrivalTimeUtc give the same moments in UTC, so you can sort or subtract them directly.
What happens with a typo in an airport code?
That search gets a free summary row with status no_results or invalid and a short explanation; the rest of the run carries on.
Is scraping Google Flights legal?
The Actor reads only public fare and schedule information, the same thing anyone sees on Google Flights, and collects no personal data. Even so, you are responsible for how you use the results: check Google's terms and the rules in your country, and ask a lawyer if your use case is unusual. Questions, odd routes or a missing field? Tell us in the Issues tab and we'll look into it.