# Flight Price Calendar — cheapest dates for any route (`lergassy/flight-price-calendar`) Actor

\[$0.20/1K rows] The cheapest departure date for any route: lowest fare per day for up to a year, five cheapest days flagged, departure x return grid for round trips. Sweep many routes in one run. No run fee, no search fee.

- **URL**: https://apify.com/lergassy/flight-price-calendar.md
- **Developed by:** [Matvey](https://apify.com/lergassy) (community)
- **Categories:** Travel, Agents, MCP servers
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.10 / 1,000 rows

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

## Flight Price Calendar

**Flight Price Calendar** answers one question: **when is this route cheapest?** It returns the lowest
fare for every departure date over the next weeks or the whole year — Google's own date grid, as data —
and flags the cheapest days. For round trips it returns the departure × return grid, so you also see
whether leaving a day earlier or staying a night longer is cheaper.

**$0.20 per 1,000 rows. No run fee, no search fee, no proxy fee.** A full year of dates for one route
is 365 rows — **7 cents**.

### What a run returns

One row per date:

| Field | Example |
|---|---|
| `date` | 2027-03-15 |
| `price` / `currency` | 92 / USD |
| `isCheapest` | true for the five cheapest days in the window |
| `googleFlightsUrl` | Opens that exact date on Google Flights |
| `tripLength` (round trips) | Nights of stay for this departure × return pair |

Plus a summary row with `cheapestDates` — the five best days with their prices — and, if you want it,
Google's `priceLevel` and the typical price band for the route.

### How to use it

1. Enter **origin**, **destination** and a **departure date** to anchor the window.
2. Set **calendarDays**: `60` for the next two months, `365` for the year.
3. Click **Start**. You get one row per date, cheapest days flagged.

Round trip: add a **return date**. Google keeps your trip length flexible around it and returns the
grid, so you get "leave Tuesday, come back Sunday — $80 less" as rows you can sort.

#### A whole route map at once

```json
{
  "routes": [
    { "origin": "DPS", "destination": "SIN" },
    { "origin": "DPS", "destination": "BKK" },
    { "origin": "DPS", "destination": "KUL" }
  ],
  "calendarDays": 180
}
```

Three routes × 180 days = 540 rows = **11 cents**. Because nothing is charged per search, sweeping
fifty routes costs exactly fifty times the rows and not a cent more.

### What it is good for

- **Flexible travellers and fare-deal sites**: publish "cheapest week to fly Bali–Singapore" from data
  instead of guesswork.
- **Travel agencies**: answer "when should I book" with the actual grid in front of the client.
- **Pricing and revenue teams**: a year of daily lows per route is a demand curve — school holidays,
  Eid, Christmas and the quiet weeks all show up.
- **Trip planners and AI agents**: the calendar is the fastest way to turn "sometime in March" into a
  concrete date.

### Fields you can set

| Input | What it does |
|---|---|
| `calendarDays` | Size of the window: 30, 60, 180, 365 |
| `returnDate` | Switches to the departure × return grid |
| `adults` / `children` / `infants` | Up to 9 passengers, infants in seat or on lap |
| `cabinClass` | economy, premium economy, business, first |
| `maxStops` | Nonstop only, or up to one or two stops |
| `currency` / `market` | Price in any currency, from any country's point of sale |
| `routes` | A list of routes swept in one run |

### What it costs

One event, $0.0002 per row — **$0.20 per 1,000**, down to $0.10 on higher Store tiers. Searches,
retries, residential proxy and run start are free; rows that fail are never charged. A year for one
route: 7 cents. Ten routes, 60 days, every week for a month: 2,400 rows — **48 cents**.

### Notes and limits

Calendar prices are the lowest fare Google shows for that date at the moment of the run — they move
during the day, so a daily schedule is worth more than one big sweep. A stay longer than about a month
returns a thinner grid, because most airlines cap round-trip stays. If Google does not answer the
calendar request, an `error` row says so instead of a silent gap, and it is not charged.

The Actor reads publicly displayed prices without logging in or collecting personal data. Google's
terms restrict automated access, and the legality of scraping public data depends on your jurisdiction
and use.

### Need something else?

Want the grid in a different shape, or a sweep across a hundred routes? **Open an issue on this
Actor's page** — answered the same day.

Need the full itinerary list, layovers, aircraft, CO₂ and booking options with seller prices? Use
[Google Flights Scraper](https://apify.com/lergassy/google-flights-scraper). Watching a single route
for a price drop? [Flight Price Tracker](https://apify.com/lergassy/flight-price-tracker).

# Actor input Schema

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

Departure airport code, e.g. <code>DPS</code> (Bali), <code>CGK</code> (Jakarta), <code>SIN</code> (Singapore), <code>LHR</code> (London)

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

Arrival airport code, e.g. <code>SIN</code> (Singapore), <code>BKK</code> (Bangkok), <code>SYD</code> (Sydney). Ignored when <b>Explore</b> is on.

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

Format <code>YYYY-MM-DD</code> Leave the whole route empty and the Actor runs a demo search so a first run always returns rows.

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

Leave empty for one-way. Format <code>YYYY-MM-DD</code>. Round-trip prices are the total for both directions.

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

Passengers aged 12 and over (1–9). Prices are the total for all passengers.

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

Passengers aged 2 to 11. Google applies child fares where the airline offers them.

## `infantsInSeat` (type: `integer`):

Under 2 years old, with their own seat (charged as a child fare on most airlines).

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

Under 2 years old, travelling on an adult's lap (usually ~10% of the adult fare).

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

Economy, premium economy, business or first

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

<code>any</code>, <code>0</code> nonstop only, <code>1</code> up to one stop, <code>2</code> up to two stops

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

ISO code for prices: <code>USD</code>, <code>IDR</code>, <code>EUR</code>, <code>SGD</code>, <code>AUD</code>…

## `market` (type: `string`):

Two-letter country code of the point of sale, e.g. <code>US</code>, <code>ID</code>, <code>GB</code>, <code>DE</code>, <code>AU</code>. Google returns the fares, sellers and booking links available to buyers in that country — prices differ by market. Leave empty for Google's default.

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

Google returns up to ~150 itineraries per search

## `sortBy` (type: `string`):

Google's own ranking (best), or by price, duration or departure time

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

Lowest fare for each departure date over this many days starting at the departure date — Google's date grid as data. <code>0</code> = off, <code>60</code> = two months, up to <code>365</code>. One request per 90 days. Adds <code>calendar\_day</code> items and a <code>calendar.cheapestDates</code> summary to the search item. For round trips the trip length (return minus departure) is kept fixed.

## `resolveBookingOptions` (type: `boolean`):

For the top flights of each search, fetch Google's booking options: airline and travel agencies (Trip.com, Expedia, Kiwi…), their prices, fees, and a deep link to book. Round trips need <b>Return flights</b> on — options are fetched for the outbound plus its cheapest return. One extra request per flight — cap it with the field below.

## `resolveReturnFlights` (type: `boolean`):

For the top outbound itineraries of a round trip, fetch Google's list of return flights — each with the total price for both directions — so you get complete outbound + return combinations. One extra request per outbound itinerary.

## `exploreAnywhere` (type: `boolean`):

Instead of a fixed route, list the cheapest destinations Google suggests from <b>Origin</b> — city, country, price, airline, stops, duration and suggested dates. Uses <b>Departure/Return date</b> when set, otherwise Google's flexible one-week trips over the coming months.

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

Search many routes in one run. Each item: <code>{"origin": "DPS", "destination": "BKK", "departureDate": "2026-10-15", "returnDate": "2026-10-22"}</code> (returnDate optional). Passengers, cabin and filters below apply to every route.

## `multiCityLegs` (type: `array`):

A multi-city trip as a list of legs: <code>{"origin": "SIN", "destination": "BKK", "date": "2026-10-15"}</code>, <code>{"origin": "BKK", "destination": "HKT", "date": "2026-10-19"}</code>, <code>{"origin": "HKT", "destination": "SIN", "date": "2026-10-23"}</code>. Google prices the trip leg by leg; the Actor resolves complete itineraries for the top first-leg options. The total is shown when Google can sell all legs as one ticket.

## `airlines` (type: `array`):

IATA airline codes to keep, e.g. <code>SQ</code>, <code>GA</code>, <code>QZ</code>. Leave empty for all.

## `excludeAirlines` (type: `array`):

IATA airline codes to drop, e.g. <code>TR</code> (Scoot)

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

Drop flights above this price (in the selected currency)

## `maxDurationMinutes` (type: `integer`):

Drop itineraries longer than this, e.g. <code>720</code> for 12 hours

## `maxLayoverMinutes` (type: `integer`):

Drop itineraries with any layover longer than this, e.g. <code>180</code>

## `departureTimeFrom` (type: `string`):

Earliest departure time, local, e.g. <code>06:00</code>

## `departureTimeTo` (type: `string`):

Latest departure time, local, e.g. <code>12:00</code>

## `arrivalTimeFrom` (type: `string`):

Earliest arrival time, local, e.g. <code>08:00</code>

## `arrivalTimeTo` (type: `string`):

Latest arrival time, local, e.g. <code>22:00</code>

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

Language of airport and airline names, e.g. <code>en</code>, <code>id</code>, <code>de</code>

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

Return just the price calendar and the search summary — the cheapest way to sweep dates or routes.

## `includePriceInsights` (type: `boolean`):

Add Google's price level (low / typical / high), typical price range and 60-day price history to the search summary and to every flight

## `includeSearchSummary` (type: `boolean`):

Adds one <code>type: "search"</code> row per search with how many itineraries Google had, its own lowest price, the price level and the price history. It is not a flight, so it is off by default and the table stays flights only — the same summary is always saved as the run's <b>SEARCH\_SUMMARY</b> record in the key-value store.

## `maxDestinations` (type: `integer`):

How many destinations to return in Explore mode, cheapest first.

## `maxBookingResolutions` (type: `integer`):

Per search, counted from the top of the sorted list

## `maxReturnResolutions` (type: `integer`):

Per round-trip search, counted from the top of the sorted list

## `maxReturnOptions` (type: `integer`):

How many return flights to keep for each outbound itinerary, cheapest first.

## `maxMultiCityResolutions` (type: `integer`):

How many first-leg options to follow through all legs (one request per leg each)

## `dataSource` (type: `string`):

<b>Auto</b>: Google's results API (full list of 100–150 itineraries, needs a residential proxy) with automatic fallback to the results page (first ~15 itineraries, works from any IP). Force one source for debugging.

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

Google serves the full results API only to residential IPs — keep <b>Residential</b> proxies for complete results (a search transfers ~250 KB, a fraction of a cent). Datacenter proxies still work through the page fallback with the first ~15 itineraries.

## Actor input object example

```json
{
  "origin": "DPS",
  "destination": "SIN",
  "departureDate": "2027-03-15",
  "adults": 1,
  "children": 0,
  "infantsInSeat": 0,
  "infantsOnLap": 0,
  "cabinClass": "economy",
  "maxStops": "any",
  "currency": "USD",
  "maxResults": 100,
  "sortBy": "best",
  "calendarDays": 60,
  "resolveBookingOptions": false,
  "resolveReturnFlights": false,
  "exploreAnywhere": false,
  "routes": [],
  "multiCityLegs": [],
  "language": "en",
  "calendarOnly": true,
  "includePriceInsights": true,
  "includeSearchSummary": true,
  "maxDestinations": 60,
  "maxBookingResolutions": 10,
  "maxReturnResolutions": 10,
  "maxReturnOptions": 20,
  "maxMultiCityResolutions": 5,
  "dataSource": "auto",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

One row per flight itinerary: airline, flight numbers, price in the requested currency, Google's price level against the route's usual band, stops and layovers, times, aircraft, CO₂ and booking options with seller prices. Search summaries, explore destinations and cheapest-date rows share the dataset.

# 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": "DPS",
    "destination": "SIN",
    "departureDate": "2027-03-15",
    "routes": [],
    "multiCityLegs": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/flight-price-calendar").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": "DPS",
    "destination": "SIN",
    "departureDate": "2027-03-15",
    "routes": [],
    "multiCityLegs": [],
}

# Run the Actor and wait for it to finish
run = client.actor("lergassy/flight-price-calendar").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": "DPS",
  "destination": "SIN",
  "departureDate": "2027-03-15",
  "routes": [],
  "multiCityLegs": []
}' |
apify call lergassy/flight-price-calendar --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lergassy/flight-price-calendar"
        }
    }
}
```

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/gm204vKXycpNev6dp/builds/IOOE6YctebYzUDm14/openapi.json
