# Flight Price Tracker — Cheapest Day to Fly & Airfare Alerts (`kestrel/flight-price-tracker`) Actor

Flight price tracker for Google Flights: the cheapest fare for every departure day in your window, one row per day with price, airline, stops and times, ranked so the cheapest day to fly is row one. Set a max price and only days under it are delivered and billed. Pay per fare row.

- **URL**: https://apify.com/kestrel/flight-price-tracker.md
- **Developed by:** [Tedj MEABIOU](https://apify.com/kestrel) (community)
- **Categories:** Travel, Automation, Business
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 fare row (cheapest of the day)s

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Flight Price Tracker — Cheapest Day to Fly & Airfare Alerts

A **flight price tracker** that reads Google Flights and returns the cheapest fare for every departure day in your window — one row per route and day, with the airline, stops, times and duration behind that price. Run it once to see the **cheapest day to fly**; schedule it and you have **airfare price tracking** you own, with a `maxPrice` line that turns any run into a **flight price alert**. No API key, no login, no browser.

It is a different product from an itinerary scraper. An itinerary scraper bills every fare Google lists for a day (usually 10–35). This bills **one row per day**, so a 30-day window on a route is 30 rows — cheap enough to run every morning.

Last verified working: 2026-08-29.

### What does the flight price tracker do?

You give it routes, a first departure day and a window length. For each route it searches every day in the window, keeps the cheapest itinerary of each day, ranks the days, and delivers:

- **`fare` rows** — one per route and departure day: `price` for all passengers, `airline` and `airlines`, `stops`, `depart_time` / `arrive_time`, `duration` and `duration_minutes`, every `layover`, `co2_kg`, the `google_url` that reproduces the search, `itineraries_seen` (how many fares Google listed that day), and two ranking fields: `rank_in_window` (1 = the cheapest day of the window) and `cheapest_in_window` (`true` on exactly one day per route).
- **`status` rows** — one per route: `days_searched`, `fares` delivered, `filtered` (days over `maxPrice`), `no_results`, `errors`, the window's `cheapest` fare and its `cheapest_date`. Never charged.

Round trips are priced the way Google shows them: set `tripLengthDays` and every day becomes a round trip returning that many days later, with `price` as the **total for both legs** and `round_trip_total: true`.

### Cheapest day to fly, one row per day

The question most people bring to Google Flights is not "what is the fare" but "which day should I leave". Google answers it with a calendar you have to read by eye. This answers it as data: the `fare` row with `cheapest_in_window: true` is the day, and `rank_in_window` orders the rest — so "the three cheapest departures in October" is a filter on one column, not a spreadsheet exercise.

A seven-day window on one route is seven searches and at most seven rows. A month is 30. Two routes over a month is 60 rows, and the two `status` rows tell you which route and day won overall. Sort by `price`, or by `depart_date` to see the shape of the month; every row also says what it beat, in `itineraries_seen`.

The ranking is computed over the whole window **before** any `maxPrice` filter, so a filtered run still tells you that the day you kept was, say, the second-cheapest of the month.

### Airfare price tracking on a schedule

Google's own tracker emails you when a fare moves, on the routes and dates it chooses, and keeps the history to itself. Scheduling this run gives you the same signal as rows you keep:

- Every row carries `fetched_at`, so a **flight price history** for your routes falls out of the dataset — one series per route and departure day, growing by one point per run.
- Relative dates (`"30 days"`, `"6 weeks"`) mean a scheduled run always looks the same distance ahead. It never goes stale, and it never prices a day that has passed.
- The window moves with the calendar, so yesterday's rank 1 can be compared with today's: that is **flight price monitoring** for a route, not a one-off snapshot.
- The `status` rows give you a one-line summary per route per run — `cheapest` and `cheapest_date` — which is usually all a daily message needs.

At one row per day, the arithmetic of tracking is simple: a daily run on three routes over a 30-day window is 90 rows a day, about 2,700 a month. The price per row is on this page's pricing tab; the compute behind a run that size is a fraction of a cent.

### Flight price alerts: maxPrice filters before billing

Set `maxPrice` and the run delivers only the days whose cheapest fare is at or under that number. Days over the line are dropped **before** billing — an alert run that finds nothing costs nothing, and the `status` row still tells you how many days were `filtered` and what the window's `cheapest` was, so you can see how far off the line you are.

That makes a **flight price drop alert** a two-node automation: schedule the run with `maxPrice`, and send a message when the dataset has any `fare` row. You do not need to store the previous price or diff anything — the filter is the comparison. Because you keep every row, the alert can be smarter than Google's: "nonstop under 400 on any of these three routes, any day next month" is one input.

```json
{ "routes": ["JFK-LHR", "EWR-LHR"], "departDate": "14 days", "days": 30, "maxStops": "nonstop", "maxPrice": 400, "currency": "USD" }
```

Nothing under 400? Zero fare rows, zero charge, two `status` rows with the real minimum in `cheapest`.

### Google Flights price tracker vs this actor

Google's tracker, Hopper, Kayak alerts and the airline apps all do one thing well: tell *you* when *their* pick of dates moves. What none of them gives you is the table — every day, with the fare and the itinerary behind it, in a format you can join, chart, or feed to an automation. The comparison in practice:

| | Google's price tracking | This actor |
| --- | --- | --- |
| Which days | The dates you saved, or Google's suggestion | Every day of a window you set, 1–60 days |
| Output | An email | A dataset row per day: price, airline, stops, times, rank |
| History | Google keeps it | You keep it — `fetched_at` on every row |
| Alert condition | Google decides what counts as a drop | Your `maxPrice`, per route, with stops and cabin filters |
| Integration | None | Apify API, n8n, Make, Zapier, MCP for AI agents |
| Cost | Free, unexportable | Per delivered row, nothing for empty or filtered days |

If what you want is **cheap flights** on a route as a one-off, Google's page is fine. If you want to **track flight prices** across dates over weeks, feed them to a sheet or a bot, or watch a line and act when a fare crosses it, that needs rows, and rows are what this returns.

### Input

| Field | What it does |
| --- | --- |
| `routes` | Routes as airport codes, one per line: `LIS-LHR`, `JFK-LAX`. Google's city codes work too — `NYC-LON` searches every New York and London airport. Written `LIS-LHR`, `lis > lhr` or `JFK to LAX`, all the same. |
| `departDate` | The first day of the window: `2026-10-05`, or relative so schedules never go stale: `30 days`, `6 weeks`, `tomorrow`. Past dates are rejected. |
| `days` | How many consecutive departure days to price, 1–60. One search and at most one billed row per day. Default 14. |
| `tripLengthDays` | `0` = one-way. `N` = every day is a round trip returning N days after departure, priced for both legs. |
| `seat` | `economy`, `premium_economy`, `business`, `first`. |
| `adults` | Up to 9. Prices are the total for everyone travelling. |
| `maxStops` | `any`, `nonstop`, `one_or_fewer`, `two_or_fewer` — applied before picking the day's cheapest fare. |
| `maxPrice` | `0` = deliver every day. `N` = deliver only days at or under N in `currency`; the rest are dropped before billing. |
| `currency` | Any ISO code for every price, e.g. `USD`, `EUR`, `GBP`. |
| `market` | Two-letter country code for the Google market (`gl`). Fares and airlines differ by market. |
| `sessions`, `perIp` | Parallel proxy sessions and the pace of each. Leave alone unless a run is throttled. |
| `proxyConfiguration` | Apify Proxy. Required — Google blocks datacentre traffic that is not rotated. |

#### Example: the cheapest day to fly in the next month, two routes

```json
{ "routes": ["LIS-LHR", "LIS-CDG"], "departDate": "tomorrow", "days": 30, "currency": "EUR", "market": "pt" }
```

#### Example: a daily nonstop business-class watch, week-long round trips

```json
{ "routes": ["JFK-LHR"], "departDate": "14 days", "days": 21, "tripLengthDays": 7, "seat": "business", "maxStops": "nonstop" }
```

#### Example: an alert line for a family of four

```json
{ "routes": ["LHR-JFK"], "departDate": "45 days", "days": 14, "adults": 4, "maxPrice": 1800, "currency": "GBP", "market": "gb" }
```

### Output

One `fare` row per route and day:

```json
{
  "type": "fare", "route": "LIS-LHR", "origin": "LIS", "destination": "LHR", "trip": "one_way",
  "depart_date": "2026-10-05", "return_date": null, "seat": "economy", "adults": 1, "currency": "USD",
  "price": 127, "price_display": "127 US dollars", "round_trip_total": false,
  "airline": "Tap Air Portugal", "airlines": ["Tap Air Portugal"], "stops": 0,
  "depart_time": "8:00 PM", "arrive_time": "10:55 PM", "depart_day": "Monday, October 5", "arrive_day": "Monday, October 5",
  "duration": "2 hr 55 min", "duration_minutes": 175,
  "layovers": null, "layover_airports": null, "overnight_layover": false, "co2_kg": 123,
  "google_url": "https://www.google.com/travel/flights?tfs=...",
  "itineraries_seen": 12, "cheapest_in_window": true, "rank_in_window": 1,
  "fetched_at": "2026-08-29T06:25:14+00:00"
}
```

A day whose cheapest fare has a connection carries it:

```json
{
  "stops": 1, "duration_minutes": 785,
  "layovers": [{ "index": 1, "of": 1, "minutes": 550, "airport": "Aéroport de Paris-Charles de Gaulle", "city": "Paris" }],
  "layover_airports": ["Aéroport de Paris-Charles de Gaulle"]
}
```

And one `status` row per route:

```json
{
  "type": "status", "route": "LIS-LHR", "trip": "one_way", "seat": "economy", "currency": "USD",
  "depart_date": "2026-10-05", "return_date": null,
  "days_searched": 7, "fares": 7, "filtered": 0, "no_results": 0, "errors": 0,
  "cheapest": 127, "cheapest_date": "2026-10-05", "status": "ok", "error": null,
  "fetched_at": "2026-08-29T06:25:20+00:00"
}
```

`duration_minutes` exists so you can sort without parsing `"13 hr 5 min"`; `rank_in_window` and `cheapest_in_window` exist so you never have to compute the minimum yourself. The dataset has three views in the Console — *Overview*, *Cheapest fare by day* and *Run status* — and exports to CSV, Excel or JSON.

### How much does it cost?

Pay per event, one event per **delivered** `fare` row — at most one per route and departure day. Days on which Google lists nothing, days dropped by `maxPrice`, failed days and `status` rows are free, and nothing a spending limit refused is ever delivered.

Some worked sizes at the listed per-row price:

- One route, 7 days: 7 rows.
- One route, 30 days: 30 rows.
- Three routes, 30 days, daily for a month: 90 rows a run, about 2,700 a month.
- An alert run with `maxPrice` that finds nothing: 0 rows, $0 beyond a fraction of a cent of compute.

The verified runs behind this listing used $0.0002–$0.003 of platform compute each. Exact per-row pricing is on this page's pricing tab.

### How to use it from Python, JavaScript, curl, n8n, Make or an AI agent

Run it and read the dataset. In **Python**:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("kestrel/flight-price-tracker").call(run_input={
    "routes": ["LIS-LHR"], "departDate": "30 days", "days": 14, "currency": "EUR",
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["type"] == "fare":
        print(row["rank_in_window"], row["depart_date"], row["price"], row["airline"], row["stops"])
```

In **JavaScript** (Node):

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('kestrel/flight-price-tracker').call({
    routes: ['JFK-LHR'], departDate: '14 days', days: 21, tripLengthDays: 7, maxStops: 'nonstop',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const best = items.find((i) => i.type === 'fare' && i.cheapest_in_window);
console.log(best.depart_date, best.price, best.airline);
```

With **curl**, synchronously, getting the dataset straight back:

```bash
curl -X POST "https://api.apify.com/v2/acts/kestrel~flight-price-tracker/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H 'Content-Type: application/json' \
  -d '{"routes":["LIS-LHR"],"departDate":"30 days","days":7,"maxPrice":150,"currency":"EUR"}'
```

For **n8n** and **Make** (and Zapier), the whole alert is three steps: a Schedule trigger, an HTTP Request to the `run-sync-get-dataset-items` URL above with the JSON body, and a message step that fires when the returned array has any row with `type: "fare"`. With `maxPrice` set, an empty array means "nothing under the line today". Map `depart_date`, `price`, `airline` and `google_url` into the message and the recipient can book from it.

For **AI agents**, the actor is callable over Apify's MCP server, so an agent asked "when is it cheapest to fly Lisbon to London next month" can run it and read the `cheapest_in_window` row back with no glue code.

### Is it legal to track prices from Google Flights?

This reads the same public result page a visitor sees, with no login and no account, and it collects **no personal data** — a fare is a price, an airline and two timestamps. In the EU and the US, reading public pages that contain no personal data is broadly accepted, and *hiQ v. LinkedIn* is the usual reference point for public data specifically.

That is not the whole story: Google's Terms of Service discourage automated access, so this is a terms question rather than a criminal one, and the responsibility sits with the operator of the run. Prices are facts and facts are not copyrightable, but a database can attract *sui generis* protection in the EU, so do not redistribute the raw dataset as a product. If you are unsure how any of this applies to your use, ask a lawyer — this is not legal advice.

### Limits and honest notes

- **One row per day means one itinerary per day.** The row is the cheapest fare Google lists for that day under your cabin and stop filters. If you need every itinerary — to compare airlines on the same day, or to see the second-cheapest option — use the [Google Flights Scraper](https://apify.com/kestrel/google-flights-prices), which bills per itinerary instead.
- **Google's list is what you get.** Fares visible only after login, in corporate channels or on airline sites Google does not index are not in it.
- **Results are read in English.** The parser reads Google's English accessibility labels, which is why there is no language input; `currency` and `market` are the two inputs that change the fares themselves.
- **Prices include what Google shows** — taxes and carrier fees as Google presents them. Baggage and seat fees are not in the number.
- **A currency swap is an error, not a row.** Some markets ignore the requested currency; a day priced in another one is reported in `status` rather than billed.
- **The window is capped at 60 days** per run. For a longer horizon, run twice with different `departDate` values.
- **Ties go to the earlier day.** When two days share the lowest fare, the earlier departure takes rank 1.

### FAQ

#### Does it need a Google Flights API key?

No. There is no public Google Flights API to hold a key for, and this uses none. No login, no cookies, no browser — it builds the same `tfs` query parameter Google puts in its own URLs and reads the page Google returns. If you want a **flight price tracking api** shape, call it synchronously through Apify's API (the curl example above) and treat the rows as the response.

#### How do I find the cheapest day to fly on Google Flights?

Set `departDate` to the first day you could leave and `days` to how far you are flexible. The `fare` row with `cheapest_in_window: true` is the answer; `rank_in_window` orders the alternatives. The `status` row repeats it as `cheapest` and `cheapest_date` if you only want the headline. That is the **cheapest day to fly google flights** search, as one input and one column.

#### Can I get flight price history?

Not retroactively — Google does not publish history, and neither can this. What you can do is *build* it: schedule a daily run with a relative `departDate`, and every row lands with `fetched_at`. Two weeks of that is two weeks of history per route and departure day that is yours to keep and chart — a **flight price calendar** over time, not just across dates.

#### How do I set up Google Flights price alerts with it?

Set `maxPrice`, schedule the run, and send a message whenever the dataset contains a `fare` row. Because filtering happens before billing, a quiet day costs nothing. **Google flights price alerts** in their native form only cover the dates you saved; this covers every day of the window and any stop or cabin filter you set.

#### Does it do round trips?

Yes. `tripLengthDays: 7` prices every day of the window as a week-long round trip; `price` is the total for both legs and `round_trip_total` is `true`. **Round trip flight prices** across a window are how most leisure searches actually look, and that is one input here.

#### What about nonstop-only, or business class?

`maxStops: "nonstop"` restricts every day's search to nonstop itineraries before the cheapest is picked, so the row is the cheapest *nonstop* that day — a **nonstop flight search** per day rather than one that a cheap connection would otherwise win. `seat: "business"` prices **business class fares** the same way; expect a different, smaller market than economy rather than a fixed multiple of it.

#### Why do prices differ from what I see in my browser?

Three usual reasons: your `market` differs from your browser's country, your `currency` differs, or the fare moved — airline pricing changes through the day. Set `market` and `currency` explicitly and re-run to compare like for like; each row carries the `google_url` that reproduces the exact search.

#### How many routes and days can one run track?

Up to 60 days per route, any number of routes; each route is searched in parallel across `sessions`. A 30-day window on five routes is 150 searches and, with no filter, 150 rows. Larger horizons are two runs with different `departDate` values.

#### Is it a scraper for Skyscanner or Kayak?

No — it reads Google Flights. Those sites and Google draw on largely the same carriers and online travel agents, so for **airline ticket prices** on a route the numbers move together and you get them from one source on one schedule. For the full itinerary list from the same source, the **google flights scraper** linked below is the sibling listing.

#### Is there a free tier?

Empty days, filtered days, failed days and `status` rows are always free, and Apify's free plan includes monthly platform credit you can spend on the paid rows. A run that finds nothing under your `maxPrice` costs nothing beyond a fraction of a cent of compute.

### Related scrapers

Need every itinerary, not just the cheapest? The **[Google Flights Scraper](https://apify.com/kestrel/google-flights-prices)** is the same engine billing per itinerary row — use it when you want to compare airlines and times on the same day; use this one when you want the **cheapest flights by date** across a window.

The rest of the trip, from the same publisher, with the same pay-per-delivered-row billing:

- **[Google Hotels Prices Scraper](https://apify.com/kestrel/google-hotels-prices)** — hotel prices and every booking site's rate for a stay, for the same dates you just priced the fare for.
- **[Airbnb Scraper](https://apify.com/kestrel/airbnb-prices-calendar)** — Airbnb prices, availability calendars and occupancy.
- **[Airbnb Reviews Scraper](https://apify.com/kestrel/airbnb-reviews-scraper)** — every guest review of an Airbnb listing.
- **[Agoda Reviews Scraper](https://apify.com/kestrel/agoda-reviews-scraper)** — Agoda hotel reviews with separate positives and negatives.

All of them bill per delivered row, never charge for rows a filter or a spending limit removed, and write an Apify dataset you can export to CSV, Excel or JSON.

# Actor input Schema

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

Routes as airport codes, one per line: "LIS-LHR", "JFK-LAX". Google's city codes work too (NYC-LON searches every New York and London airport). Each route is tracked across every day of the window.

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

The first day of the window: YYYY-MM-DD, or relative so a scheduled run never goes stale: "30 days", "6 weeks", "tomorrow". Past dates are rejected.

## `days` (type: `integer`):

How many consecutive departure days to price, starting on the first day. 14 = two weeks of fares; 30 = a month. One search and at most one billed row per day.

## `tripLengthDays` (type: `integer`):

0 = one-way fares. N = every day is priced as a round trip returning N days after departure, and the price is the total for both legs.

## `seat` (type: `string`):

Cabin to price. Business and first are a different, smaller market than economy.

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

Adult passengers. Every price is the total for all of them.

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

Limit connections before picking the day's cheapest fare. "Nonstop only" tracks the fare most travellers actually want; "Any" takes the cheapest of everything Google lists.

## `maxPrice` (type: `number`):

0 = deliver every day. N = deliver only days whose cheapest fare is at or under N in the currency below. Days over the line are dropped BEFORE billing, so an alert run that finds nothing costs nothing.

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

ISO code for every price, e.g. USD, EUR, GBP. If Google prices in another currency for your market the day is reported as an error rather than billed in the wrong one.

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

Two-letter country code for the Google market (gl), e.g. us, de, gb. Fares and available airlines differ by market. Results are always read in English.

## `sessions` (type: `integer`):

How many proxy sessions (egress IPs) run in parallel. More is faster; each one is paced separately.

## `perIp` (type: `number`):

Pace for each session. Google tolerates about 0.5/s per IP; raising it causes retries, not speed.

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

Apify Proxy is required: Google blocks datacentre traffic that is not rotated. The default group works.

## Actor input object example

```json
{
  "routes": [
    "LIS-LHR"
  ],
  "departDate": "30 days",
  "days": 7,
  "tripLengthDays": 0,
  "seat": "economy",
  "adults": 1,
  "maxStops": "any",
  "maxPrice": 0,
  "currency": "USD",
  "market": "us",
  "sessions": 4,
  "perIp": 0.5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

One row per route and departure day with that day's cheapest fare, plus one status row per route. Fare rows are billed as delivered; status rows are always free.

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

One JSON record with the routes and days searched, fares delivered and charged, days filtered by maxPrice, the cheapest fare and its day, error counts and HTTP stats.

# 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": [
        "LIS-LHR"
    ],
    "departDate": "30 days",
    "days": 7
};

// Run the Actor and wait for it to finish
const run = await client.actor("kestrel/flight-price-tracker").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": ["LIS-LHR"],
    "departDate": "30 days",
    "days": 7,
}

# Run the Actor and wait for it to finish
run = client.actor("kestrel/flight-price-tracker").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": [
    "LIS-LHR"
  ],
  "departDate": "30 days",
  "days": 7
}' |
apify call kestrel/flight-price-tracker --silent --output-dataset

```

## MCP server setup

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

```

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/mMGReYdTa3XMOtcz1/builds/XXubYl77os7lh5lnu/openapi.json
