# Google Flights Cheapest Fare Monitor (`quilldata/google-flights`) Actor

Track the cheapest public Google Flights fare for any route and date. One clean row per check, built for schedules. Failed or empty runs are free.

- **URL**: https://apify.com/quilldata/google-flights.md
- **Developed by:** [Quill Data](https://apify.com/quilldata) (community)
- **Categories:** Travel
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 flight offers

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 Cheapest Fare Monitor

Track the cheapest public Google Flights fare for any route and date. One clean row per check, built for schedules. Failed or empty runs are free.

### What you get

Give it an origin, a destination and a date. By default it returns **one row: the cheapest fare** shown on the first Google Flights results screen, with airline, stops, duration, departure and arrival time, and Google's price level (low / typical / high). Put it on a schedule and you have a simple fare watcher.

Need more than the cheapest? Set `cheapestOnly` to `false` and raise `maxResults` (up to 150) to get one row per offer.

You pay only for rows that carry a price. Blocked pages, empty results and unpriced offers cost nothing.

### What it is

- A reader for the **public first results screen** of google.com/travel/flights (server-rendered HTML, no login, no browser, no proxy).
- One dataset row per fare offer; in the default mode, one row per route/date (the lowest price).
- Price, currency, airline, stops, total duration, local depart/arrive time, price level, and a link back to the same Google search.

### What it isn't (honest limits)

- **Not the full result list.** It reads what the first screen shows (often 10–30 offers), not every flight Google can find.
- **Not the Date grid / Price graph calendar.** Those are drawn in the browser and are not in the public HTML. `calendarDays > 0` only writes a free notice row today.
- No flight numbers or airline IATA codes when the first screen does not show them (fields stay empty; nothing is guessed).
- No booking, no booking-site offers, no seat maps, no personal data.
- Results depend on what Google returns to the run's IP; sometimes the page has no offer cards. Those runs write a free notice row and are not charged.

### Input example

```json
{
  "origin": "JFK",
  "destination": "LAX",
  "departureDate": "2026-11-27",
  "cheapestOnly": true,
  "maxResults": 3,
  "currency": "USD",
  "gl": "us",
  "hl": "en"
}
```

| Input | Meaning |
|---|---|
| `origin`, `destination` | IATA airport codes (required) |
| `departureDate` | YYYY-MM-DD (required) |
| `returnDate` | optional YYYY-MM-DD for a round trip |
| `adults`, `cabinClass` | passengers; `economy` / `premium_economy` / `business` / `first` |
| `currency`, `gl`, `hl` | currency code, Google region, interface language |
| `cheapestOnly` | default `true`: keep only the lowest-priced offer |
| `maxResults` | default 3, max 150 (effective limit is 1 while `cheapestOnly` is on) |

### Output example

```json
{
  "type": "offer",
  "origin": "JFK",
  "destination": "LAX",
  "departure_date": "2026-11-27",
  "trip_type": "round_trip",
  "cabin_class": "economy",
  "adults": 1,
  "currency": "USD",
  "price": 545,
  "price_display": "$545",
  "price_level": "high",
  "airline": "American",
  "airline_codes": [],
  "flight_numbers": [],
  "stops": 1,
  "duration_minutes": 991,
  "depart_at": "7:00 PM on Friday, November 27",
  "arrive_at": "8:31 AM on Saturday, November 28",
  "google_flights_url": "https://www.google.com/travel/flights?hl=en&gl=us&curr=USD&q=Flights%20from%20JFK%20to%20LAX%20on%202026-11-27",
  "result_depth": "ssr",
  "scraped_at": "2026-10-30T03:47:57Z"
}
```

*(Real cloud row from 2026-10-30. Prices change all the time. Google may label a fare as round trip even when no return date was given; `trip_type` reports what Google shows.)*

### Output fields (`type=offer`)

| Field | Meaning |
|---|---|
| `type` | `offer` (free helper rows: `notice`) |
| `origin`, `destination`, `departure_date`, `return_date` | from input |
| `trip_type` | `one_way` / `round_trip` as Google labels the fare |
| `cabin_class`, `adults` | from input |
| `price`, `currency`, `price_display` | numeric price, currency, raw text |
| `price_level` | Google price insight: `low` / `typical` / `high` (if shown) |
| `airline` | marketing airline name as shown |
| `airline_codes`, `flight_numbers` | usually `[]` – not on the first screen; never invented |
| `stops`, `duration_minutes` | number of stops, total minutes |
| `depart_at`, `arrive_at` | local time text as shown |
| `google_flights_url`, `source_url` | public search URL |
| `scraped_at` | UTC ISO time |
| `result_depth` | `ssr` (first screen only) |
| `raw_aria` | original accessible label (for audit) |

### Pricing

**$0.002 per priced offer** (`flight-offer` event). No per-page fee and no dataset-item fee. Failed, blocked, empty and unpriced rows are free. In the default cheapest-only mode, one scheduled check costs about $0.002.

### Also from Quill Data

- **[Google Hotels Prices](https://apify.com/quilldata/google-hotels)** — nightly and total-stay hotel rates for the same dates; failed runs are not charged.
- **[Tennis Scores](https://apify.com/quilldata/tennis-scores)** — ATP, WTA and Challenger results with automatic source failover.

### Data source and terms

Public Google Flights search pages, read without login. **Not affiliated with, endorsed by, or sponsored by Google.** You are responsible for using the data in line with the terms that apply to you.

# Actor input Schema

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

Departure airport code, for example JFK.

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

Arrival airport code, for example LAX.

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

YYYY-MM-DD.

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

Optional YYYY-MM-DD for round trip.

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

Number of adult passengers.

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

economy, premium_economy, business, or first.

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

Three-letter currency code.

## `gl` (type: `string`):

Google results region, for example us or gb.

## `hl` (type: `string`):

Interface language.

## `cheapestOnly` (type: `boolean`):

Default true: keep only the single lowest-priced offer per route/date (first one wins on a tie). Built for scheduled price watching: one billable row per run. Set to false (and raise maxResults) to get several offers.

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

Max offer rows to keep from the SSR first screen. Default 3 is aimed at scheduled price monitoring (with cheapestOnly=true only 1 row is kept anyway). For more rows, raise this (up to 150) AND turn off cheapestOnly.

## `calendarDays` (type: `integer`):

If >0, also collect lowest fares for this many departure days. 0 = off.

## `calendarOnly` (type: `boolean`):

If true, skip offer rows and only emit calendar_day rows when calendarDays > 0.

## `requestDelaySecs` (type: `number`):

Minimum pause between live Google requests.

## Actor input object example

```json
{
  "origin": "JFK",
  "destination": "LAX",
  "departureDate": "2026-12-15",
  "adults": 1,
  "cabinClass": "economy",
  "currency": "USD",
  "gl": "us",
  "hl": "en",
  "cheapestOnly": true,
  "maxResults": 3,
  "calendarDays": 0,
  "calendarOnly": false,
  "requestDelaySecs": 6
}
```

# Actor output Schema

## `offers` (type: `string`):

Default dataset of flight offer rows (and free notice rows).

# 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",
    "departureDate": "2026-12-15",
    "adults": 1,
    "cabinClass": "economy",
    "currency": "USD",
    "gl": "us",
    "hl": "en",
    "maxResults": 3,
    "calendarDays": 0,
    "requestDelaySecs": 6
};

// Run the Actor and wait for it to finish
const run = await client.actor("quilldata/google-flights").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",
    "departureDate": "2026-12-15",
    "adults": 1,
    "cabinClass": "economy",
    "currency": "USD",
    "gl": "us",
    "hl": "en",
    "maxResults": 3,
    "calendarDays": 0,
    "requestDelaySecs": 6,
}

# Run the Actor and wait for it to finish
run = client.actor("quilldata/google-flights").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",
  "departureDate": "2026-12-15",
  "adults": 1,
  "cabinClass": "economy",
  "currency": "USD",
  "gl": "us",
  "hl": "en",
  "maxResults": 3,
  "calendarDays": 0,
  "requestDelaySecs": 6
}' |
apify call quilldata/google-flights --silent --output-dataset

```

## MCP server setup

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

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/cpYOdNWydsb9ojX12/builds/jmh5fKhvWDVg7T1uq/openapi.json
