# Google Flights Scraper & Price Monitor (`olliolli/google-flights-prices`) Actor

Track Google Flights fares across airport routes. Export flight prices, compare departure dates and monitor new or changed fares. No login; pay per delivered result.

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

## Pricing

$2.00 / 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 & Price Monitor

Compare **Google Flights prices**, build a departure-date price calendar and track airfare changes across airport routes. Export structured flight results to JSON, CSV or Excel, or connect the Apify API to your own workflow. Monitor mode delivers **new flights and changed fares only**: unchanged results have no event charge.

Use it for route research, travel-price dashboards and recurring fare checks. This Actor reads public Google Flights pages without an account, user cookies or a separate API subscription.

### Start with two routes

```json
{
  "routes": ["BRU-BCN", "AMS-LIS"],
  "tripType": "oneway",
  "currency": "EUR",
  "country": "be",
  "maxResultsPerSearch": 10
}
```

Leave `departDate` empty to search 21 days ahead. Set an explicit `YYYY-MM-DD` date to track the **same departure** on subsequent runs. Airport codes must be three letters. Travel dates must fall within the next 330 days. City names, country searches and multi-city journeys are not supported.

### What you receive

Each dataset row is one priced outbound itinerary: route, departure/arrival dates and local times, currency, airlines, flight numbers, stops, layovers and duration. Aircraft, legroom and CO₂ estimates are included when Google supplies them. `googleFlightsUrl` opens the corresponding search, not a guaranteed bookable fare.

The Actor verifies the echoed route, travel dates, passenger count, cabin and currency, and filters out itineraries that do not match the requested departure airport, arrival airport, date or maximum stops. Unverified results are skipped without an event charge.

Two additional records are linked from the Output tab:

- **CALENDAR:** the cheapest returned fare per successfully completed route/date, plus Google's search-level price insights and historical prices where available. This is the cheapest fare in the retrieved results, not a guarantee across every airline or seller. The calendar is not billed separately.
- **OUTPUT:** completion status, successful/failed/unchecked searches, excluded rows, unchanged results, delivered rows and charged-event count. Always inspect this record when using the API. An incomplete run is marked failed while retaining useful results already delivered.

`priceLevel`, `typicalLow` and `typicalHigh` describe Google's **overall search**, not a judgement about every individual itinerary. Price history can be absent or shorter than 60 days. All times are local airport times; no UTC offset is inferred.

### Build a price calendar

Set `extraDays: 6` for seven departure dates per route. Set `tripType: "return"` and `stayDays: 4` for a return four days after each departure. Return prices cover the round trip, but **the dataset describes the outbound itinerary only**; the return-flight details are not retrieved.

You can request economy, premium economy, business or first class, 1–9 adults, an ISO currency and a country setting. These are requested preferences, not a promise that every route has inventory. `maxPrice` excludes higher fares from the flight dataset; CALENDAR still describes the retrieved search results.

### Monitor airfare changes

```json
{
  "routes": ["BRU-BCN"],
  "departDate": "2026-12-15",
  "mode": "monitor",
  "stateName": "winter-barcelona",
  "priceChangePercent": 2,
  "currency": "EUR"
}
```

Choose a future date before running this example. The first run establishes the baseline and returns `NEW` flights. Later runs with the same `stateName` return `PRICE_DOWN` or `PRICE_UP`, including `previousPrice` and `priceChangePercent`. The threshold compares against the **last reported price**, so small cumulative changes are not lost. A zero threshold still excludes identical prices.

Create an Apify task and schedule it to run daily or weekly. Keep dates, currency, cabin and passenger count consistent for comparable fares. Leaving the departure date empty deliberately advances the travel date every day and therefore creates new departures rather than tracking one fixed departure.

State is retained for 90 days from the last reported observation. Use a different state name for independent watches. **Do not overlap runs using the same state name.** Disappearing flights are not reported as sold out: the first results page can change without a flight becoming unavailable. External notifications require your own Apify integration or webhook.

### Pricing

**$2 per 1,000 delivered flight itineraries** (`flight`: $0.002). No Actor start event, no duplicate dataset-item fee, no separate calendar fee.

| Example | Actor event charge |
| --- | ---: |
| 10 flight rows | $0.02 |
| 5 routes × 7 days × 5 returned rows | $0.35 |
| Monitor repeat with no qualifying changes | $0.00 |
| Monitor repeat with 3 changed fares | $0.006 |
| Failed or unverified search with no delivered rows | $0.00 |

Set **Maximum cost per run** in Apify. The Actor stops when another result cannot fit; already delivered results remain available. An event budget is not a guarantee of zero platform usage for owner tests or other usage charged separately by your Apify arrangement. Own-account test charges are not customer revenue.

### Limits and reliability

- This Actor retrieves Google's **first results page**, up to 10 itineraries per route/date. It does not claim exhaustive flight or booking-provider coverage.
- At most 200 route/date searches per run; free Apify accounts are limited to the first five and OUTPUT reports the remainder as unchecked.
- Public pages can be blocked or change format. Connection recovery is bounded to three proxy sessions per run; HTTP 429 stops the run. No captcha solving, user login or unlimited IP rotation.
- Fares are observations, not reservations. Baggage, payment fees and the final airline checkout price can differ. No booking, refund, ticket availability or price guarantee is provided.
- No children/infants, multi-city itineraries, booking links per seller, seat maps, full return-flight selection or email alerts built in.
- Monitor state changes only for delivered results. Billing uses stable event identifiers for recovery within the same run; manually starting a fresh run is a separate run.
- Only public flight information is output. No traveler names, contact details or payment data are collected.

### Troubleshooting

**No results:** inspect OUTPUT. A failed connection or unverified search is different from a completed search whose prices exceeded `maxPrice`.

**Incomplete run:** inspect `stopped`, `searchesFailed` and `uncheckedSearches`. A budget stop can leave a route partially delivered. A later run can retry; use monitor mode to avoid charging again for unchanged delivered fares.

**Unexpected monitoring rows:** check that your departure dates and search settings stayed the same and that `stateName` matches. A rolling departure date creates new flights each day.

For support, open an issue with the run ID and route/date settings. Do not share credentials or personal traveler information.

# Actor input Schema

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

Airport codes, one route per line, e.g. BRU-BCN or AMS-LIS.

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

One-way or return. For return trips the price is the round-trip price and the outbound flights are listed.

## `departDate` (type: `string`):

YYYY-MM-DD. Empty = 21 days from today, which keeps scheduled runs in the future.

## `extraDays` (type: `integer`):

Also search the following days, e.g. 6 = a 7-day price calendar per route.

## `stayDays` (type: `integer`):

Return trips only: return date = departure date + this many days.

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

Number of adult passengers (prices are shown for the whole group as Google shows them).

## `seatClass` (type: `string`):

Cabin class.

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

Only flights with at most this many stops.

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

ISO currency code, e.g. EUR, USD, GBP.

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

Two-letter country code Google uses for the search, e.g. be, nl, de.

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

Google's first results page holds about 10 itineraries (best + cheapest).

## `maxPrice` (type: `integer`):

Skip flights above this price. 0 = no limit.

## `mode` (type: `string`):

Snapshot returns every flight. Monitor remembers prices between runs and returns only new flights and price changes.

## `stateName` (type: `string`):

Monitor mode only. Runs with the same name share their price memory.

## `priceChangePercent` (type: `integer`):

Monitor mode only. Ignore smaller price changes.

## Actor input object example

```json
{
  "routes": [
    "BRU-BCN",
    "AMS-LIS"
  ],
  "tripType": "oneway",
  "extraDays": 0,
  "stayDays": 4,
  "adults": 1,
  "seatClass": "economy",
  "maxStops": "any",
  "currency": "EUR",
  "country": "be",
  "maxResultsPerSearch": 10,
  "maxPrice": 0,
  "mode": "snapshot",
  "stateName": "default",
  "priceChangePercent": 2
}
```

# Actor output Schema

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

Each itinerary with price, airlines, stops and times.

## `calendar` (type: `string`):

Cheapest retrieved fare per completed route/date, with optional price insights and history.

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

Searches, rows and charged events.

# 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": [
        "BRU-BCN",
        "AMS-LIS"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("olliolli/google-flights-prices").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": [
        "BRU-BCN",
        "AMS-LIS",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("olliolli/google-flights-prices").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": [
    "BRU-BCN",
    "AMS-LIS"
  ]
}' |
apify call olliolli/google-flights-prices --silent --output-dataset

```

## MCP server setup

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

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/qobr7VKNZXG0xE9HJ/builds/8kbZvdSUuHdPnlfsP/openapi.json
