# Google Flights Scraper - Flight Prices, Airlines, Stops & Times (`rel8ble/google-flights-scraper`) Actor

Use this to get Google Flights prices for a route and date. Input: origin and destination IATA codes (e.g. JFK, LAX), departure date, optional return date, passengers, cabin. One result = one itinerary: total price, airlines, flight numbers, stops, layovers, times, CO2. $0.50 per 1,000 results.

- **URL**: https://apify.com/rel8ble/google-flights-scraper.md
- **Developed by:** [Giovanni Rich](https://apify.com/rel8ble) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Google Flights Scraper & API - Flight Prices and Airfare Data

Scrape Google Flights and get flight prices as clean JSON: this Google Flights API returns one-way and round-trip itineraries with the **total price**, airlines, flight numbers, stops, layovers, durations, local departure/arrival times **with UTC offsets**, aircraft, legroom and CO2 emissions.
Use it as a fast, cheap flight price scraper for fare tracking, travel apps and airfare data research - no browser, no Google API key, a typical search returns 10-40 itineraries in about one second.

### How to use

1. Enter a route: `origin` and `destination` airport codes (e.g. `JFK` and `LAX`), a departure date (empty = 30 days from today) and, for a round trip, a return date.
2. Click **Start**. Each search takes a few seconds.
3. Download the flights as JSON, CSV or Excel from the dataset, or call the actor from your code through the Apify API.

### Use cases

- **Fare tracking and price alerts**: run it on a schedule for your routes and get notified when the price drops. `priceLevel` gives Google's own low / typical / high verdict.
- **Travel apps and AI agents**: feed real itineraries into a booking assistant, chatbot or comparison tool.
- **Airfare market research**: compare airlines, nonstop availability, connection points and price levels across routes and dates.
- **Corporate travel**: price a list of trips (many routes and dates in one run) in business or economy.
- **Sustainability reporting**: per-flight and per-segment CO2 estimates, plus the difference from the route's typical emissions.

### Input

| Field | What it does |
|---|---|
| `origin`, `destination` | IATA airport code (`JFK`), several airports comma-separated (`JFK,EWR,LGA`), or a Google city id (`/m/02_286` = New York, all airports). |
| `departureDate` | `YYYY-MM-DD`. Empty = 30 days from today. |
| `returnDate` | `YYYY-MM-DD` for a round trip. Empty = one-way. |
| `searches` | Many routes/dates in one run: `[{"origin":"JFK","destination":"LAX","departureDate":"YYYY-MM-DD","returnDate":"YYYY-MM-DD"}, ...]` |
| `adults`, `children`, `infantsInSeat`, `infantsOnLap` | Passengers (max 9). Prices are totals for everyone. |
| `cabinClass` | `economy`, `premium_economy`, `business`, `first`. |
| `maxStops` | `any`, `0` (nonstop), `1`, `2`. |
| `airlines` | Only these airlines (`AA`, `DL`, `BA`...) or alliances (`STAR_ALLIANCE`, `ONEWORLD`, `SKYTEAM`). |
| `currency` | Any 3-letter code: `USD`, `EUR`, `GBP`, `JPY`... |
| `maxResults` | Itineraries per search (0 = all Google shows). |
| `returnFlightsForTopOutbound` | Round trips: how many of the top outbound flights to expand into full outbound + return pairs (default 3). `0` = outbound options only. |

### Input example

One-way, next month (leaving `departureDate` out searches 30 days from today):

```json
{
    "origin": "JFK",
    "destination": "LAX",
    "adults": 1,
    "cabinClass": "economy",
    "maxStops": "any",
    "currency": "USD",
    "maxResults": 10
}
```

Round trip with a fixed date and only nonstop flights:

```json
{
    "origin": "SFO",
    "destination": "ORD",
    "departureDate": "2026-10-20",
    "returnDate": "2026-10-23",
    "maxStops": "0",
    "returnFlightsForTopOutbound": 3,
    "currency": "USD"
}
```

### Output example

One row per itinerary. This is a real row from a test run (Charlotte to Tokyo Narita, one-way), lightly trimmed:

```json
{
  "searchId": "CLT-NRT 2026-12-03",
  "tripType": "one_way",
  "origin": "CLT",
  "destination": "NRT",
  "cabinClass": "economy",
  "passengers": { "adults": 1, "children": 0, "infantsInSeat": 0, "infantsOnLap": 0 },
  "currency": "USD",
  "position": 1,
  "category": "best",
  "price": 1014,
  "priceLevel": "typical",
  "airlines": ["Air Canada"],
  "airlineCodes": ["AC"],
  "flightNumbers": ["AC 8746", "AC 9"],
  "stops": 1,
  "totalDurationMinutes": 1055,
  "totalDuration": "17 hr 35 min",
  "departureAirport": "CLT",
  "departureAirportName": "Charlotte Douglas International Airport",
  "departureDateTime": "2026-12-03T08:55:00-05:00",
  "arrivalAirport": "NRT",
  "arrivalAirportName": "Narita International Airport",
  "arrivalDateTime": "2026-12-04T16:30:00+09:00",
  "arrivalDayOffset": 1,
  "layovers": [
    { "airport": "YYZ", "airportName": "Toronto Pearson International Airport", "city": "Toronto", "durationMinutes": 98, "durationText": "1 hr 38 min" }
  ],
  "segments": [
    {
      "flightNumber": "AC 8746", "airline": "Air Canada", "airlineCode": "AC",
      "operatedBy": "Air Canada Express - Jazz", "aircraft": "Embraer 175",
      "departureAirport": "CLT", "arrivalAirport": "YYZ",
      "departureDateTime": "2026-12-03T08:55:00-05:00", "arrivalDateTime": "2026-12-03T10:57:00-05:00",
      "durationMinutes": 122, "legroom": "31 in", "emissionsKg": 142
    },
    {
      "flightNumber": "AC 9", "airline": "Air Canada", "airlineCode": "AC",
      "operatedBy": null, "aircraft": "Boeing 777",
      "departureAirport": "YYZ", "arrivalAirport": "NRT",
      "departureDateTime": "2026-12-03T12:35:00-05:00", "arrivalDateTime": "2026-12-04T16:30:00+09:00",
      "durationMinutes": 835, "legroom": "31 in", "emissionsKg": 582
    }
  ],
  "emissionsKg": 724,
  "typicalEmissionsKg": 817,
  "emissionsDifferencePercent": -11,
  "returnFlight": null,
  "googleFlightsUrl": "https://www.google.com/travel/flights/booking?tfs=...",
  "scrapedAt": "2026-09-24T05:14:34.715Z"
}
```

(Some fields shortened here; the dataset also has `searchDepartureDate`, `searchReturnDate`, `departureDate`, `departureTime`, `arrivalDate`, `arrivalTime` and airport names on every segment.)

**Round trips**: `price` is the full round-trip total and `returnFlight` holds the return leg with the same fields (airlines, flight numbers, segments, layovers, times). `googleFlightsUrl` opens the exact outbound + return pair on Google Flights' booking page. Round-trip rows also carry `outboundPosition` and a `priceNote`.

`category` is `best` for the flights Google ranks as "Best", `other` for the rest. `priceLevel` is Google's own verdict for the route and date: `low`, `typical` or `high`.

A `RUN_SUMMARY` record in the key-value store lists, per search: results, itineraries found, price level and why it stopped.

### Pricing

Pay per result: **$0.50 per 1,000 results** (one result = one flight itinerary row).

- 1,000 results = $0.50
- 10,000 results = $5.00

A one-way search usually returns 10-40 itineraries, so a single route/date costs about $0.005-$0.02. The Apify free plan includes $5 of monthly credit, enough to try the actor on real routes.

### Integrations

- **Apify API**: start runs and fetch results over REST, or with the official JavaScript and Python clients.
- **No-code**: connect to Make, Zapier, n8n and Google Sheets to push fares into spreadsheets, alerts or workflows.
- **Webhooks**: get a call when a run finishes (e.g. to trigger a price-drop alert).
- **Schedules**: run the same searches daily or hourly from the Apify Console.
- **MCP for AI agents**: the Apify MCP server (https://mcp.apify.com) lets Claude, ChatGPT, Cursor and other agents call this Google Flights scraper as a tool.

### How round trips work

Google Flights prices a round trip as a pair. First it lists outbound flights, each with the cheapest round-trip price that includes it; after you pick one, it lists the returns with the final total. This actor does the same: it lists outbound flights, then fetches the returns for the top `returnFlightsForTopOutbound` outbound flights (Google's "best" order) and outputs one row per complete pair. Set it to `0` if you only need the outbound list with "from" prices (1 request per search).

### Speed and cost

- One-way search: 1 request, about 1 second, 10-40 itineraries.
- Round trip with the default of 3 expanded outbound flights: 4 requests, typically 25-40 complete round trips.
- No browser, so it runs fine at 256 MB memory.

### Reliability

- Plain HTTP with rotating proxy sessions. Blocked or captcha responses are detected, the session is retired and the request retried on a new IP with backoff.
- If a round-trip return lookup fails after all retries, you still get the outbound row (with `returnFlight: null` and a `returnFlightsError`), not a crashed run.
- Inputs are checked before any request is made (bad airport codes, past dates, more than 9 passengers), with a clear error message.
- Runs survive migrations: progress is saved and resumed.

### FAQ

**Is it legal to scrape Google Flights?** The actor only collects publicly visible flight search results - no logins and no personal data. You are responsible for how you use the data: respect Google's terms of service and applicable laws such as GDPR. This is not legal advice; ask a lawyer if you are unsure.

**How does it avoid blocks?** It sends plain HTTP requests with realistic Chrome desktop headers through Apify Proxy, using a pool of rotating sessions. Captcha pages, "unusual traffic" pages, 401/403/429 responses and empty pages are detected; the session is retired and the request is retried on a new IP with backoff (6 retries by default, configurable). If you run many searches and still see blocks, switch the proxy group to RESIDENTIAL.

**What are the limits?** Up to 9 passengers per search, about 11 months ahead, and whatever is on Google's initial results page (typically 10-40 one-way options per search). Round trips expand up to 30 outbound flights. Multi-city trips, per-agency booking prices and baggage fees are not supported (see Limits below).

**Is there an official Google Flights API?** No public one - Google shut down its QPX Express flight API in 2018. This actor reads the same results the Google Flights website shows, so you can use it as a Google Flights API.

**Which airports can I use?** Any IATA airport code Google Flights knows. Use commas for several airports on one side (`JFK,EWR,LGA` or `LHR,LGW,STN`).

**Are the prices real?** They are the prices Google Flights shows for your passengers, cabin and currency at the time of the run. Fares change constantly; `scrapedAt` tells you when each row was captured.

**Are times local?** Yes. `departureDateTime` and `arrivalDateTime` are local airport times with the UTC offset (for example `2026-12-04T16:30:00+09:00`), so you can compute real elapsed times and time zones.

**Do I get booking links?** Each row has `googleFlightsUrl`, which opens that itinerary on Google Flights where the airline and travel-agency booking options are listed. Booking-option prices per agency are not included.

**Can I search a whole month?** Put one entry per date in `searches`. Each search is one request (plus return lookups for round trips).

**Why fewer results than on the website?** Google sometimes loads extra "other flights" after the first screen. The actor returns everything that is in the initial results page (in tests: 36 JFK-LAX one-way options, 18 Madrid-Barcelona, 7 Charlotte-Tokyo).

**Do I need a proxy?** Apify Proxy (the default) works. If you run a lot of searches and see blocks in the log, switch the proxy group to RESIDENTIAL.

### Limits

- Multi-city (open-jaw with 3+ legs) searches are not supported yet; one-way and round trip are.
- Per-agency booking prices (Expedia vs airline, etc.) and baggage-fee details are not extracted.
- Google only sells about 11 months ahead.
- At most 9 passengers per search (Google Flights' own limit).

# Actor input Schema

## `origin` (type: `string`):

Departure airport. A 3-letter IATA code ("JFK"), several comma-separated ("JFK,EWR,LGA"), or a Google city id ("/m/02\_286" = all New York airports). Always set it for your route; if omitted the demo route JFK-LAX is used. Ignored when searches is set.

## `destination` (type: `string`):

Arrival airport. A 3-letter IATA code ("LAX"), several comma-separated ("LHR,LGW"), or a Google city id. Always set it; if omitted "LAX" is used. Ignored when searches is set.

## `departureDate` (type: `string`):

Optional. Outbound date, format YYYY-MM-DD, e.g. "2026-12-03"; today up to ~11 months ahead. Omit to search 30 days from today.

## `returnDate` (type: `string`):

Optional. Return date for a round trip, format YYYY-MM-DD, on or after departureDate. Omit for a one-way search.

## `searches` (type: `array`):

Optional. Many routes or dates in one run: JSON array of objects {"origin": "JFK", "destination": "LAX", "departureDate": "2026-12-03", "returnDate": "2026-12-10"} (returnDate optional). When set, origin/destination/dates above are ignored; passengers, cabin and filters apply to all.

## `adults` (type: `integer`):

Optional. Passengers aged 12+, integer 1-9. Default 1. Prices are totals for all passengers; max 9 passengers in total.

## `children` (type: `integer`):

Optional. Children aged 2-11, integer 0-8. Default 0. Counts toward the 9-passenger limit.

## `infantsInSeat` (type: `integer`):

Optional. Infants under 2 with their own seat, integer 0-8. Default 0. Counts toward the 9-passenger limit.

## `infantsOnLap` (type: `integer`):

Optional. Infants under 2 on a lap, integer 0-8, at most one per adult. Default 0.

## `cabinClass` (type: `string`):

Optional. Cabin to price: "economy" (default), "premium\_economy", "business" or "first".

## `maxStops` (type: `string`):

Optional. Maximum stops each way, as a string: "any" (default), "0" (nonstop only), "1" or "2".

## `airlines` (type: `array`):

Optional. Only these airlines: list of 2-character IATA codes (\["AA", "DL", "BA"]) or alliances ("STAR\_ALLIANCE", "ONEWORLD", "SKYTEAM"). Omit for all airlines.

## `currency` (type: `string`):

Optional. 3-letter ISO 4217 currency code for prices, e.g. "USD", "EUR", "GBP". Default "USD".

## `maxResults` (type: `integer`):

Optional. Maximum itineraries per search, integer >= 0. Default 50; 0 = all Google shows (typically 10-40 one-way). You pay per itinerary.

## `returnFlightsForTopOutbound` (type: `integer`):

Optional, round trips only. Fetch return options for the top N outbound flights and output one row per full round trip, integer 0-30. Default 3. 0 = outbound rows only, each with Google's cheapest round-trip price. Each N is one extra request.

## `language` (type: `string`):

Optional. Google interface language code (hl), e.g. "en", "de". Default "en" (most consistent field values).

## `country` (type: `string`):

Optional. 2-letter lowercase country code (gl) Google searches from, e.g. "us", "gb", "de". Can change prices and fares shown. Default "us".

## `maxConcurrency` (type: `integer`):

Optional, advanced. Number of parallel requests, integer 1-20. Default 5. Leave unset unless the run is very large.

## `maxRequestRetries` (type: `integer`):

Optional, advanced. Retries per failed or blocked request, integer 0-20; each retry uses a new proxy session. Default 6. Leave unset.

## `proxyConfiguration` (type: `object`):

Optional, advanced. Apify Proxy settings object, e.g. {"useApifyProxy": true}. Default: Apify Proxy on (datacenter). Leave unset; switch to {"useApifyProxy": true, "apifyProxyGroups": \["RESIDENTIAL"]} only if the run log shows repeated blocks.

## Actor input object example

```json
{
  "origin": "JFK",
  "destination": "LAX",
  "adults": 1,
  "children": 0,
  "infantsInSeat": 0,
  "infantsOnLap": 0,
  "cabinClass": "economy",
  "maxStops": "any",
  "currency": "USD",
  "maxResults": 10,
  "returnFlightsForTopOutbound": 3,
  "language": "en",
  "country": "us",
  "maxConcurrency": 5,
  "maxRequestRetries": 6,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `flights` (type: `string`):

All itineraries found, with price, airlines, flight numbers, stops, layovers, times and emissions.

## `summary` (type: `string`):

Per-search counts, price level and stop reasons.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "origin": "JFK",
    "destination": "LAX",
    "maxResults": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("rel8ble/google-flights-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "origin": "JFK",
    "destination": "LAX",
    "maxResults": 10,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("rel8ble/google-flights-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "origin": "JFK",
  "destination": "LAX",
  "maxResults": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call rel8ble/google-flights-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rel8ble/google-flights-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/eT4rStuUtmx12Z1tW/builds/HNWVjemXAKoTx1JHL/openapi.json
