Google Flights Scraper
Under maintenancePricing
Pay per usage
Google Flights Scraper
Under maintenanceScrape Google Flights itineraries as flat rows: live price, airlines, departure/arrival times, duration, stops, layovers, aircraft, CO2 estimate, and a shareable deep link. One-way or round-trip, any cabin class or currency. Pay only for delivered rows - failed fetches cost nothing.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Aaron S
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
4 days ago
Last modified
Categories
Share
Get live Google Flights prices as flat, ready-to-use rows - one row per itinerary, with airlines, times, duration, stops, layovers, aircraft, and CO2 estimates. One-way or round-trip, any cabin class, any currency. No charge for failed fetches.
Try it
Paste this into the input editor and hit Run:
{"origin": "LHR","destination": "JFK","departDate": "2026-09-25","returnDate": "","adults": 1,"cabinClass": "economy","currency": "GBP","maxItems": 50}
Input fields
| Field | Type | Values | Notes |
|---|---|---|---|
origin | string | 3-letter IATA code, e.g. LHR, JFK, NYC | Airport codes and metro/city codes both work |
destination | string | 3-letter IATA code | Same as origin |
departDate | string | YYYY-MM-DD | Must be today or later |
returnDate | string | YYYY-MM-DD or empty | Empty = one-way. When set, rows are departing-flight options priced as round-trip totals (how Google Flights itself works) |
adults | integer | 1-9 | Default 1 |
cabinClass | string | economy | premium_economy | business | first | Default economy |
currency | string | ISO code, e.g. USD, GBP, EUR | Prices returned in this currency |
maxItems | integer | e.g. 50 | Caps rows delivered before the run stops |
proxyGroups | array | e.g. ["RESIDENTIAL"] | RESIDENTIAL (default) recommended - Google blocks datacenter IPs on the Flights surface |
One query returns the complete result set for that route and date (typically 10-30 itineraries) in a single request - there is no pagination to pay for.
Output
Flat rows, one per itinerary. No nested objects to unpack - multi-leg details come as compact |-delimited strings. Real example row (LHR-JFK one-way, economy):
{"origin": "LHR","destination": "JFK","departDate": "2026-09-25","returnDate": "","cabinClass": "economy","adults": 1,"currency": "GBP","fetchedAt": "2026-08-26T12:00:00.000Z","category": "best","price": 602,"priceCurrency": "GBP","airlineCodes": "B6","airlineNames": "JetBlue","departureAirport": "LHR","departureTime": "2026-09-25 08:15","arrivalAirport": "JFK","arrivalTime": "2026-09-25 11:19","durationMinutes": 484,"stops": 0,"layovers": "","flightNumbers": "B62220","legs": "B62220 LHR 2026-09-25 08:15 -> JFK 2026-09-25 11:19","aircraft": "Airbus A321neo","co2Grams": 537000,"co2TypicalGrams": 484000,"deepLink": "https://www.google.com/travel/flights/search?tfs=GhoSCjIwMjYtMDktMjVqBRIDTEhScgUSA0pGS0IBAUgBmAEC&hl=en&curr=GBP"}
A connecting itinerary fills the multi-leg fields:
{"airlineNames": "Tap Air Portugal","price": 519,"stops": 1,"layovers": "LIS 490m","flightNumbers": "TP1363 | TP209","legs": "TP1363 LHR 2026-09-25 06:00 -> LIS 2026-09-25 08:45 | TP209 LIS 2026-09-25 16:55 -> JFK 2026-09-25 20:05","durationMinutes": 1145}
categoryisbest(Google's ranked picks) orother(the rest of the result set).deepLinkopens the exact same search in Google Flights - hand it to users for booking.co2Gramsis Google's per-passenger CO2e estimate for the itinerary;co2TypicalGramsis the route-typical value it is compared against.
Queries that fail after retries are logged to a separate google-flights-errors dataset (origin, destination, departDate, reason, fetchedAt) instead of leaving a silent gap in your results.
Coming from fast-flights?
The fast-flights Python library proves this route works - but you run it, patch it when Google changes internals, and supply your own unblocked IPs. This actor is the same server-rendered ?tfs= route as a managed service: residential proxy rotation, session-scoped cookies, retries with identity rotation, block detection, and flat rows with layovers and flight numbers already extracted.
| fast-flights | This actor |
|---|---|
FlightData(date=..., from_airport="LHR", to_airport="JFK") | "origin": "LHR", "destination": "JFK", "departDate": ... |
Passengers(adults=2) | "adults": 2 |
seat="business" | "cabinClass": "business" |
trip="round-trip" + second FlightData | just set "returnDate" |
| bring your own proxy | residential rotation built in |
Result.flights[n].price | flat rows with price, layovers, flight numbers, CO2 |
How this compares
| This actor | Typical Flights actors on the Store | |
|---|---|---|
| Charge on failed queries | Never - only delivered rows are billed | Often bill per run or per started query |
| Actor start | Free - no per-run fee | Some charge a flat fee before any data lands |
| Output shape | Flat rows, one per itinerary | Frequently nested per-search JSON you have to unpack |
| Reliability approach | Session rotation (Crawlee session pool), bounded retries with identity rotation, block detection | Not usually documented in the listing |
Pricing
Pay-per-event, priced on delivered rows: you're billed only once itinerary rows land in your dataset. Starting a run costs nothing. If a query fails after retries, it goes to the errors dataset instead, and you pay nothing for it.
Using the API
Apify API (HTTP)
curl "https://api.apify.com/v2/acts/meticulous_ground~google-flights-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"origin": "LHR","destination": "JFK","departDate": "2026-09-25","currency": "GBP"}'
JavaScript (apify-client)
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('meticulous_ground/google-flights-scraper').call({origin: 'LHR',destination: 'JFK',departDate: '2026-09-25',returnDate: '2026-10-02',cabinClass: 'economy',currency: 'GBP',});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Python (apify-client)
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("meticulous_ground/google-flights-scraper").call(run_input={"origin": "EDI","destination": "LHR","departDate": "2026-09-25","currency": "GBP",})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item)
Run one query per Actor call - each call returns that route and date's complete itinerary set.