# FlightStats Flight Status Scraper - Delays, Gates, Tails (`parseforge/flightstats-scraper`) Actor

Track live flight status on FlightStats by flight number or route: delay minutes, gate, terminal, aircraft and tail number. Export to CSV, Excel, JSON or XML.

- **URL**: https://apify.com/parseforge/flightstats-scraper.md
- **Developed by:** [ParseForge](https://apify.com/parseforge) (community)
- **Categories:** Travel, Automation, Developer tools
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.72 / 1,000 results

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?

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

![ParseForge Banner](https://github.com/ParseForge/apify-assets/blob/ad35ccc13ddd068b9d6cba33f323962e39aed5b2/banner.jpg?raw=true)

## ✈️ FlightStats Flight Status Scraper

> 🚀 **Export live flight status from FlightStats in seconds.** One flight page or a whole route board, 50 columns per flight, 5 rows in 7.8 seconds and roughly 120 flights a minute on a single run.

FlightStats by Cirium publishes a free flight tracker: type a flight number, get its status, its delay in minutes, the terminal and gate it leaves from, the belt the bags land on, the aircraft type and the tail number. This Actor reads that same public page and turns it into a flat table you can open in Excel.

Give it a flight designator such as `BA112`, an airport pair such as `JFK-LHR`, or a FlightStats URL you already have. A route returns the whole departure board for that day: 23 operating flights on JFK to LHR, 22 on ATL to MCO, measured 2026-09-08. Every row carries both the naive local time at the airport and a real UTC instant, so a mixed-timezone export still sorts correctly.

**Coverage.** The public tracker publishes roughly 3 days back and 2 days forward. Day minus 4 answers "out of date range" and day plus 3 returns an empty board. Older status sits behind Cirium's paid product and is not available here, so this Actor does not pretend to offer a flight history archive.

| Who it is for | What they get |
| --- | --- |
| 🚚 Freight forwarders and ground handlers | Gate, terminal, baggage belt and live delay minutes for every inbound flight |
| 🧳 Travel agencies and OTAs | Status for a customer's booked flight number, including the operating carrier behind a codeshare |
| 📊 Aviation analysts | Departure and arrival boards for a route with aircraft type and tail number on every leg |
| 🤖 Automation builders | A clean JSON feed to drive alerts in Make, Zapier or n8n without touching a paid aviation API |
| 🏢 Corporate travel desks | One table of every flight your travellers are on today, with delay minutes ready to sort |

### 📋 What the FlightStats Flight Status Scraper does

- Reads the public FlightStats flight tracker page and lifts the flight record straight out of the page state, so nothing depends on fragile CSS selectors.
- Accepts three kinds of source at once: flight designators (`BA112`, `AA 100`, `B6 615`), airport pairs (`JFK-LHR`, `LAX to SFO`) and FlightStats URLs.
- Sweeps a route board across four time windows so one route request covers the whole day rather than a six hour slice.
- Drops codeshare duplicates by default: JFK to LHR lists 120 ticketed flight numbers for the same 23 aircraft, and you almost never want all 120.
- Returns scheduled and actual times twice, once as airport local time and once as a UTC instant, plus the IANA time zone of both airports.
- Carries delay minutes at departure and at arrival, terminal, gate, baggage claim, aircraft type, aircraft code and tail number.
- Keeps the codeshare list on the row, so you can see that BA 112 also sells as AA 6925, AS 5250, AY 5512, EI 8812 and IB 3540.
- Filters by status, by minimum delay, and by date inside the published window.
- Rotates its exit IP every 100 requests, because the load balancer in front of the site answers HTTP 403 after roughly 182 requests from one address.
- Rounds robin across every source you give it, so a cap of 50 rows spreads over all your flights and routes instead of being eaten by the first busy board.

### 🎬 Full Demo (🚧 Coming soon)

A short walkthrough video is on the way. Until then the sample records below are real rows from a real run.

### 📊 Output

Every row is one ticketed flight number on one calendar day.

| Field | Type | What it holds |
| --- | --- | --- |
| `flightNumber` | string | Airline code and number as printed on a boarding pass, for example `BA 112` |
| `flightCode` | string | The same designator with no space, for example `BA112` |
| `sourceUrl` | string | The FlightStats page this row was read from |
| `airlineName` | string | Marketing airline name |
| `airlineCode` | string | Two or three character IATA airline code |
| `flightDate` | string | Scheduled departure date at the origin airport, `YYYY-MM-DD` |
| `flightStatus` | string | `Scheduled`, `Departed`, `Arrived`, `Cancelled` or `Diverted` |
| `statusDetail` | string | The site's own wording, for example `On time` or `Delayed by 45m` |
| `originAirportCode` | string | IATA code of the departure airport |
| `originAirportName` | string | Full airport name |
| `originCity` | string | City the departure airport serves |
| `originCountry` | string | Two letter country code |
| `destinationAirportCode` | string | IATA code of the arrival airport |
| `destinationAirportName` | string | Full airport name |
| `destinationCity` | string | City the arrival airport serves |
| `destinationCountry` | string | Two letter country code |
| `scheduledDeparture` | string | Scheduled departure in airport local time, ISO 8601 |
| `scheduledDepartureUtc` | string | The same instant in UTC |
| `actualDeparture` | string | Actual departure once off the gate, estimate before that |
| `actualDepartureUtc` | string | The same instant in UTC |
| `departureTimeType` | string | `Actual` or `Estimated`, so you know which one you are reading |
| `departureDelayMinutes` | integer | Minutes late off the gate, 0 when on time |
| `scheduledArrival` | string | Scheduled arrival in airport local time |
| `scheduledArrivalUtc` | string | The same instant in UTC |
| `actualArrival` | string | Actual arrival once landed, estimate before that |
| `actualArrivalUtc` | string | The same instant in UTC |
| `arrivalTimeType` | string | `Actual` or `Estimated` |
| `arrivalDelayMinutes` | integer | Minutes late on arrival, 0 when on time |
| `flightDuration` | string | Block time as the site prints it, for example `7h 10m` |
| `originTerminal` | string | Departure terminal |
| `originGate` | string | Departure gate |
| `destinationTerminal` | string | Arrival terminal |
| `destinationGate` | string | Arrival gate |
| `baggageClaim` | string | Baggage belt at the arrival airport |
| `aircraftType` | string | Aircraft description, for example `Boeing 777-300ER` |
| `aircraftCode` | string | IATA equipment code, for example `77W` |
| `tailNumber` | string | Registration of the aircraft flying the leg |
| `operatedBy` | string | The flight that actually flies the metal |
| `isCodeshare` | string | `Yes` when this number is sold on someone else's aircraft |
| `diverted` | string | `Yes` or `No` |
| `divertedAirportCode` | string | Where a diverted flight actually went |
| `cancelled` | string | `Yes` or `No` |
| `finalStatus` | string | `On Time` or `Delayed`, set once the flight has landed |
| `flightPhase` | string | `Climbing`, `Cruising`, `Descending` or `Landed` while airborne |
| `originTimeZone` | string | IANA zone of the departure airport |
| `destinationTimeZone` | string | IANA zone of the arrival airport |
| `flightId` | integer | The site's own identifier for this leg on this day |
| `codeshares` | array | Every other airline and number selling the same seat |
| `scrapedAt` | string | ISO timestamp of the read |
| `error` | string | Only on an error row, `null` on a data row |

Three real records from a run:

```json
[
  {
    "flightNumber": "BA 112",
    "flightCode": "BA112",
    "sourceUrl": "https://www.flightstats.com/v2/flight-tracker/BA/112?year=2026&month=9&date=8",
    "airlineName": "British Airways",
    "airlineCode": "BA",
    "flightDate": "2026-09-08",
    "flightStatus": "Scheduled",
    "statusDetail": "On time",
    "originAirportCode": "JFK",
    "originAirportName": "New York John F. Kennedy International Airport",
    "originCity": "New York",
    "originCountry": "US",
    "destinationAirportCode": "LHR",
    "destinationAirportName": "London Heathrow Airport",
    "destinationCity": "London",
    "destinationCountry": "GB",
    "scheduledDeparture": "2026-09-08T18:30:00",
    "scheduledDepartureUtc": "2026-09-08T22:30:00.000Z",
    "actualDeparture": "Not Disclosed",
    "actualDepartureUtc": "Not Disclosed",
    "departureTimeType": "Estimated",
    "departureDelayMinutes": 0,
    "scheduledArrival": "2026-09-09T06:40:00",
    "scheduledArrivalUtc": "2026-09-09T05:40:00.000Z",
    "actualArrival": "Not Disclosed",
    "actualArrivalUtc": "Not Disclosed",
    "arrivalTimeType": "Estimated",
    "arrivalDelayMinutes": 0,
    "flightDuration": "7h 10m",
    "originTerminal": "8",
    "originGate": "Not Disclosed",
    "destinationTerminal": "5",
    "destinationGate": "Not Disclosed",
    "baggageClaim": "Not Disclosed",
    "aircraftType": "Boeing 777-300ER",
    "aircraftCode": "77W",
    "tailNumber": "G-STBK",
    "operatedBy": "British Airways 112",
    "isCodeshare": "No",
    "diverted": "No",
    "divertedAirportCode": "N/A",
    "cancelled": "No",
    "finalStatus": "N/A",
    "flightPhase": "N/A",
    "originTimeZone": "America/New_York",
    "destinationTimeZone": "Europe/London",
    "flightId": 1407025436,
    "codeshares": [
      { "airlineName": "American Airlines", "airlineCode": "AA", "flightNumber": "6925" },
      { "airlineName": "Alaska Airlines", "airlineCode": "AS", "flightNumber": "5250" },
      { "airlineName": "Finnair", "airlineCode": "AY", "flightNumber": "5512" },
      { "airlineName": "Aer Lingus", "airlineCode": "EI", "flightNumber": "8812" },
      { "airlineName": "Iberia", "airlineCode": "IB", "flightNumber": "3540" }
    ],
    "scrapedAt": "2026-09-08T15:39:28.912Z",
    "error": null
  },
  {
    "flightNumber": "DL 1562",
    "flightCode": "DL1562",
    "sourceUrl": "https://www.flightstats.com/v2/flight-tracker/DL/1562?year=2026&month=9&date=8&flightId=1406836587",
    "airlineName": "Delta Air Lines",
    "airlineCode": "DL",
    "flightDate": "2026-09-07",
    "flightStatus": "Arrived",
    "statusDetail": "On time",
    "originAirportCode": "ATL",
    "originAirportName": "Atlanta Hartsfield-Jackson International Airport",
    "originCity": "Atlanta",
    "originCountry": "US",
    "destinationAirportCode": "MCO",
    "destinationAirportName": "Orlando International Airport",
    "destinationCity": "Orlando",
    "destinationCountry": "US",
    "scheduledDeparture": "2026-09-07T23:59:00",
    "scheduledDepartureUtc": "2026-09-08T03:59:00.000Z",
    "actualDeparture": "2026-09-07T23:43:00",
    "actualDepartureUtc": "2026-09-08T03:43:00.000Z",
    "departureTimeType": "Actual",
    "departureDelayMinutes": 0,
    "scheduledArrival": "2026-09-08T01:33:00",
    "scheduledArrivalUtc": "2026-09-08T05:33:00.000Z",
    "actualArrival": "2026-09-08T01:00:00",
    "actualArrivalUtc": "2026-09-08T05:00:00.000Z",
    "arrivalTimeType": "Actual",
    "arrivalDelayMinutes": 0,
    "flightDuration": "1h 17m",
    "originTerminal": "S",
    "originGate": "T8",
    "destinationTerminal": "B",
    "destinationGate": "86",
    "baggageClaim": "31",
    "aircraftType": "Airbus A321 (sharklets)",
    "aircraftCode": "32B",
    "tailNumber": "N370DN",
    "operatedBy": "Delta Air Lines 1562",
    "isCodeshare": "No",
    "diverted": "No",
    "divertedAirportCode": "N/A",
    "cancelled": "No",
    "finalStatus": "On Time",
    "flightPhase": "Landed",
    "originTimeZone": "America/New_York",
    "destinationTimeZone": "America/New_York",
    "flightId": 1406836587,
    "codeshares": [
      { "airlineName": "Aeromexico", "airlineCode": "AM", "flightNumber": "3604" },
      { "airlineName": "Korean Air", "airlineCode": "KE", "flightNumber": "3127" },
      { "airlineName": "LATAM Airlines", "airlineCode": "LA", "flightNumber": "6514" },
      { "airlineName": "SAS", "airlineCode": "SK", "flightNumber": "3118" },
      { "airlineName": "Virgin Atlantic", "airlineCode": "VS", "flightNumber": "5159" }
    ],
    "scrapedAt": "2026-09-08T15:39:29.169Z",
    "error": null
  },
  {
    "flightNumber": "BA 178",
    "flightCode": "BA178",
    "sourceUrl": "https://www.flightstats.com/v2/flight-tracker/BA/178?year=2026&month=9&date=8&flightId=1407025585",
    "airlineName": "British Airways",
    "airlineCode": "BA",
    "flightDate": "2026-09-08",
    "flightStatus": "Departed",
    "statusDetail": "On time",
    "originAirportCode": "JFK",
    "originAirportName": "New York John F. Kennedy International Airport",
    "originCity": "New York",
    "originCountry": "US",
    "destinationAirportCode": "LHR",
    "destinationAirportName": "London Heathrow Airport",
    "destinationCity": "London",
    "destinationCountry": "GB",
    "scheduledDeparture": "2026-09-08T07:50:00",
    "scheduledDepartureUtc": "2026-09-08T11:50:00.000Z",
    "actualDeparture": "2026-09-08T07:44:00",
    "actualDepartureUtc": "2026-09-08T11:44:00.000Z",
    "departureTimeType": "Actual",
    "departureDelayMinutes": 0,
    "scheduledArrival": "2026-09-08T19:45:00",
    "scheduledArrivalUtc": "2026-09-08T18:45:00.000Z",
    "actualArrival": "2026-09-08T19:21:00",
    "actualArrivalUtc": "2026-09-08T18:21:00.000Z",
    "arrivalTimeType": "Estimated",
    "arrivalDelayMinutes": 0,
    "flightDuration": "6h 55m",
    "originTerminal": "8",
    "originGate": "Not Disclosed",
    "destinationTerminal": "5",
    "destinationGate": "Not Disclosed",
    "baggageClaim": "Not Disclosed",
    "aircraftType": "Boeing 777-200 / 200ER",
    "aircraftCode": "772",
    "tailNumber": "G-VIID",
    "operatedBy": "British Airways 178",
    "isCodeshare": "No",
    "diverted": "No",
    "divertedAirportCode": "N/A",
    "cancelled": "No",
    "finalStatus": "N/A",
    "flightPhase": "Cruising",
    "originTimeZone": "America/New_York",
    "destinationTimeZone": "Europe/London",
    "flightId": 1407025585,
    "codeshares": [
      { "airlineName": "American Airlines", "airlineCode": "AA", "flightNumber": "6939" },
      { "airlineName": "Alaska Airlines", "airlineCode": "AS", "flightNumber": "5262" },
      { "airlineName": "Finnair", "airlineCode": "AY", "flightNumber": "5478" },
      { "airlineName": "Aer Lingus", "airlineCode": "EI", "flightNumber": "8878" },
      { "airlineName": "Iberia", "airlineCode": "IB", "flightNumber": "3564" }
    ],
    "scrapedAt": "2026-09-08T15:39:29.900Z",
    "error": null
  }
]
```

`Not Disclosed` means the airport or airline did not publish that value; Heathrow, for instance, publishes terminals but almost never arrival gates. `N/A` means the field does not apply yet, such as a final on-time verdict on a flight that has not landed.

### ✨ Why choose this Actor

- **Reads the page state, not the pixels.** The flight record comes out of the data the page ships with itself, so a redesign of the layout does not silently empty your rows.
- **Both clock faces.** Local airport time and a real UTC instant on every timestamp, plus the IANA zone, so a spreadsheet of flights across five countries sorts correctly.
- **Codeshares handled properly.** One flag tells you whether a number is sold on someone else's metal, and the whole codeshare family stays on the row.
- **A route is one input.** You do not need to know which flight numbers fly JFK to LHR; ask for the pair and get the board.
- **Honest about the window.** 3 days back, 2 days forward. No promise of an archive that the free site does not have.
- **Survives the rate rule.** The exit IP rotates before the site's 403 threshold instead of after it.
- **No account, no key.** Everything it reads is served to a logged-out visitor.

### 📈 How it compares to alternatives

| Approach | Flight number lookup | Whole route board | Gate, terminal, belt | Tail number | Historical archive | Account needed |
| --- | --- | --- | --- | --- | --- | --- |
| **This Actor** | ✅ | ✅ 4 window sweep | ✅ | ✅ | ❌ 3 days back only | ❌ |
| Cirium's own paid API | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ paid contract |
| Copying the site by hand | ✅ | 🐢 one page at a time | ✅ | ✅ | ❌ | ❌ |
| ADS-B trackers (OpenSky, ADSB.lol) | 🤏 by registration | ❌ | ❌ | ✅ | 🤏 limited | ❌ |
| Airline websites one by one | ✅ | ❌ | ✅ | 🤏 sometimes | ❌ | 🤏 sometimes |
| A generic browser scraper | ✅ | 🤏 fragile selectors | 🤏 | 🤏 | ❌ | ❌ |

### 🚀 How to use

1. **Create a free Apify account.** [Sign up here](https://console.apify.com/sign-up?fpr=vmoqkp) and you start with $5 of free platform credit, enough to try this Actor properly.
2. **Open the Actor** and paste what you want to track: a flight number such as `BA112`, an airport pair such as `JFK-LHR`, or a FlightStats URL.
3. **Pick a date** inside the published window, or leave it empty for today.
4. **Set Max Items** to the number of flights you want back.
5. **Click Start**, wait a few seconds, then download CSV, Excel, JSON or XML from the Storage tab.

### 💼 Business use cases

#### 🚚 Ground handling and cargo recovery

Feed tomorrow's inbound flight numbers in every morning and get the terminal, gate and belt for each one, with the delay in minutes attached. Crews get rostered against reality instead of against the published schedule.

#### 🧳 Proactive customer service for travel sellers

Run the booked flight numbers of every traveller departing today, filter to a minimum delay of 15 minutes, and you have the exact list of customers to email before they call you.

#### 📊 Route and fleet analysis

Pull a route board for a few days and you have every operator on the pair, the aircraft type each one uses and the tail numbers in rotation, which is the raw material for a capacity or competitor study.

#### 🏢 Duty of care for corporate travel

Cross the day's route boards with your traveller manifest and you know instantly which of your people are on a flight that is airborne, delayed, cancelled or diverted.

### 🔌 Automating FlightStats Flight Status Scraper

Schedule it in Apify to run every hour on the flight numbers you care about and pipe the dataset into Slack, a Google Sheet or your own webhook. Because the output is flat, `arrivalDelayMinutes` alone is enough to drive an alert rule, and `flightStatus` plus `flightPhase` tells you whether an aircraft is still climbing, cruising, descending or already on the ground. Apify's API returns the dataset as JSON, CSV or Excel from a single URL, so any tool that can read an HTTP endpoint can consume it.

### 🌟 Beyond business use cases

Track the family flight home and get a text when it pushes back. Follow a specific tail number across the week to see which routes it flies. Build a small board for the airport you live near. Settle a bet about whether a route is really always late by pulling three days of arrival delay minutes and taking the average. Teach a class about time zones with a table where the same flight has two departure clocks.

### 🤖 Ask an AI assistant about this scraper

Paste this into ChatGPT, Claude or any assistant to get help building on top of it:

```
I am using the ParseForge FlightStats Flight Status Scraper on Apify
(https://apify.com/parseforge). It returns one row per ticketed flight number
per day with these fields: flightNumber, flightCode, sourceUrl, airlineName,
airlineCode, flightDate, flightStatus, statusDetail, originAirportCode,
originAirportName, originCity, originCountry, destinationAirportCode,
destinationAirportName, destinationCity, destinationCountry,
scheduledDeparture, scheduledDepartureUtc, actualDeparture, actualDepartureUtc,
departureTimeType, departureDelayMinutes, scheduledArrival,
scheduledArrivalUtc, actualArrival, actualArrivalUtc, arrivalTimeType,
arrivalDelayMinutes, flightDuration, originTerminal, originGate,
destinationTerminal, destinationGate, baggageClaim, aircraftType, aircraftCode,
tailNumber, operatedBy, isCodeshare, diverted, divertedAirportCode, cancelled,
finalStatus, flightPhase, originTimeZone, destinationTimeZone, flightId,
codeshares, scrapedAt, error.
Local timestamps have no offset and belong to the airport time zone in the
matching time zone column; the Utc columns are real instants. Coverage is about
3 days back and 2 days forward. Help me build ...
```

### ❓ Frequently Asked Questions

#### ❓ How far back can I go?

About 3 days. Measured 2026-09-08, the tracker reports "out of date range" at 4 days back, and the route board returns nothing 3 days ahead. Anything older is part of Cirium's paid historical product and this Actor will not invent it.

#### ❓ Do I need a FlightStats or Cirium account?

No. Everything this Actor reads is what a logged-out visitor sees. The departures and arrivals board and the historical flight status feature both redirect to a login, so they are deliberately out of scope.

#### ❓ What is the difference between asking for a flight number and asking for a route?

A flight number returns exactly one row for that day. A route returns the whole departure board for the airport pair: 23 operating flights on JFK to LHR and 22 on ATL to MCO on 2026-09-08.

#### ❓ Why did I get 120 rows from one route instead of 23?

Because you turned codeshares on. FlightStats lists every ticketed number, so one aircraft can appear six times under six different airlines. The default keeps only the carrier that actually flies it.

#### ❓ What is `operatedBy` for?

It names the flight that actually flies the aircraft. On an operating flight it repeats that flight's own designator; on a codeshare it points at the metal, for example `Virgin Atlantic 4` on a row sold as Air France 6753.

#### ❓ Why is a row's `flightDate` a day earlier than the date I asked for?

A route board window can reach across midnight, so a board pulled for the 8th can include a flight that departs at 23:59 on the 7th. The `flightDate` column always reflects the real scheduled departure date at the origin airport.

#### ❓ Why is the arrival gate `Not Disclosed`?

Not every airport publishes one. Heathrow gives terminals and baggage belts but almost never an arrival gate, while Atlanta and Orlando publish gate, terminal and belt. `Not Disclosed` means the source withheld it, never that the Actor failed to read it.

#### ❓ Are the times local or UTC?

Both. Every timestamp comes twice: a naive local time at the airport and a matching UTC instant in the column ending in `Utc`. The `originTimeZone` and `destinationTimeZone` columns give the IANA zone so you can convert either way.

#### ❓ What does `departureTimeType` mean?

It tells you whether the "actual" column is a real observed time or still an estimate. Before pushback the site shows an estimate, after pushback it shows the actual.

#### ❓ How fast is it and what is the ceiling?

A five row run over one flight and two routes took 7.8 seconds and 13 requests. One request returns one flight, so throughput sits near 120 flights a minute. The hard ceiling is the size of the boards you ask for, not a page limit.

#### ❓ Why do I sometimes get fewer rows than Max Items?

Because a flight number with no published status for that date returns nothing, filters drop rows, and duplicates are removed. Widen the date, drop the status filter, or add another route.

#### ❓ Does it deduplicate?

Yes, on flight code plus date plus origin plus destination, so the same flight arriving through both a URL and a route board is written once.

#### ❓ Do I need a proxy?

It is on by default and you should leave it on. The load balancer in front of the site returns a bare HTTP 403 after roughly 182 requests from a single address, so the Actor rotates its exit IP every 100 requests.

#### ❓ Can I get the live position of the aircraft?

No. The tracker does carry position points once a flight is airborne, but they are empty before departure and disappear again after landing, so a column for them would be blank on most rows. Use `flightPhase` for a reliable in-flight signal.

#### ❓ Is this the Cirium API?

No, and it is not a substitute for it. This reads the free public web tracker. If you need contracted coverage, guaranteed history or an SLA, buy the Cirium product directly.

### 🔌 Integrate with any app

Every run writes an Apify dataset you can pull as JSON, CSV, Excel or XML from one API URL, so Make, Zapier, n8n, Google Sheets, Power BI, Airtable and your own code can all read it without any extra glue. Webhooks fire when a run finishes, which is enough to push a delay alert straight into Slack or an on-call queue.

### 🔗 Recommended Actors

- **FlightAware Public Tracker Scraper** for a second opinion on a flight from a different public source.
- **Flightradar24 Live Flights Scraper** when you want live positions rather than schedule and gate data.
- **OpenSky Network Live Flight Scraper** for raw ADS-B state vectors by registration.
- **ADSB.lol Live Flights Scraper** for an open community feed of airborne aircraft.

💡 **Pro Tip:** Browse the whole ParseForge collection at <https://apify.com/parseforge> for more travel and aviation data Actors that plug into the same workflow.

**🆘 Need Help?** [Open our contact form](https://tally.so/r/BzdKgA)

*Not affiliated with, endorsed by or connected to FlightStats or Cirium. This Actor collects only publicly available data from pages that FlightStats serves to any logged-out visitor, and it does not access the Cirium API or any account-protected feature.*

# Actor input Schema

## `startUrls` (type: `array`):

FlightStats flight tracker pages to read. A flight page looks like https://www.flightstats.com/v2/flight-tracker/BA/112 and a route board like https://www.flightstats.com/v2/flight-tracker/route/JFK/LHR. A year, month and date already in the URL wins over the Flight date field below. Leave empty and use Flight numbers or routes instead.

## `searchTerms` (type: `array`):

One entry per flight or per route. A flight designator such as BA112, AA 100 or B6 615 returns that single flight. An airport pair such as JFK-LHR or LAX to SFO returns the whole departure board for that route on the chosen date. Airport codes are three letter IATA codes.

## `maxItems` (type: `integer`):

Free users: Limited to 10 items (preview). Paid users: Optional, max 1,000,000. Leave empty on a paid plan for 100 rows.

## `flightDate` (type: `string`):

Departure date at the origin airport, as YYYY-MM-DD. Leave empty for today. Measured 2026-09-08: day minus 4 answers isOutOfDateRange and day plus 3 returns an empty board, so useful values run from three days ago to two days ahead.

## `codeshareHandling` (type: `string`):

A route board lists every ticketed flight number, so one aircraft can appear five or six times under different airlines. Operating flights only keeps the carrier that actually flies the aircraft. Measured 2026-09-08 on JFK to LHR: 120 ticketed rows, 23 operating flights. Ignored when the source is a single flight number.

## `flightStatuses` (type: `array`):

Leave empty to keep every flight. Scheduled, Departed and Arrived are the three states FlightStats publishes for a normal flight; Cancelled and Diverted come from the cancellation and diversion flags on the same record.

## `minDelayMinutes` (type: `integer`):

Keep only flights delayed by at least this many minutes at departure or at arrival. Leave empty to keep on-time flights too. Set 15 for the usual industry definition of a delayed flight.

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

On by default. Measured 2026-09-08: 182 requests from one exit address in 62 seconds earned a bare HTTP 403, so the Actor rotates its exit IP every 100 requests and again on any 403. Turn it off only for very small runs.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.flightstats.com/v2/flight-tracker/BA/112"
    }
  ],
  "searchTerms": [
    "JFK-LHR",
    "ATL-MCO"
  ],
  "maxItems": 10,
  "codeshareHandling": "operating",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

Key fields: flight, airline, route, status, scheduled and actual times, delay minutes, terminal, gate, aircraft

## `fullData` (type: `string`):

Complete dataset with all 50 fields, including the UTC timestamps, the time zone names and the codeshare array

# 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 = {
    "startUrls": [
        {
            "url": "https://www.flightstats.com/v2/flight-tracker/BA/112"
        }
    ],
    "searchTerms": [
        "JFK-LHR",
        "ATL-MCO"
    ],
    "maxItems": 10,
    "codeshareHandling": "operating",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("parseforge/flightstats-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 = {
    "startUrls": [{ "url": "https://www.flightstats.com/v2/flight-tracker/BA/112" }],
    "searchTerms": [
        "JFK-LHR",
        "ATL-MCO",
    ],
    "maxItems": 10,
    "codeshareHandling": "operating",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("parseforge/flightstats-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 '{
  "startUrls": [
    {
      "url": "https://www.flightstats.com/v2/flight-tracker/BA/112"
    }
  ],
  "searchTerms": [
    "JFK-LHR",
    "ATL-MCO"
  ],
  "maxItems": 10,
  "codeshareHandling": "operating",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call parseforge/flightstats-scraper --silent --output-dataset

```

## MCP server setup

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