# Google Flights Scraper: Fares, Schedules, Stops and Round Trips (`cozybit/google-flights-scraper`) Actor

Google Flights scraper, no browser: prices for your route, dates, passengers and cabin, with times, duration, stops, layovers, each leg's flight number and aircraft, and CO2. One way or round trip, many dates per run for cheapest-day searches. Trial: 0.01 USD per 1,000 itineraries until 30 Nov 2026.

- **URL**: https://apify.com/cozybit/google-flights-scraper.md
- **Developed by:** [Cozybit](https://apify.com/cozybit) (community)
- **Categories:** Travel, E-commerce, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.01 / 1,000 flight itineraries

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: prices, schedules and connections for any route and date

Get flight options and prices from Google Flights as clean records, without a browser and without a Google account. For each route and date you get the itineraries Google shows before "View more flights":

- **Price** for your whole party and trip (one way or round trip), in the currency you choose.
- **Schedule**: departure and arrival times, total duration, number of stops and each layover with its airport and length.
- **Flights**: every leg with airline, flight number, aircraft, legroom, times and on-board amenities (Wi-Fi, power, entertainment).
- **Bags and price level**: carry-on and checked bags included in the fare, and whether Google rates prices for the search as low, typical or high.
- **Emissions**: CO2 estimate for the itinerary and the typical value for the route.
- Whether Google ranks the itinerary among its "best" options.
- Optional **fare calendar**: the cheapest fare for every day over up to 180 days, one record per day.

Typical uses: fare monitoring for routes you sell or fly, finding the cheapest date in a range, route and schedule research, travel-deal sites.

Prices include all platform costs: you pay per itinerary returned and nothing for proxies or compute.

### Input

| Field | What it does | Default |
|---|---|---|
| Routes | 1-100 routes as `FROM-TO` with three-letter airport or city codes, such as `SFO-LAX`, `LON-NYC` | required |
| Departure dates | Up to 30 dates (`YYYY-MM-DD`, or a time from the run date such as `3 weeks`; up to 330 days ahead); each route is searched for each date | 14 days from today |
| Return after days | 0 for one way; 1-30 for a round trip returning that many days later | 0 (one way) |
| Adults, children, lap infants | 1-9 adults, up to 8 children, up to one lap infant per adult | 1 adult |
| Cabin class | Economy, premium economy, business or first | economy |
| Maximum stops | Any, nonstop, at most 1 or at most 2 | any |
| Currency | Any currency Google supports, such as `USD`, `EUR`, `GBP`, `INR`, `JPY` | `USD` |
| Search country | The Google market to search from, such as `US`, `DE`, `GB` | `US` |
| Maximum itineraries per search | 1-200 | 100 |
| Fare calendar (days) | 1-180 to get the cheapest fare for each day instead of itineraries (see below); 0 is off | 0 |

Example: cheapest day to fly London to New York in business class, four Fridays, prices in pounds:

```json
{
  "routes": ["LON-NYC"],
  "departureDates": ["2027-01-08", "2027-01-15", "2027-01-22", "2027-01-29"],
  "cabinClass": "business",
  "currency": "GBP",
  "country": "GB"
}
```

Example: round trip Berlin-Lisbon for a week, two adults:

```json
{ "routes": ["BER-LIS"], "departureDates": ["2027-04-02"], "returnAfterDays": 7, "adults": 2, "currency": "EUR", "country": "DE" }
```

### Output

One record per itinerary. Example (round trip, one stop):

```json
{
  "route": "BER-LIS", "origin": "BER", "destination": "LIS",
  "departure_date": "2026-11-29", "return_date": "2026-12-06", "trip_type": "round_trip",
  "position": 2, "is_best": true, "status": "ok", "error": null,
  "price": 209, "currency": "EUR", "typical_price_low": 180, "typical_price_high": 280, "price_level": "typical",
  "carry_on_bags_included": 1, "checked_bags_included": 0,
  "passengers": { "adults": 1, "children": 0, "infants_on_lap": 0 }, "cabin_class": "economy",
  "airline_codes": ["KL"], "airlines": ["KLM"],
  "departure_airport": "BER", "arrival_airport": "LIS",
  "departure_time": "2026-11-29T06:00", "arrival_time": "2026-11-29T10:30", "duration_minutes": 330,
  "stops": 1,
  "layovers": [{ "airport": "AMS", "airport_name": "Amsterdam Airport Schiphol", "city": "Amsterdam", "minutes": 65 }],
  "legs": [
    { "airline_code": "KL", "airline": "KLM", "flight_number": "1770", "operated_by": null, "from": "BER", "from_name": "Berlin Brandenburg Airport",
      "to": "AMS", "to_name": "Amsterdam Airport Schiphol", "departure_time": "2026-11-29T06:00", "arrival_time": "2026-11-29T07:25",
      "duration_minutes": 85, "aircraft": "Airbus A321neo", "legroom": "29 in", "amenities": ["In-seat USB outlet"] },
    { "airline_code": "KL", "airline": "KLM", "flight_number": "1579", "operated_by": null, "from": "AMS", "from_name": "Amsterdam Airport Schiphol",
      "to": "LIS", "to_name": "Humberto Delgado Airport", "departure_time": "2026-11-29T08:30", "arrival_time": "2026-11-29T10:30",
      "duration_minutes": 180, "aircraft": "Airbus A321neo", "legroom": "29 in", "amenities": ["Wi-Fi for a fee", "In-seat USB outlet"] }
  ],
  "co2_grams": 172000, "typical_co2_grams": 217000,
  "source_url": "https://www.google.com/travel/flights/search?tfs=...&hl=en&gl=de&curr=EUR",
  "booking_url": "https://www.google.com/travel/flights/search?tfs=...&hl=en&gl=de&curr=EUR",
  "booking_token": "Google-provided itinerary token...",
  "scraped_at": "2026-10-30T18:08:57.882Z"
}
```

- Times are local to each airport, as on Google Flights.
- `price` covers all passengers. For round trips it is the round-trip total, and the record describes the outbound flights (as on Google Flights before you pick a return).
- `price` is `null` when Google shows "price unavailable" for an itinerary.
- `typical_price_low` and `typical_price_high` are Google's typical price bounds for the search, in your chosen currency, or `null` when Google omits them.
- `price_level` is Google's own rating of prices for the search (route and date): `low`, `typical` or `high`, the same on every itinerary of that search, or `null` when Google gives no rating we recognise.
- `carry_on_bags_included` and `checked_bags_included` are the bag counts Google shows for the fare, or `null` when Google gives no count (often on international and premium fares).
- Each leg's `amenities` lists Google's labels, such as `Free Wi-Fi`, `Wi-Fi for a fee`, `In-seat power & USB outlets`, `On-demand video`, `Live TV` or `Stream media to your device`; `[]` when Google lists none.
- `booking_url` opens the selected one-way itinerary's Google Flights booking page. For round trips it is the search URL, since the record does not select a return flight. Missing booking details also use the search URL. `booking_token` is Google's itinerary token, or `null` if absent; links and tokens may expire.
- Each leg's `operated_by` is Google's explicit operating-carrier text, or `null` when absent. It is not a list of codeshare airlines.
- Records keep the same field names in format v1; any future change will be announced here first.

#### Fare calendar

Set **Fare calendar (days)** to get Google's date grid as data: the cheapest fare for every departure day, starting at your earliest departure date, for up to 180 days per route. Round trips use "Return after days" as a fixed trip length. One record per day:

```json
{
  "record_type": "calendar_day", "route": "JFK-CDG", "origin": "JFK", "destination": "CDG",
  "departure_date": "2026-11-08", "return_date": null, "trip_type": "one_way",
  "price": 316, "currency": "USD", "is_cheapest": true,
  "passengers": { "adults": 1, "children": 0, "infants_on_lap": 0 }, "cabin_class": "economy",
  "source_url": "https://www.google.com/travel/flights/search?tfs=...&hl=en&gl=us&curr=USD",
  "status": "ok", "error": null, "scraped_at": "2026-11-01T23:04:45.633Z"
}
```

- `price` is the lowest fare Google shows for that day for your whole party, or `null` if Google shows none. `is_cheapest` marks the cheapest day(s) in the window. `source_url` opens that day's search on Google Flights.
- The calendar needs airport codes (`JFK`, not the city code `NYC`); a city code gives an error record for that route.
- Itinerary records carry `record_type: "flight"`. The dataset has a "Fare calendar" view.

`status: "no_data"` means Google listed no flights for that route and date. `status: "error"` means the search failed after all retries; `error` says why. You never pay for `no_data` or `error` records. A run summary (`RUN_SUMMARY`) is saved in the run's key-value store.

### Use it from code

Get your API token in Apify Console under **Settings > API & Integrations**. Each example runs the actor, waits for it to finish and prints the itineraries.

Python (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("cozybit/google-flights-scraper").call(run_input={
    "routes": ["JFK-CDG"],
    "departureDates": ["2027-03-12"],
    "returnAfterDays": 7,
})
for flight in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(flight["airlines"], flight["departure_time"], flight["stops"], flight["price"])
```

JavaScript (`npm install apify-client`):

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

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const run = await client.actor('cozybit/google-flights-scraper').call({
    routes: ['JFK-CDG'],
    departureDates: ['2027-03-12'],
    returnAfterDays: 7,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const flight of items) console.log(flight.airlines, flight.departure_time, flight.stops, flight.price);
```

HTTP API, one request that runs the actor and returns the records as JSON (for runs up to 5 minutes; use the clients above for longer ones):

```bash
curl -X POST "https://api.apify.com/v2/acts/cozybit~google-flights-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer <YOUR_API_TOKEN>" -H "Content-Type: application/json" \
  -d '{"routes": ["JFK-CDG"], "departureDates": ["2027-03-12"], "returnAfterDays": 7}'
```

To watch fares over time, save the input as a task in Apify Console and add a schedule; relative dates such as `"departureDates": ["3 weeks"]` keep each run looking the same distance ahead.

### Pricing

**Trial price until 30 November 2026:** 0.01 USD per 1,000 flights (the lowest price Apify allows). From 1 December 2026 this scraper costs 0.75 USD per 1,000 flights. Apify notifies all users before a price change.

You pay per itinerary returned; platform usage (compute and proxies) is included.

| Event | Price |
|---|---|
| Flight (one itinerary with its price) | 0.75 USD per 1,000 (0.00075 USD each) |

Worked examples (a search typically returns about 17 itineraries, see [Limits](#limits)):

- One route on one date, about 17 itineraries: **about 0.013 USD**.
- One route on 30 dates to find the cheapest day, about 500 itineraries: **about 0.38 USD**.

The fare calendar is free during the trial: calendar days are not charged until its own price is announced here.

To cap spending, set a maximum cost per run in the run options, or lower "Maximum itineraries per search"; the actor stops cleanly when the cap is reached.

### Free Apify plan

On the free Apify plan a run returns at most **40 itineraries** (or 40 calendar days). When the limit is reached the run finishes successfully with the status message "Free Apify plan limit reached"; everything collected so far is in the dataset. Any paid Apify plan removes the limit.

### Reliability

In 48 test runs on the Apify platform (15 routes, 5 countries and currencies, dates 3-180 days ahead, one-way and round trips), **45 of 48 searches returned itineraries** (1,123 in total) and Google limited no IP. The other 3 got a temporary Google error page; the actor retries such pages through a new IP, up to four attempts. The median run took 5 seconds. Fare calendar prices matched another scraper's calendar on all 30 days of a side-by-side test.

How it stays reliable: the actor reads the data Google embeds in its result page instead of driving a browser, sends a few paced requests per IP and switches to a new IP when Google limits one. Each search is checked against your date and currency, so a page where Google ignored your request becomes a clear error instead of wrong prices. If Google changes its page format, the run fails with a message naming the changed part rather than returning an empty or wrong dataset.

### Limits

- **Round trips** return the outbound options with round-trip prices; the matching return flights (a second step on Google Flights) are not included.
- Only the list before **"View more flights"** is returned, not Google's full list: a median of **17 itineraries** per search in our tests, range **7-68**. Raising the per-search cap does not fetch the extra flights.
- **Children and lap infants** (experimental) are sent to Google, but Google's response does not confirm the party, so check family prices.
- **Fare calendar:** up to 180 days per route, airport codes only. 31 of 32 route calendars succeeded in our tests; Google sometimes answers a calendar request with an error, and the actor retries it through new IPs (up to four attempts).
- Multi-city trips are not supported in this version.
- Prices are what Google shows at the time of the run and change often.
- Google Flights has no official public API; when Google changes its site the actor may fail until it is updated.

### Related actors

- [Google Flights Fare Calendar](https://apify.com/cozybit/google-flights-fare-calendar): just the cheapest fare for every day, up to 180 days per route and 100 routes per run.
- [Google Hotels Scraper](https://apify.com/cozybit/google-hotels-scraper): hotel prices, ratings and details for any city and dates.
- [Google Hotels Booking-Site Prices](https://apify.com/cozybit/google-hotels-booking-prices): every booking site's price for a hotel and your dates.

### Support

Report problems and feature requests on the actor's **Issues** tab, ideally with the run link.

# Actor input Schema

## `routes` (type: `array`):

Enter 1-100 routes such as JFK-CDG (New York to Paris) or LAX-NYC. Use uppercase three-letter IATA airport or city codes. Duplicate routes and extra spaces are removed.

## `departureDates` (type: `array`):

Up to 30 YYYY-MM-DD or relative dates such as 3 weeks, from today through 330 days ahead (UTC). Use a whole number of days, weeks, months or years; relative dates count from the run date. Empty means 14 days from today. Each route is searched for each resolved date; duplicates are removed.

## `returnAfterDays` (type: `integer`):

0 for one way; 1-30 for a round trip returning this many days after departure. Round-trip prices are totals, not one-way prices; results describe outbound options.

## `fareCalendarDays` (type: `integer`):

0 turns this off. Otherwise returns one row per departure day with Google's cheapest total fare, replacing the itinerary list. Requires airport codes, not city codes (for example JFK instead of NYC). Starts at the earliest departure date and covers this many consecutive days, maximum 180. Round trips use Return after days as a fixed trip length. The full window, including returns, must stay within 330 days ahead. Uses one Google request per route. Maximum itineraries per search does not apply; free plans return at most 40 calendar rows per run.

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

Number of adults, from 1 to 9. Prices cover the whole party.

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

Number of children, from 0 to 8. Child passenger request codes are unverified; Google may ignore them.

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

Number of lap infants, from 0 to 4, at most one per adult. Infant request codes are unverified; Google may ignore them.

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

Requested cabin class.

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

Any, nonstop (0), at most 1 or at most 2 stops. This request encoding is unverified; Google may ignore it.

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

Three-letter uppercase currency code. A returned search-state currency mismatch is an error.

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

Two-letter uppercase country code. Sets Google's market (gl) and, for residential proxies only, the proxy country. Datacenter and custom proxies retain their own routing.

## `maxResultsPerSearch` (type: `integer`):

Maximum itineraries per route and date. Google may list fewer; there is no pagination. Free Apify plans return at most 40 itineraries across the entire run.

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

Datacenter by default. Residential proxies are optional and use the search country. No automatic fallback. Turn off for direct requests, which cannot rotate a blocked IP.

## Actor input object example

```json
{
  "routes": [
    "JFK-CDG"
  ],
  "departureDates": [
    "2027-03-12"
  ],
  "returnAfterDays": 0,
  "fareCalendarDays": 0,
  "adults": 1,
  "children": 0,
  "infantsOnLap": 0,
  "cabinClass": "economy",
  "maxStops": "any",
  "currency": "USD",
  "country": "US",
  "maxResultsPerSearch": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `fareCalendar` (type: `string`):

Opt-in calendar_day rows: each departure day's cheapest total fare, fixed return date for round trips, and lowest-price day flags. Replaces itineraries when fareCalendarDays is above 0.

## `results` (type: `string`):

Itinerary overview. Full records also include booking_url, booking_token, typical_price_low/high, Google's price_level for this search (route and date), carry_on_bags_included and checked_bags_included counts (null when unstated), and operated_by plus verified Wi-Fi, power/USB and entertainment amenities on each leg.

# 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 = {
    "routes": [
        "JFK-CDG"
    ],
    "departureDates": [
        "3 weeks"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cozybit/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 = {
    "routes": ["JFK-CDG"],
    "departureDates": ["3 weeks"],
}

# Run the Actor and wait for it to finish
run = client.actor("cozybit/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 '{
  "routes": [
    "JFK-CDG"
  ],
  "departureDates": [
    "3 weeks"
  ]
}' |
apify call cozybit/google-flights-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cozybit/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/rTAa68kee8wUtPb3d/builds/dpcNgJctdVCbzg8wq/openapi.json
