# Google Flights Scraper - Prices and Calendar (`sumitr_mardy/google-flights-scraper`) Actor

Export public Google Flights itineraries with numeric fares, airlines, stops, layovers, airports and local times. Compare one-way or round-trip searches, or find the lowest fare per calendar day. Relative dates keep scheduled price checks in the future.

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

## Pricing

from $0.30 / 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.
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 — Prices and Cheapest-Date Calendar

Export public Google Flights first-page itineraries with numeric prices, airlines, stops, layovers, airports, local times and duration. Search one-way or round-trip fares, or build a cheapest-date calendar. No login, cookie, Google API key or browser required.

Not affiliated with Google. Fares are what Google Flights displays for the query, currency and country at run time; they are **not booking quotes**. No booking links or ticket purchase in v1.

### Quick start

A date that stays in the future:

```json
{"routes":[{"from":"JFK","to":"LIS"}],"departureDaysFromToday":45,"maxResultsPerSearch":5}
```

Fixed-date one way:

```json
{"routes":[{"from":"JFK","to":"LIS"}],"departureDate":"2026-12-10","maxResultsPerSearch":30}
```

Relative round trip:

```json
{"routes":[{"from":"JFK","to":"CDG"}],"departureDaysFromToday":45,"returnDaysAfterDeparture":7,"maxResultsPerSearch":30}
```

Fourteen-day cheapest-date calendar:

```json
{"routes":[{"from":"LHR","to":"BKK"}],"departureDaysFromToday":45,"calendarDays":14,"cheapestPerDayOnly":true}
```

The fixed-date example eventually expires. Use relative dates for daily checks.

### Input

| Field | Default | Meaning |
|---|---|---|
| routes | required | Array of {from,to}; IATA codes or city names. Optional departureDate/returnDate per route override global fixed dates. |
| departureDate | absent | Fixed YYYY-MM-DD for ordinary searches. |
| departureDaysFromToday | 45 | UTC days ahead, 0–365, used when there is no fixed date. |
| returnDate | absent | Fixed return date; turns the search into a round trip. |
| returnDaysAfterDeparture | absent | Relative return interval, 0–365 days; useful for schedules. |
| dateFrom, dateTo | absent | Inclusive fixed calendar range, at most 60 dates. Calendar mode is one way. |
| calendarDays | absent | Relative calendar of 1–60 dates beginning departureDaysFromToday ahead. Alternative to dateFrom/dateTo. |
| cheapestPerDayOnly | true | In calendar mode return one lowest-priced eligible itinerary per route/day. |
| maxResultsPerSearch | 50 | Maximum unique first-page rows, 1–200. Cheapest-only calendars return one. |
| currency | USD | ISO currency sent as curr. |
| language, country | en, us | Flights UI language and country. Full structured parsing is verified for English; other languages may produce partial rows with raw labels. |
| nonstopOnly | false | Local filter, no surcharge. Ambiguous/unparsed stop counts are excluded. |

At most 100 generated route/date searches per run. Invalid routes/dates become free invalid_input rows. Exact normalized route/date searches and repeated DOM itinerary labels are deduplicated. Calendar ranges cannot be combined with return dates. Past dates, invalid dates, return-before-departure and ranges over 60 days are rejected.

The calendar makes one search per day. It is **not** Google's private calendar API. With cheapestPerDayOnly=false, it exports up to maxResultsPerSearch per day instead.

### What is returned

All 30 keys are present, never null. Missing strings are "", numbers are 0 and arrays are \[].

| Field | Meaning |
|---|---|
| inputIndex, from, to | Original route index and supplied origin/destination. |
| departureDate, returnDate, tripType | Requested dates and one_way or round_trip. |
| price, currency, priceText | Parsed numeric displayed fare, requested currency and raw fare text. |
| airlines, airline | Airline array and joined display names. |
| stops, layovers | Stop count and array of {airport,city,duration}. |
| departureAirport, departureTime, departureDay | Airport and local displayed departure time/day. |
| arrivalAirport, arrivalTime, arrivalDay | Airport and local displayed arrival time/day. |
| arrivesNextDay | True when the displayed arrival day differs; can mean more than one day. Not a UTC-normalized date calculation. |
| durationText, durationMinutes | Raw elapsed duration and parsed minutes. |
| isCheapestOfDay, position | Lowest positive fare among eligible first-page rows for this route/day; one-based output position. |
| searchUrl, label | Reproducible public query URL and original decoded itinerary aria-label. |
| status, subStatus, error, scrapedAt | Stable outcome, machine-readable reason, explanation and ISO scrape time. |

Rows are ordered by numeric fare, with unknown prices last. Tied lowest fares can all have isCheapestOfDay=true in full mode; cheapest-only mode keeps the first tie. If no fare parses, the first raw-label row is retained with isCheapestOfDay=false, rather than inventing a cheapest price.

Unparsed labels are not discarded by the parser: available fields and the raw label remain in an ok/flight row. User filters and result limits still apply. A 0 price or stop count in such a partial row is missing information, not a verified free or nonstop flight.

**Round-trip rows describe the outbound itinerary choice and the displayed round-trip total.** The return date is the requested search date; complete return-flight legs, selected booking options, taxes/baggage breakdowns and final ticket availability are outside v1. Airport times/day labels are local display text; no timezone offsets or exact UTC times are inferred.

### Status and billing

| status | subStatus | Flight charge |
|---|---|---|
| ok | flight | Yes |
| no_results | no_results | No |
| failed | invalid_input, http_CODE, blocked, empty_page, parse_error, network_error, free_work_limit, cost_limit_reached | No |

Failed, empty and locally filtered rows have no flight event charge. A partially completed calendar can contain successful dates plus free failure rows for other dates. Already saved itineraries remain charged.

| Apify tier | Per itinerary row | Per 1,000 rows |
|---|---|---|
| FREE | $0.0006 | $0.60 |
| BRONZE | $0.0005 | $0.50 |
| SILVER | $0.0004 | $0.40 |
| GOLD+ | $0.0003 | $0.30 |

Default Actor start event: $0.00005 per GB, minimum one event. It still applies to an empty/failed run. Dataset-item billing is disabled; platform usage is included under PPE. The calendar is charged only for selected saved rows, not all itineraries parsed internally. User spending limits can stop output early.

### Schedule a daily price check

1. Run or save a task with departureDaysFromToday:45 instead of a fixed departureDate.
2. For a moving 14-day calendar add calendarDays:14 and cheapestPerDayOnly:true. For a round trip add returnDaysAfterDeparture:7.
3. In Apify Console open Schedules, create a schedule, choose the saved task, select a daily time/timezone and enable it.
4. Review the run status and dataset, or configure your own integration to consume successful rows.

Each daily run advances the departure/calendar dates relative to that day's UTC date. Fixed departureDate/dateFrom/dateTo values do not advance and eventually need manual updates. No schedule is created automatically by this Actor. A 14-row daily calendar at FREE list price is $0.0084 in flight events plus the start event; no_results/failed days have no flight event charge.

### API examples

```bash
curl -X POST "https://api.apify.com/v2/acts/sumitr_mardy~google-flights-scraper/run-sync-get-dataset-items?format=json" \
  -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \
  -d '{"routes":[{"from":"JFK","to":"LIS"}],"departureDaysFromToday":45,"maxResultsPerSearch":5}'
```

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("sumitr_mardy/google-flights-scraper").call(
    run_input={"routes":[{"from":"LHR","to":"BKK"}],
               "departureDaysFromToday":45, "calendarDays":14,
               "cheapestPerDayOnly":True}
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(row["departureDate"], row["price"], row["currency"], row["status"])
```

For longer calendars use asynchronous runs and download the dataset after completion.

### Use it from AI agents (MCP)

Hosted OAuth:

```json
{"mcpServers":{"flights":{"url":"https://mcp.apify.com/?tools=sumitr_mardy/google-flights-scraper"}}}
```

Hosted Bearer alternative:

```json
{"mcpServers":{"flights":{"url":"https://mcp.apify.com/?tools=sumitr_mardy/google-flights-scraper","headers":{"Authorization":"Bearer YOUR_APIFY_TOKEN"}}}}
```

Stdio:

```json
{"mcpServers":{"flights":{"command":"npx","args":["-y","@apify/actors-mcp-server","--tools","sumitr_mardy/google-flights-scraper"],"env":{"APIFY_TOKEN":"YOUR_APIFY_TOKEN"}}}}
```

Specify origin, destination, currency and date strategy. Ask for a cheapest-only calendar when comparing dates. Inspect status/subStatus and the raw label before interpreting missing fields or comparing fares.

### Limits and reliability

Only the first server-rendered best/other lists are used. The Actor does not call internal RPC, paginate beyond the first results page or collect booking links. Duplicate mobile/desktop labels are removed, so unique itinerary counts can be lower than the raw DOM label count.

Transient empty HTML shells are retried up to two more times directly. Non-challenge failures can use one final default datacenter attempt. A real CAPTCHA, /sorry/ or consent challenge stops the host for the run; no cookie, login, residential proxy, IP rotation around challenges or CAPTCHA solving. At most two searches concurrently, with a 500 ms pause after each response per worker. Hard deadlines and a free-work loss guard bound unproductive requests.

Prices, result availability, airport groupings and UI wording can change. Currency and country affect displayed fares. A city name can include nearby airports. If a city-name query repeatedly returns an empty server-rendered page, use specific IATA airports; the verified New York–Paris round-trip preset uses JFK and CDG. Nothing here reserves or purchases a ticket.

For hotel nightly prices and two-adult stays, use the sister [Google Hotels Scraper](https://apify.com/sumitr_mardy/google-hotels-scraper).

# Actor input Schema

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

Airport codes or city names. Optional per-route departureDate/returnDate override global fixed dates.

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

Optional fixed YYYY-MM-DD. Prefer relative days for schedules.

## `departureDaysFromToday` (type: `integer`):

UTC days ahead when no fixed departure date is provided. Keeps scheduled tasks in the future.

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

Optional fixed return date; makes a round trip.

## `returnDaysAfterDeparture` (type: `integer`):

Optional relative return interval for evergreen round-trip tasks.

## `dateFrom` (type: `string`):

Optional inclusive calendar start YYYY-MM-DD; use with dateTo. Calendar mode is one way.

## `dateTo` (type: `string`):

Inclusive calendar end, maximum 60 dates.

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

Optional 1–60 day relative calendar, starting departureDaysFromToday ahead; alternative to dateFrom/dateTo.

## `cheapestPerDayOnly` (type: `boolean`):

In calendar mode return one lowest-priced first-page itinerary per route/date.

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

Maximum unique first-page itineraries. Calendar cheapest-only mode returns one.

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

ISO currency code sent as curr. Prices are displayed search fares, not booking quotes.

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

Flights UI language. Full structured parsing is verified for English; other languages can retain partial raw-label rows.

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

Two-letter country code sent as gl.

## `nonstopOnly` (type: `boolean`):

Filter locally without an extra fee. Ambiguous/unparsed stop counts are excluded.

## Actor input object example

```json
{
  "routes": [
    {
      "from": "JFK",
      "to": "LIS"
    }
  ],
  "departureDaysFromToday": 45,
  "cheapestPerDayOnly": true,
  "maxResultsPerSearch": 5,
  "currency": "USD",
  "language": "en",
  "country": "us",
  "nonstopOnly": false
}
```

# Actor output Schema

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

No description

# 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": [
        {
            "from": "JFK",
            "to": "LIS"
        }
    ],
    "departureDaysFromToday": 45,
    "maxResultsPerSearch": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("sumitr_mardy/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": [{
            "from": "JFK",
            "to": "LIS",
        }],
    "departureDaysFromToday": 45,
    "maxResultsPerSearch": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("sumitr_mardy/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": [
    {
      "from": "JFK",
      "to": "LIS"
    }
  ],
  "departureDaysFromToday": 45,
  "maxResultsPerSearch": 5
}' |
apify call sumitr_mardy/google-flights-scraper --silent --output-dataset

```

## MCP server setup

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