# Google Flights Scraper (bulk searches) (`steadydata/google-flights`) Actor

Flight options from Google Flights for up to 200 searches per run: price, airlines, flight numbers, times, duration, stops and layovers, aircraft and CO2, in Google's order. One-way or round trip, any cabin class and currency. Pay only for delivered flights.

- **URL**: https://apify.com/steadydata/google-flights.md
- **Developed by:** [Steadydata Team](https://apify.com/steadydata) (community)
- **Categories:** Travel, E-commerce, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.77 / 1,000 flight listeds

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, bulk searches)

Flight options from Google Flights for **up to 200 route-and-date searches per run**:
price, airlines and flight numbers, departure and arrival times, duration, stops and
layover airports, aircraft and Google's CO2 estimate, in the order Google Flights shows
them ("Top options" first). One-way or round trip, any cabin class, any currency. **You
only pay for flight options that are actually delivered.**

### Why this scraper

- **The structured data, not a screenshot.** Google Flights renders its results from an
  embedded data block; this actor reads that block, so times are exact, flight numbers
  are real and nothing is guessed from text.
- **Bulk by design.** Paste 200 searches such as `AMS LHR 2026-10-15` or
  `JFK LAX 2026-11-03 2026-11-10` and get one flat table with the search and Google's rank
  on every row, ready for fare monitoring or route analysis.
- **Round trips priced as round trips.** For a return search the price is Google's round
  trip total, exactly as the page shows it, with the outbound options listed.
- **No residential proxies.** Google Flights serves its results page to Apify's standard
  datacenter pool; in testing on 13-09-2026 a search came back in about 3 seconds with 68
  itineraries.
- **Only delivered flights are charged.** A search with no results, or a badly formed
  one, comes back as a clear error record at no cost.

### Who this is for

Fare monitoring for a set of routes and dates. Travel researchers and analysts comparing
airlines, stops and prices across markets. Teams building price alerts or route datasets
without scraping a browser.

### Who this is not for

This actor returns Google's displayed options, not a booking: `bookingUrl` opens the
search on Google Flights. Prices are the ones Google shows at the moment of the run and
can change by the hour. Google decides how many itineraries to show for a search; the
actor delivers what is on the page (10 to 70 in testing) and cannot force more. Only
airport codes are accepted, not city names.

### Input example

```json
{
    "searches": ["AMS LHR 2026-10-15", "JFK LAX 2026-11-03 2026-11-10"],
    "seatClass": "economy",
    "adults": 1,
    "currency": "EUR",
    "maxFlightsPerSearch": 50
}
```

A search is `FROM TO YYYY-MM-DD` for one-way, with a second date for a round trip.

### Output example

```json
{
    "search": "AMS LHR 2026-10-15",
    "rank": 1,
    "group": "top",
    "price": 117,
    "currency": "EUR",
    "airlines": ["British Airways"],
    "airlineCodes": ["BA"],
    "flightNumbers": ["BA443"],
    "departureAirport": "AMS",
    "departureTime": "2026-10-15T19:40",
    "arrivalAirport": "LHR",
    "arrivalTime": "2026-10-15T19:55",
    "durationMinutes": 75,
    "stops": 0,
    "layoverAirports": [],
    "aircraft": ["Airbus A320"],
    "emissionsKg": 54.0,
    "tripType": "one_way",
    "seatClass": "economy",
    "bookingUrl": "https://www.google.com/travel/flights?tfs=...&hl=en&curr=EUR",
    "status": "ok"
}
```

`layoverAirports` lists the IATA codes of the stopovers in order and is an empty list on a nonstop flight; `stops` says how many there are. On a long-haul search such as AMS to SYD every row carries them.

A search that yields nothing produces an error record instead, and is **not** charged:

```json
{
    "input": "AMS LHR",
    "status": "error",
    "errorCode": "INVALID_SEARCH",
    "error": "Expected 'FROM TO YYYY-MM-DD [YYYY-MM-DD]' with IATA codes, got 'AMS LHR'"
}
```

Error codes: `INVALID_SEARCH`, `NO_FLIGHTS`, `BLOCKED`. `INPUT_TRUNCATED` appears once when your input is longer than this actor accepts.

### Related actors from steadydata

- [google-flights-price-calendar](https://apify.com/steadydata/google-flights-price-calendar): the cheapest day to fly: one row per departure day over a range
- [google-hotels-city](https://apify.com/steadydata/google-hotels-city): the hotels at the destination: ratings, reviews, indicative price
- [google-trends-batch](https://apify.com/steadydata/google-trends-batch): when interest in a destination peaks

### Pricing

Pay per event: one `flight-listed` event per delivered flight option. No charge for
searches that fail, no separate platform-usage surcharge. `maxFlightsPerSearch` is your
hard cost ceiling per search.

**Free Apify plan:** this actor delivers up to 25 rows per run for accounts on the Apify free
plan, and then stops with a message. That limit is set by us, not by Apify. It exists so the
actor keeps paying for itself for the people who do pay. Any paid Apify plan runs it at full
size, billed per delivered row, with failed rows never charged.

**Reviews:** if this actor saves you time, a short review on this page is the one thing that
helps most. Ratings are what other buyers look at first, and we have no other way to ask.

### FAQ

**Times are local?**
Yes, local to each airport, as Google Flights shows them, without a timezone suffix.

**What is `group`?**
Google's own split: `top` for its "Top options", `other` for the rest. `rank` counts
across both, top first.

**Does the price include baggage?**
It is the price Google Flights displays for the itinerary. Fare conditions such as
overhead bin access differ per airline and are not part of this data.

**Can I search by city or with flexible dates?**
No. One airport pair and one exact date (or two for a round trip) per row. For flexible
dates, add one row per date.

**Is personal data collected?**
No. Nothing on these pages is about a person.

**What happens when Google changes something?**
The data block is positional and Google may reshuffle it. The actor is monitored daily
and fixed fast, and while it is broken you are not charged, because only delivered
flights cost anything.

# Changelog

This Actor's version history is a separate document: https://apify.com/steadydata/google-flights/changelog.md

# Actor input Schema

## `searches` (type: `array`):

One search per row: 'FROM TO YYYY-MM-DD' for one-way or 'FROM TO YYYY-MM-DD YYYY-MM-DD' for a round trip, with IATA airport codes, e.g. 'AMS LHR 2026-10-15'. Up to 200 rows; a search without results comes back as a free error record.

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

Cabin class for every search.

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

Number of adult passengers (1 to 9).

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

Three-letter currency code for the prices, e.g. EUR, USD, GBP.

## `maxFlightsPerSearch` (type: `integer`):

Cost ceiling per search, in Google's order (its top options first). One delivered flight option is one charged event.

## Actor input object example

```json
{
  "searches": [
    "AMS LHR 2026-10-15",
    "JFK LAX 2026-11-03 2026-11-10"
  ],
  "seatClass": "economy",
  "adults": 1,
  "currency": "EUR",
  "maxFlightsPerSearch": 50
}
```

# 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 = {
    "searches": [
        "AMS LHR 2026-10-15",
        "JFK LAX 2026-11-03 2026-11-10"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadydata/google-flights").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 = { "searches": [
        "AMS LHR 2026-10-15",
        "JFK LAX 2026-11-03 2026-11-10",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("steadydata/google-flights").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 '{
  "searches": [
    "AMS LHR 2026-10-15",
    "JFK LAX 2026-11-03 2026-11-10"
  ]
}' |
apify call steadydata/google-flights --silent --output-dataset

```

## MCP server setup

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

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/prxWtVfAbLYpUIWV5/builds/DxREl7O6zpDQ8dBnh/openapi.json
