# Google Flights Scraper & Price Monitor API 💰$2/1k (`programmx/google-flights-fare-feed`) Actor

Scrape Google Flights itineraries and the cheapest fare per route and date, with exact prices, legs, aircraft, CO2 and a 60-day price history. Monitor mode outputs only fares that changed since the last run. No browser, no login.

- **URL**: https://apify.com/programmx/google-flights-fare-feed.md
- **Developed by:** [ProgrammX](https://apify.com/programmx) (community)
- **Categories:** Travel, Automation, Developer tools
- **Stats:** 1 total users, 0 monthly users, 95.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 itineraries

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 & Price Monitor API 💰$2/1k

**Keywords:** google flights scraper, google flights api, flight price scraper, google flights price history, airfare monitor, cheapest flight finder api, flight price tracker, google flights scraper no login, fare alert feed, travel price data, flight itinerary scraper, google flights price insights, round trip flight prices

Scrape **Google Flights** itineraries and fares for any route and date grid: price, **exact price to the cent**, airlines, flight numbers, departure and arrival times, duration, stops, layovers, aircraft, legroom and CO2. Add a **cheapest-fare snapshot** per route-date with Google's price insights and **about 60 days of daily price history**, so your very first run already has two months of history.

Turn on **monitoring mode** and schedule it daily: the actor remembers every fare and outputs only flights that are **new or re-priced** since the last run, or skips route-dates whose cheapest fare did not move. You pay for changes, not for the same fares again (with `onlyNew`, set `includeSummaryRow: false` too, otherwise the per-route-date snapshot row is still output and charged on every run).

No browser, no Google login, no API key. One fast request per route-date (about 20-90 KB), so a 30-route x 60-date grid finishes in minutes.

### Who it is for

- **Fare-deal newsletters and alert channels:** re-query a fixed route x date grid every morning and publish the drops (`changeType`, `priceChangePct`).
- **Travel agencies, TMCs and OTA analytics teams:** benchmark your fares against Google's "best" bucket per route and date.
- **Airline revenue-management and consulting shops:** track competitor fares and schedules on specific routes, daily.
- **Researchers and data journalists:** fares, CO2 per itinerary and route-level price history.

### What you get

Two row types in one dataset (`rowType`):

| Field | Description |
|---|---|
| `rowType` | `itinerary` (one per flight option) or `fare-snapshot` (one per route-date) |
| `queryOrigin`, `queryDestination`, `queryDate`, `returnDate`, `tripType`, `cabin`, `adults`, `currency` | What was searched |
| `bucket` | Google's `best` or `other` list |
| `price` | Display price (total for all passengers, rounded up by Google) |
| `priceExact` | Exact price decoded from Google's booking token, e.g. 294.50 |
| `airlineCodes`, `airlines` | Carriers on the itinerary |
| `departDate`, `departTime`, `arriveDate`, `arriveTime`, `durationMin`, `stops` | Schedule (local times) |
| `layovers[]` | Airport, airport name, city, minutes |
| `legs[]` | Per flight: from/to, times, `flightNumber`, carrier, aircraft, legroom, CO2 |
| `flightKey` | Flight numbers joined by `+`, the stable key for change detection |
| `co2Grams`, `co2TypicalGrams`, `co2DiffPct` | Google's emissions estimate vs typical for the route |
| `bookingToken` | Google's token for the offer |
| `changeType`, `previousPrice`, `priceChangePct` | Monitoring mode: `new`, `changed` (`unchanged` on snapshots) |
| `resultCount` | Itineraries Google returned for the route-date |
| `insightLevel`, `insightCurrentLowest`, `insightTypicalLow`, `insightTypicalHigh` | Google price insights (snapshot rows) |
| `priceRangeMin`, `priceRangeMax` | Cheapest and most expensive fare for the route-date |
| `priceHistory` | About 62 daily `[YYYY-MM-DD, price]` points (snapshot rows) |
| `exitCountry`, `source`, `scrapedAt` | Run metadata |

### Input

| Field | Default | Description |
|---|---|---|
| `origins` / `destinations` | `["JFK"]` / `["LHR"]` | IATA codes; every origin is paired with every destination. A Google city id such as `/m/02_286` (New York) searches all its airports at once. |
| `routes` | `[]` | Alternative: explicit pairs like `DXB-LHR`, `SFO>NRT` |
| `dates` | `[]` | Explicit departure dates `YYYY-MM-DD` |
| `daysAheadFrom` / `daysAheadTo` / `everyNDays` | 30 / 32 / 1 | Rolling window used when `dates` is empty (best for schedules) |
| `tripType` | `one-way` | `round-trip` returns outbound options priced as a round trip |
| `returnAfterDays` / `returnDate` | 7 / empty | Round-trip return date |
| `cabin` | `economy` | `economy`, `premium_economy`, `business`, `first` |
| `adults` | 1 | Prices are totals for all passengers |
| `maxStops` | empty | Keep itineraries with at most N stops |
| `currency` / `language` / `country` | `USD` / `en` / `US` | Forced in the URL, so the proxy exit country does not change the data |
| `outputMode` | `itineraries` | or `cheapest` (one snapshot row per route-date) |
| `includeSummaryRow` | true | Add the snapshot row in itineraries mode |
| `maxItinerariesPerSearch` | 15 | Keep the first N itineraries per route-date (Google returns about 20-30) |
| `onlyNew` | false | Monitoring: output only new or re-priced itineraries |
| `onlyChanged` | false | Monitoring: skip route-dates whose cheapest fare is unchanged |
| `minPriceChangePct` | 0 | Ignore smaller price changes in `onlyNew` mode |
| `maxSearches` / `maxItems` | 20 / 50 | Hard caps per run (route-date searches / rows and charges). Searches run route by route (all dates of the first route first), so a low `maxSearches` can leave later routes unsearched. Duplicate routes are searched once. |
| `ssrFallback` | true | Load the full search page if the fast call fails |
| `proxyConfiguration` | no proxy | Optional Apify Proxy; see FAQ |

Example: daily grid of 3 routes x the next 60 days, cheapest fare only:

```json
{
  "routes": ["JFK-LHR", "LAX-NRT", "DXB-LHR"],
  "daysAheadFrom": 1,
  "daysAheadTo": 60,
  "outputMode": "cheapest",
  "onlyChanged": true,
  "maxSearches": 200,
  "maxItems": 200
}
```

### Output sample

Real rows from a test run on 2026-10-03 (JFK-LHR, 2026-11-02, one-way economy; truncated):

```json
{
  "rowType": "itinerary",
  "queryOrigin": "JFK", "queryDestination": "LHR", "queryDate": "2026-11-02",
  "tripType": "one-way", "cabin": "economy", "adults": 1, "currency": "USD",
  "bucket": "best", "price": 299, "priceExact": 299,
  "airlineCodes": ["AA"], "airlines": ["American"],
  "origin": "JFK", "destination": "LHR",
  "departDate": "2026-11-02", "departTime": "17:29", "arriveDate": "2026-11-03", "arriveTime": "09:20",
  "durationMin": 651, "stops": 1,
  "layovers": [{ "durationMin": 63, "airport": "RDU", "airportName": "Raleigh-Durham International Airport", "city": "Raleigh" }],
  "legs": [
    { "from": "JFK", "to": "RDU", "departTime": "17:29", "arriveTime": "19:32", "durationMin": 123, "flightNumber": "AA4501", "aircraft": "Embraer 175", "legroom": "30 in", "co2Grams": 110704 },
    { "from": "RDU", "to": "LHR", "departTime": "20:35", "arriveTime": "09:20", "durationMin": 465, "flightNumber": "AA174", "aircraft": "Boeing 777", "legroom": "31 in", "co2Grams": 502495 }
  ],
  "flightKey": "AA4501+AA174",
  "co2Grams": 613000, "co2TypicalGrams": 431000, "co2DiffPct": 42,
  "bookingToken": "CjRIcjVkZ1lRb0xDd0VBSENnWXdCRy0tLS0tLS0t...",
  "changeType": null, "resultCount": 31, "source": "rpc", "exitCountry": "MY",
  "scrapedAt": "2026-10-03T15:53:50.554Z"
}
```

```json
{
  "rowType": "fare-snapshot",
  "queryOrigin": "JFK", "queryDestination": "LHR", "queryDate": "2026-11-02", "currency": "USD",
  "price": 299, "priceExact": 299, "airlines": ["Delta", "Virgin Atlantic"], "flightKey": "DL5638+VS22", "stops": 1,
  "resultCount": 31,
  "insightLevel": 5, "insightCurrentLowest": 299, "insightTypicalLow": 170, "insightTypicalHigh": 295,
  "priceRangeMin": 299, "priceRangeMax": 2884,
  "priceHistory": [["2026-08-04", 295], ["2026-08-05", 295], ["2026-08-06", 295], "... about 62 points"]
}
```

### Pricing (pay per event)

| Event | What you pay for | Free plan | Starter (Bronze) | Scale (Silver) | Business (Gold) |
|---|---|---|---|---|---|
| `itinerary` | One itinerary row (only new or re-priced rows in `onlyNew` mode) | $0.002 | $0.0018 | $0.0016 | $0.0014 |
| `fare-snapshot` | One cheapest-fare row per route-date with insights and 60-day history | $0.005 | $0.0045 | $0.004 | $0.0035 |

That is **$2 per 1,000 itineraries** and **$5 per 1,000 route-date snapshots** on the free plan, plus Apify's small actor-start fee. Route-dates with no flights (invalid route, or Google returned no itineraries) are output as a row with `error` set and are not charged. The default input costs under $0.11. Set a maximum cost per run in the Console and the actor stops cleanly when it is reached.

### How to schedule daily (monitoring mode)

1. Create a **task** with your routes and a rolling window, e.g. `daysAheadFrom: 7`, `daysAheadTo: 60`, and set `onlyNew: true` (itineraries) or `outputMode: "cheapest"` with `onlyChanged: true` (one row per route-date that moved).
2. Add a **schedule** to the task: daily at 05:00 UTC (`0 5 * * *`). For departures within 14 days, a second task every 6 hours catches intraday moves.
3. Connect the dataset to Google Sheets, a webhook, Slack, Zapier, Make or n8n. Each run outputs only what changed, with `previousPrice` and `priceChangePct`.

The state lives in the named key-value store `google-flights-fare-feed-state` in your account (one record per route, date, cabin, passengers and currency). Delete it to start fresh. Keep `adults`, `cabin` and `currency` fixed per task so prices stay comparable.

### Use it from the API, n8n, Make, Zapier or an AI agent

- **API:** start a run and get the results in one call:
  ```bash
  curl -X POST "https://api.apify.com/v2/acts/programmx~google-flights-fare-feed/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"routes": ["JFK-LHR"], "daysAheadFrom": 30, "daysAheadTo": 32}'
  ```
  The response is the dataset as JSON; add `&format=csv` for CSV. This endpoint waits up to 5 minutes; for longer runs, start the run asynchronously and read the dataset when it finishes.
- **n8n, Make and Zapier:** use the Apify node or app, choose *Run Actor*, pick this actor and paste the input JSON.
- **Google Sheets, Slack, email and webhooks:** add an integration on the actor or task in Apify Console.
- **AI agents:** add this actor to Apify's MCP server (`https://mcp.apify.com`) and call it from any MCP client.

### FAQ

#### Do I need a proxy?

Usually not: in our tests Google Flights answered without one. If you see blocks, select Apify Proxy (datacenter first, then residential). The actor checks proxy health before the run and retries each request up to 4 times with a fresh session.

#### Why is the price total for all passengers?

That is how Google shows it. 2 adults = about twice the one-adult fare.

#### What is `priceExact`?

Google rounds the display price up to a whole unit; the booking token carries the exact amount (e.g. 294.50), which makes change detection reliable.

#### Which currencies work?

Any code Google supports; USD, EUR, GBP, MXN and ZAR were verified. If Google rejects a currency, the actor retries the search in USD and labels the rows accordingly.

#### Does it return the return flights of a round trip?

Not yet: round-trip searches return the outbound options with the round-trip total price, like Google's first results page.

#### Why do some searches take a few seconds?

Google sometimes answers a valid search with a temporary error; the actor retries it automatically (counted in `RUN_STATS.errorResponseRetries`). An invalid route is reported after 5 tries (10 with a non-USD currency, because a rejected currency is retried in USD) and is not charged.

#### Can I get statistics for a run?

Yes, the `RUN_STATS` record in the run's default key-value store has requests, retries, rows per search, proxy mode, exit country and duration.

#### How much does daily fare monitoring cost?

Example on the Free plan: 5 routes × 30 departure dates in `cheapest` mode is 150 route-dates. If every one changed, a run would cost 150 × $0.005 = $0.75; with `onlyChanged` you pay only for the route-dates whose cheapest fare moved.

#### Can I export Google Flights data to CSV or Google Sheets?

Yes. Each run's dataset downloads as CSV, Excel or JSON, and the Google Sheets integration can append every run to a sheet.

#### Can an AI agent use this actor?

Yes. Apify's MCP server (`https://mcp.apify.com`) can expose this actor as a tool to Claude, Cursor, VS Code and other MCP clients, so an agent can fetch fresh fares on request.

### Limitations

- One-way and round-trip (outbound options) only; multi-city is not supported. Return-leg selection is not implemented.
- Google's price-insight labels (`insightLevel`, typical low/high) are not documented by Google; the field meanings are our best reading.
- Prices are what Google shows to an anonymous user at the time of the run; they can differ from the airline's checkout.
- Google can change its internal response format at any time; the actor flags a suspected change in `RUN_STATS.parseDriftSuspected` and the maintainer fixes it.
- Children, infants and loyalty fares are not supported.

# Actor input Schema

## `origins` (type: `array`):

Airport IATA codes (JFK) or a Google city id (/m/02_286 = New York, all airports in one search). Every origin is paired with every destination. Ignored when 'Routes' is filled.

## `destinations` (type: `array`):

Airport IATA codes (LHR) or a Google city id. Every origin is paired with every destination.

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

Explicit origin-destination pairs such as DXB-LHR or SFO>NRT. When set, origins and destinations are ignored.

## `dates` (type: `array`):

Explicit dates. Leave empty to use the rolling window below (recommended for daily schedules). Dates up to about 330 days ahead work; past dates are skipped.

## `daysAheadFrom` (type: `integer`):

Used when 'Departure dates' is empty. 1 = tomorrow (UTC).

## `daysAheadTo` (type: `integer`):

Used when 'Departure dates' is empty. Inclusive. One search per route per date.

## `everyNDays` (type: `integer`):

1 = every day in the window, 7 = one date per week.

## `tripType` (type: `string`):

One-way, or round-trip (returns the outbound options priced as a round trip; return legs are not included).

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

Round-trip only: return date = departure date + N days. Ignored if 'Return date' is set.

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

Round-trip only: a fixed return date for every search. Leave empty to use 'return after N days'.

## `cabin` (type: `string`):

Cabin class searched on Google Flights.

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

Prices are totals for all passengers (2 adults = about 2x).

## `maxStops` (type: `integer`):

Keep only itineraries with at most this many stops. Empty = any.

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

ISO 4217 code passed to Google in the URL (USD, EUR, GBP, MXN, ZAR verified), so the proxy exit country does not change the currency.

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

Google interface language for airport and airline names (en, de, fr, ...).

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

Google country parameter, forced in the URL so results do not depend on the proxy exit country.

## `outputMode` (type: `string`):

Itineraries: one row per flight option (billed per itinerary). Cheapest: one fare-snapshot row per route-date (billed per snapshot).

## `includeSummaryRow` (type: `boolean`):

Also output one 'fare-snapshot' row per route-date: cheapest fare, Google's typical price range and about 62 days of daily price history. Billed as a fare-snapshot event.

## `maxItinerariesPerSearch` (type: `integer`):

Google returns about 20-30 itineraries per search (best first). Keep the first N.

## `onlyNew` (type: `boolean`):

Remember every itinerary's last price per route-date in the named key-value store 'google-flights-fare-feed-state' and output only flights that are new or whose price changed by at least 'Minimum price change'.

## `onlyChanged` (type: `boolean`):

Skip a route-date entirely (no rows, no charge) when its cheapest fare equals the one seen on the previous run.

## `minPriceChangePct` (type: `number`):

With 'only new or re-priced', ignore price changes smaller than this. 0 reports any change.

## `maxSearches` (type: `integer`):

Hard cap on searches (routes x dates). Each search is one request of about 20-90 KB.

## `maxItems` (type: `integer`):

Hard cap on dataset rows (and charges) per run.

## `ssrFallback` (type: `boolean`):

If the fast RPC call fails after retries, load the search page instead (about 12x the bytes). Same data.

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

Optional. Google Flights answered without a proxy in our tests. If Apify Proxy is not selected, the actor uses Decodo credentials from secret env vars when present, otherwise it connects directly.

## Actor input object example

```json
{
  "origins": [
    "JFK"
  ],
  "destinations": [
    "LHR"
  ],
  "routes": [],
  "dates": [],
  "daysAheadFrom": 30,
  "daysAheadTo": 32,
  "everyNDays": 1,
  "tripType": "one-way",
  "returnAfterDays": 7,
  "cabin": "economy",
  "adults": 1,
  "currency": "USD",
  "language": "en",
  "country": "US",
  "outputMode": "itineraries",
  "includeSummaryRow": true,
  "maxItinerariesPerSearch": 15,
  "onlyNew": false,
  "onlyChanged": false,
  "minPriceChangePct": 0,
  "maxSearches": 20,
  "maxItems": 50,
  "ssrFallback": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `fares` (type: `string`):

Flight itineraries per route and date (price, exact fare, airlines, times, stops, legs, CO2) and one cheapest fare snapshot per route and date with Google price insights and about 60 days of price history. Filter on rowType. In monitoring mode only new or changed fares are returned.

## `runStats` (type: `string`):

Summary of the run: rows emitted and charged, requests, retries, proxy mode, errors and duration.

# 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 = {
    "origins": [
        "JFK"
    ],
    "destinations": [
        "LHR"
    ],
    "routes": [],
    "dates": [],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("programmx/google-flights-fare-feed").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 = {
    "origins": ["JFK"],
    "destinations": ["LHR"],
    "routes": [],
    "dates": [],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("programmx/google-flights-fare-feed").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 '{
  "origins": [
    "JFK"
  ],
  "destinations": [
    "LHR"
  ],
  "routes": [],
  "dates": [],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call programmx/google-flights-fare-feed --silent --output-dataset

```

## MCP server setup

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

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/Xnb0yZukiUQhGUVvE/builds/QnQBSq5GA8joe2L2T/openapi.json
