Skip to content

Overview¤

Name Low-level API Service and Cache Location
Flight List
JSON
flight_list
flight_list_df
FlightListService

Cache Location:
flight_list/
└── reg/
└── {reg.upper()}.parquet
└── flight_list/
└── {iata_flight_num.upper()}.parquet
Playback
JSON
playback
playback_df
PlaybackService

Cache Location:
playback/
└── {fr24_hex_id.upper()}.parquet
Live Feed
gRPC
live_feed
live_feed_df
LiveFeedService

Cache Location:
feed/
└── {timestamp_s}.parquet
Live Feed Playback
gRPC
live_feed_playback
live_feed_df
LiveFeedPlaybackService

Cache Location:
feed/
└── {timestamp_s}.parquet
Airport List
JSON
airport_list AirportListService
Airport Search
JSON
find FindService
Nearest Flights
gRPC
nearest_flights NearestFlightsService

Cache Location:
nearest_flights/
└── {lon_x1e6}_{lat_x1e6}_{timestamp_s}.parquet
Live Flight Status
gRPC
live_flights_status LiveFlightsStatusService

Cache Location:
live_flights_status/
└── {timestamp_s}.parquet
Search Index
gRPC
search_index -
Follow Flight
gRPC
follow_flight_stream FollowFlightService
Top Flights
gRPC
top_flights TopFlightsService

Cache Location:
top_flights/
└── {timestamp_s}.parquet
Live Trail
gRPC
live_trail -
Historic Trail
gRPC
historic_trail -
Flight Details
gRPC
flight_details FlightDetailsService

Cache Location:
flight_details/
└── {flight_id}_{timestamp_s}.parquet
Playback Flight
gRPC
playback_flight PlaybackFlightService

Cache Location:
playback_flight/
└── {flight_id}_{timestamp_s}.parquet

You can find even more usage examples under tests/.

Skip to Low Level API

FR24 services¤

Flight list¤

Single page¤

from fr24 import FR24, FR24Cache


async def my_list() -> None:
    async with FR24() as fr24:
        result = await fr24.flight_list.fetch(reg="B-LRA", filter_by="historic")
        print(result.to_polars())
        result.write_table(FR24Cache.default())


await my_list()
shape: (10, 15)
┌────────────┬────────┬──────────┬─────────┬───┬────────────┬────────────┬────────────┬────────────┐
│ flight_id  ┆ number ┆ callsign ┆ icao24  ┆ … ┆ ATOD       ┆ STOA       ┆ ETOA       ┆ ATOA       │
│ ---        ┆ ---    ┆ ---      ┆ ---     ┆   ┆ ---        ┆ ---        ┆ ---        ┆ ---        │
│ u64        ┆ str    ┆ str      ┆ u32     ┆   ┆ datetime[m ┆ datetime[m ┆ datetime[m ┆ datetime[m │
│            ┆        ┆          ┆         ┆   ┆ s, UTC]    ┆ s, UTC]    ┆ s, UTC]    ┆ s, UTC]    │
╞════════════╪════════╪══════════╪═════════╪═══╪════════════╪════════════╪════════════╪════════════╡
│ 1011667820 ┆ CX170  ┆ CPA170   ┆ 7867035 ┆ … ┆ 2025-09-20 ┆ 2025-09-20 ┆ null       ┆ 2025-09-21 │
│            ┆        ┆          ┆         ┆   ┆ 16:46:55   ┆ 23:55:00   ┆            ┆ 00:21:13   │
│            ┆        ┆          ┆         ┆   ┆ UTC        ┆ UTC        ┆            ┆ UTC        │
│ 1011554520 ┆ CX171  ┆ CPA171   ┆ 7867035 ┆ … ┆ 2025-09-20 ┆ 2025-09-20 ┆ null       ┆ 2025-09-20 │
│            ┆        ┆          ┆         ┆   ┆ 07:20:40   ┆ 14:40:00   ┆            ┆ 14:21:27   │
│            ┆        ┆          ┆         ┆   ┆ UTC        ┆ UTC        ┆            ┆ UTC        │
│ 1011435329 ┆ CX648  ┆ CPA648   ┆ 7867035 ┆ … ┆ 2025-09-19 ┆ 2025-09-20 ┆ null       ┆ 2025-09-20 │
│            ┆        ┆          ┆         ┆   ┆ 18:23:36   ┆ 02:55:00   ┆            ┆ 02:52:15   │
│            ┆        ┆          ┆         ┆   ┆ UTC        ┆ UTC        ┆            ┆ UTC        │
│ 1011284495 ┆ CX647  ┆ CPA647   ┆ 7867035 ┆ … ┆ 2025-09-19 ┆ 2025-09-19 ┆ null       ┆ 2025-09-19 │
│            ┆        ┆          ┆         ┆   ┆ 07:20:48   ┆ 16:10:00   ┆            ┆ 15:42:45   │
│            ┆        ┆          ┆         ┆   ┆ UTC        ┆ UTC        ┆            ┆ UTC        │
│ 1011171753 ┆ CX648  ┆ CPA648   ┆ 7867035 ┆ … ┆ 2025-09-18 ┆ 2025-09-19 ┆ null       ┆ 2025-09-19 │
│            ┆        ┆          ┆         ┆   ┆ 19:38:57   ┆ 04:05:00   ┆            ┆ 03:59:35   │
│            ┆        ┆          ┆         ┆   ┆ UTC        ┆ UTC        ┆            ┆ UTC        │
│ 1011026581 ┆ CX647  ┆ CPA647   ┆ 7867035 ┆ … ┆ 2025-09-18 ┆ 2025-09-18 ┆ null       ┆ 2025-09-18 │
│            ┆        ┆          ┆         ┆   ┆ 09:07:57   ┆ 17:25:00   ┆            ┆ 17:44:23   │
│            ┆        ┆          ┆         ┆   ┆ UTC        ┆ UTC        ┆            ┆ UTC        │
│ 1010931855 ┆ CX110  ┆ CPA110   ┆ 7867035 ┆ … ┆ 2025-09-17 ┆ 2025-09-18 ┆ null       ┆ 2025-09-18 │
│            ┆        ┆          ┆         ┆   ┆ 22:11:58   ┆ 07:15:00   ┆            ┆ 06:51:33   │
│            ┆        ┆          ┆         ┆   ┆ UTC        ┆ UTC        ┆            ┆ UTC        │
│ 1010788305 ┆ CX111  ┆ CPA111   ┆ 7867035 ┆ … ┆ 2025-09-17 ┆ 2025-09-17 ┆ null       ┆ 2025-09-17 │
│            ┆        ┆          ┆         ┆   ┆ 11:44:15   ┆ 20:10:00   ┆            ┆ 20:34:57   │
│            ┆        ┆          ┆         ┆   ┆ UTC        ┆ UTC        ┆            ┆ UTC        │
│ 1010538830 ┆ CX300  ┆ CPA300   ┆ 7867035 ┆ … ┆ 2025-09-16 ┆ 2025-09-16 ┆ null       ┆ 2025-09-16 │
│            ┆        ┆          ┆         ┆   ┆ 12:53:57   ┆ 22:50:00   ┆            ┆ 23:01:10   │
│            ┆        ┆          ┆         ┆   ┆ UTC        ┆ UTC        ┆            ┆ UTC        │
│ 1010340276 ┆ CX301  ┆ CPA301   ┆ 7867035 ┆ … ┆ 2025-09-15 ┆ 2025-09-16 ┆ null       ┆ 2025-09-16 │
│            ┆        ┆          ┆         ┆   ┆ 17:30:58   ┆ 05:55:00   ┆            ┆ 06:24:16   │
│            ┆        ┆          ┆         ┆   ┆ UTC        ┆ UTC        ┆            ┆ UTC        │
└────────────┴────────┴──────────┴─────────┴───┴────────────┴────────────┴────────────┴────────────┘

Paginate all pages¤

Queries for next page as long as user doesn't enter x, or if there are no pages left. In each iteration, rows are upserted and saved to the cache.

Note that pagination cannot be run in parallel: fetching page N requires information from page N-1.

from fr24 import FR24, FR24Cache

cache = FR24Cache.default()


async def my_full_list() -> None:
    async with FR24() as fr24:
        results = fr24.flight_list.new_result_collection()  # (1)!
        async for result in fr24.flight_list.fetch_all(reg="B-LRA"):
            results.append(result)  # (2)!
            if input() == "x":
                break
            results.write_table(cache)
        print(results.to_polars())  # (3)!


await my_full_list()
  1. Create a new result collections, a list under the hood.
  2. Appends the current flight list to the collection. Note that it does not remove duplicates.
  3. Merges the collections into a single table. Removes duplicates (if any).
shape: (22, 15)
┌───────────┬────────┬──────────┬─────────┬───┬─────────────┬────────────┬────────────┬────────────┐
│ flight_id ┆ number ┆ callsign ┆ icao24  ┆ … ┆ ATOD        ┆ STOA       ┆ ETOA       ┆ ATOA       │
│ ---       ┆ ---    ┆ ---      ┆ ---     ┆   ┆ ---         ┆ ---        ┆ ---        ┆ ---        │
│ u64       ┆ str    ┆ str      ┆ u32     ┆   ┆ datetime[ms ┆ datetime[m ┆ datetime[m ┆ datetime[m │
│           ┆        ┆          ┆         ┆   ┆ , UTC]      ┆ s, UTC]    ┆ s, UTC]    ┆ s, UTC]    │
╞═══════════╪════════╪══════════╪═════════╪═══╪═════════════╪════════════╪════════════╪════════════╡
│ 952283415 ┆ CX382  ┆ CPA382   ┆ 7867035 ┆ … ┆ 2025-01-17  ┆ 2025-01-17 ┆ null       ┆ 2025-01-17 │
│           ┆        ┆          ┆         ┆   ┆ 11:14:41    ┆ 22:25:00   ┆            ┆ 22:15:37   │
│           ┆        ┆          ┆         ┆   ┆ UTC         ┆ UTC        ┆            ┆ UTC        │
│ 952264050 ┆ CX383  ┆ CPA383   ┆ 7867035 ┆ … ┆ null        ┆ null       ┆ null       ┆ null       │
│ 952125211 ┆ CX383  ┆ CPA383   ┆ 7867035 ┆ … ┆ 2025-01-16  ┆ 2025-01-17 ┆ null       ┆ 2025-01-17 │
│           ┆        ┆          ┆         ┆   ┆ 17:57:05    ┆ 06:30:00   ┆            ┆ 06:53:54   │
│           ┆        ┆          ┆         ┆   ┆ UTC         ┆ UTC        ┆            ┆ UTC        │
│ 951961210 ┆ CX710  ┆ CPA710   ┆ 7867035 ┆ … ┆ 2025-01-16  ┆ 2025-01-16 ┆ null       ┆ 2025-01-16 │
│           ┆        ┆          ┆         ┆   ┆ 00:15:55    ┆ 03:55:00   ┆            ┆ 03:38:15   │
│           ┆        ┆          ┆         ┆   ┆ UTC         ┆ UTC        ┆            ┆ UTC        │
│ 951777224 ┆ CX735  ┆ CPA735   ┆ 7867035 ┆ … ┆ 2025-01-15  ┆ 2025-01-15 ┆ null       ┆ 2025-01-15 │
│           ┆        ┆          ┆         ┆   ┆ 06:44:49    ┆ 10:25:00   ┆            ┆ 10:31:32   │
│           ┆        ┆          ┆         ┆   ┆ UTC         ┆ UTC        ┆            ┆ UTC        │
│ …         ┆ …      ┆ …        ┆ …       ┆ … ┆ …           ┆ …          ┆ …          ┆ …          │
│ 951229708 ┆ CX624  ┆ CPA624   ┆ 7867035 ┆ … ┆ 2025-01-12  ┆ 2025-01-13 ┆ null       ┆ 2025-01-13 │
│           ┆        ┆          ┆         ┆   ┆ 20:15:14    ┆ 01:30:00   ┆            ┆ 00:59:37   │
│           ┆        ┆          ┆         ┆   ┆ UTC         ┆ UTC        ┆            ┆ UTC        │
│ 951146643 ┆ CX623  ┆ CPA623   ┆ 7867035 ┆ … ┆ 2025-01-12  ┆ 2025-01-12 ┆ null       ┆ 2025-01-12 │
│           ┆        ┆          ┆         ┆   ┆ 12:57:58    ┆ 18:55:00   ┆            ┆ 18:23:19   │
│           ┆        ┆          ┆         ┆   ┆ UTC         ┆ UTC        ┆            ┆ UTC        │
│ 951012767 ┆ CX714  ┆ CPA714   ┆ 7867035 ┆ … ┆ 2025-01-11  ┆ 2025-01-11 ┆ null       ┆ 2025-01-11 │
│           ┆        ┆          ┆         ┆   ┆ 18:55:20    ┆ 21:10:00   ┆            ┆ 22:05:36   │
│           ┆        ┆          ┆         ┆   ┆ UTC         ┆ UTC        ┆            ┆ UTC        │
│ 950956719 ┆ CX715  ┆ CPA715   ┆ 7867035 ┆ … ┆ 2025-01-11  ┆ 2025-01-11 ┆ null       ┆ 2025-01-11 │
│           ┆        ┆          ┆         ┆   ┆ 13:03:44    ┆ 16:25:00   ┆            ┆ 16:29:15   │
│           ┆        ┆          ┆         ┆   ┆ UTC         ┆ UTC        ┆            ┆ UTC        │
│ 950873921 ┆ CX162  ┆ CPA162   ┆ 7867035 ┆ … ┆ 2025-01-11  ┆ 2025-01-11 ┆ null       ┆ 2025-01-11 │
│           ┆        ┆          ┆         ┆   ┆ 01:09:49    ┆ 09:30:00   ┆            ┆ 09:41:27   │
│           ┆        ┆          ┆         ┆   ┆ UTC         ┆ UTC        ┆            ┆ UTC        │
└───────────┴────────┴──────────┴─────────┴───┴─────────────┴────────────┴────────────┴────────────┘

Playback¤

Miracle on the Hudson¤

Downloads the flight trajectory for UA1549

import rich
from fr24 import FR24, FR24Cache


async def my_playback() -> None:
    async with FR24() as fr24:
        result = await fr24.playback.fetch(0x2FB3041)  # (1)!
        df = result.to_polars()
        print(df)
        rich.print(result.metadata())
        result.write_table(FR24Cache.default())


await my_playback()
  1. From https://www.flightradar24.com/data/pinned/ua1549-2fb3041#2fb3041.
shape: (363, 9)
┌────────────┬───────────┬────────────┬──────────┬───┬───────────────┬───────┬────────┬────────────┐
│ timestamp  ┆ latitude  ┆ longitude  ┆ altitude ┆ … ┆ vertical_spee ┆ track ┆ squawk ┆ ems        │
│ ---        ┆ ---       ┆ ---        ┆ ---      ┆   ┆ d             ┆ ---   ┆ ---    ┆ ---        │
│ u32        ┆ f32       ┆ f32        ┆ i32      ┆   ┆ ---           ┆ i16   ┆ u16    ┆ struct[18] │
│            ┆           ┆            ┆          ┆   ┆ i16           ┆       ┆        ┆            │
╞════════════╪═══════════╪════════════╪══════════╪═══╪═══════════════╪═══════╪════════╪════════════╡
│ 1232049993 ┆ 40.770302 ┆ -73.862801 ┆ 0        ┆ … ┆ null          ┆ 59    ┆ 0      ┆ null       │
│ 1232049997 ┆ 40.770302 ┆ -73.862503 ┆ 0        ┆ … ┆ null          ┆ 65    ┆ 0      ┆ null       │
│ 1232050001 ┆ 40.770302 ┆ -73.862198 ┆ 0        ┆ … ┆ null          ┆ 71    ┆ 0      ┆ null       │
│ 1232050005 ┆ 40.770302 ┆ -73.862198 ┆ 0        ┆ … ┆ null          ┆ 76    ┆ 0      ┆ null       │
│ 1232050009 ┆ 40.770302 ┆ -73.862198 ┆ 0        ┆ … ┆ null          ┆ 82    ┆ 0      ┆ null       │
│ …          ┆ …         ┆ …          ┆ …        ┆ … ┆ …             ┆ …     ┆ …      ┆ …          │
│ 1232051425 ┆ 40.781399 ┆ -73.998199 ┆ 326      ┆ … ┆ null          ┆ 223   ┆ 0      ┆ null       │
│ 1232051429 ┆ 40.779202 ┆ -73.999603 ┆ 274      ┆ … ┆ null          ┆ 226   ┆ 0      ┆ null       │
│ 1232051433 ┆ 40.777199 ┆ -74.001297 ┆ 187      ┆ … ┆ null          ┆ 222   ┆ 0      ┆ null       │
│ 1232051437 ┆ 40.775002 ┆ -74.002899 ┆ 106      ┆ … ┆ null          ┆ 223   ┆ 0      ┆ null       │
│ 1232051441 ┆ 40.773102 ┆ -74.004303 ┆ 42       ┆ … ┆ null          ┆ 223   ┆ 0      ┆ null       │
└────────────┴───────────┴────────────┴──────────┴───┴───────────────┴───────┴────────┴────────────┘
{
    "flight_id": 50016321,
    "callsign": "AWE1549",
    "flight_number": "UA1549",
    "status_type": "departure",
    "status_text": None,
    "status_diverted": None,
    "status_time": None,
    "model_code": "A320",
    "icao24": 10493137,
    "registration": "N106US",
    "owner": None,
    "airline": None,
    "origin": "KLGA",
    "destination": "KCLT",
    "median_delay": None,
    "median_time": None,
}

File operations¤

Saves trajectory data to disk, reads the track and metadata from it.

import rich
from fr24 import FR24, FR24Cache

cache = FR24Cache.default()


async def my_playback() -> None:
    async with FR24() as fr24:
        result = await fr24.playback.fetch(0x2FB3041)
        result.write_table(cache)  # (1)!
    # some time later...
    df_local = cache.playback.scan_table(0x2FB3041).collect()  # (2)!
    print(df_local)


await my_playback()
  1. Saves the parquet to the cache.
  2. Load the parquet from the cache.
shape: (363, 9)
┌────────────┬───────────┬────────────┬──────────┬───┬───────────────┬───────┬────────┬────────────┐
│ timestamp  ┆ latitude  ┆ longitude  ┆ altitude ┆ … ┆ vertical_spee ┆ track ┆ squawk ┆ ems        │
│ ---        ┆ ---       ┆ ---        ┆ ---      ┆   ┆ d             ┆ ---   ┆ ---    ┆ ---        │
│ u32        ┆ f32       ┆ f32        ┆ i32      ┆   ┆ ---           ┆ i16   ┆ u16    ┆ struct[18] │
│            ┆           ┆            ┆          ┆   ┆ i16           ┆       ┆        ┆            │
╞════════════╪═══════════╪════════════╪══════════╪═══╪═══════════════╪═══════╪════════╪════════════╡
│ 1232049993 ┆ 40.770302 ┆ -73.862801 ┆ 0        ┆ … ┆ null          ┆ 59    ┆ 0      ┆ null       │
│ 1232049997 ┆ 40.770302 ┆ -73.862503 ┆ 0        ┆ … ┆ null          ┆ 65    ┆ 0      ┆ null       │
│ 1232050001 ┆ 40.770302 ┆ -73.862198 ┆ 0        ┆ … ┆ null          ┆ 71    ┆ 0      ┆ null       │
│ 1232050005 ┆ 40.770302 ┆ -73.862198 ┆ 0        ┆ … ┆ null          ┆ 76    ┆ 0      ┆ null       │
│ 1232050009 ┆ 40.770302 ┆ -73.862198 ┆ 0        ┆ … ┆ null          ┆ 82    ┆ 0      ┆ null       │
│ …          ┆ …         ┆ …          ┆ …        ┆ … ┆ …             ┆ …     ┆ …      ┆ …          │
│ 1232051425 ┆ 40.781399 ┆ -73.998199 ┆ 326      ┆ … ┆ null          ┆ 223   ┆ 0      ┆ null       │
│ 1232051429 ┆ 40.779202 ┆ -73.999603 ┆ 274      ┆ … ┆ null          ┆ 226   ┆ 0      ┆ null       │
│ 1232051433 ┆ 40.777199 ┆ -74.001297 ┆ 187      ┆ … ┆ null          ┆ 222   ┆ 0      ┆ null       │
│ 1232051437 ┆ 40.775002 ┆ -74.002899 ┆ 106      ┆ … ┆ null          ┆ 223   ┆ 0      ┆ null       │
│ 1232051441 ┆ 40.773102 ┆ -74.004303 ┆ 42       ┆ … ┆ null          ┆ 223   ┆ 0      ┆ null       │
└────────────┴───────────┴────────────┴──────────┴───┴───────────────┴───────┴────────┴────────────┘
{
    "flight_id": 50016321,
    "callsign": "AWE1549",
    "flight_number": "UA1549",
    "status_type": "departure",
    "status_text": None,
    "status_diverted": None,
    "status_time": None,
    "model_code": "A320",
    "icao24": 10493137,
    "registration": "N106US",
    "owner": None,
    "airline": None,
    "origin": "KLGA",
    "destination": "KCLT",
    "median_delay": None,
    "median_time": None,
}

Airport List¤

import httpx

from fr24.types.json import AirportList
from fr24.json import airport_list, AirportListParams
from fr24.proto.headers import get_grpc_headers

import polars as pl


async def my_arrivals() -> AirportList:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        response = await airport_list(
            client,
            AirportListParams(airport="tls", mode="arrivals"),
            headers=headers,
            auth=None,
        )
        response.raise_for_status()
        list_ = response.json()
        return list_  # type: ignore


airports = await my_arrivals()
arrivals = airports["result"]["response"]["airport"]["pluginData"]["schedule"][
    "arrivals"
]["data"]
assert arrivals is not None
df = pl.json_normalize(arrivals)
print(df)
shape: (10, 76)
┌───────────┬───────────┬───────────┬───────────┬───┬───────────┬───────────┬───────────┬──────────┐
│ flight.id ┆ flight.id ┆ flight.id ┆ flight.id ┆ … ┆ flight.ti ┆ flight.ai ┆ flight.ow ┆ flight.a │
│ entificat ┆ entificat ┆ entificat ┆ entificat ┆   ┆ me.other. ┆ rcraft.im ┆ ner       ┆ irline   │
│ ion.id    ┆ ion.row   ┆ ion.numbe ┆ ion.numbe ┆   ┆ duration  ┆ ages      ┆ ---       ┆ ---      │
│ ---       ┆ ---       ┆ r.d…      ┆ r.a…      ┆   ┆ ---       ┆ ---       ┆ null      ┆ null     │
│ str       ┆ i64       ┆ ---       ┆ ---       ┆   ┆ null      ┆ null      ┆           ┆          │
│           ┆           ┆ str       ┆ str       ┆   ┆           ┆           ┆           ┆          │
╞═══════════╪═══════════╪═══════════╪═══════════╪═══╪═══════════╪═══════════╪═══════════╪══════════╡
│ 3963916d  ┆ 563063588 ┆ AF6132    ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 1         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ null      ┆ 563365562 ┆ null      ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 4         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 39638d76  ┆ 563085809 ┆ T71527    ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 2         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 3963a803  ┆ 563063662 ┆ AF7408    ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 2         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 396399a4  ┆ 563087474 ┆ U24849    ┆ EC4849    ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 7         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ null      ┆ 563088423 ┆ V72371    ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 4         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 3963978d  ┆ 563085809 ┆ T73718    ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 1         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 3963ab98  ┆ 563089434 ┆ XK720     ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 8         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 396398ab  ┆ 563071223 ┆ FR3903    ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 6         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 3963b61f  ┆ 563072081 ┆ GP155     ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 9         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
└───────────┴───────────┴───────────┴───────────┴───┴───────────┴───────────┴───────────┴──────────┘
from fr24.types.json import Find
from fr24 import FR24

import polars as pl


async def my_find() -> Find:
    async with FR24() as fr24:
        result = await fr24.find.fetch(query="paris")
        return result.to_dict()


results = await my_find()
df = pl.json_normalize(results["results"])
print(df)
shape: (9, 7)
┌─────┬───────────────────────────────┬─────────┬──────────┬────────────┬────────────┬─────────────┐
│ id  ┆ label                         ┆ type    ┆ match    ┆ detail.lat ┆ detail.lon ┆ detail.size │
│ --- ┆ ---                           ┆ ---     ┆ ---      ┆ ---        ┆ ---        ┆ ---         │
│ str ┆ str                           ┆ str     ┆ str      ┆ f64        ┆ f64        ┆ i64         │
╞═════╪═══════════════════════════════╪═════════╪══════════╪════════════╪════════════╪═════════════╡
│ CDG ┆ Paris Charles de Gaulle       ┆ airport ┆ begins   ┆ 49.012516  ┆ 2.555752   ┆ 201280      │
│     ┆ Airpor…                       ┆         ┆          ┆            ┆            ┆             │
│ ORY ┆ Paris Orly Airport (ORY /     ┆ airport ┆ begins   ┆ 48.723331  ┆ 2.379444   ┆ 84510       │
│     ┆ LFPO…                         ┆         ┆          ┆            ┆            ┆             │
│ LBG ┆ Paris Le Bourget Airport (LBG ┆ airport ┆ begins   ┆ 48.958801  ┆ 2.4336     ┆ 24465       │
│     ┆ …                             ┆         ┆          ┆            ┆            ┆             │
│ BVA ┆ Paris Beauvais-Tille Airport  ┆ airport ┆ begins   ┆ 49.453465  ┆ 2.115138   ┆ 15939       │
│     ┆ (…                            ┆         ┆          ┆            ┆            ┆             │
│ VIY ┆ Paris Villacoublay Velizy Air ┆ airport ┆ begins   ┆ 48.774399  ┆ 2.20154    ┆ 1038        │
│     ┆ …                             ┆         ┆          ┆            ┆            ┆             │
│ PRX ┆ Paris Cox Field (PRX / KPRX)  ┆ airport ┆ begins   ┆ 33.636665  ┆ -95.450279 ┆ 953         │
│ XCR ┆ Paris Vatry Chalons Airport   ┆ airport ┆ begins   ┆ 48.759998  ┆ 4.2        ┆ 710         │
│     ┆ (X…                           ┆         ┆          ┆            ┆            ┆             │
│ PHT ┆ Paris Henry County Airport    ┆ airport ┆ begins   ┆ 36.336384  ┆ -88.38427  ┆ 199         │
│     ┆ (PH…                          ┆         ┆          ┆            ┆            ┆             │
│ OPL ┆ Opelousas St. Landry Parish   ┆ airport ┆ contains ┆ 30.555695  ┆ -92.098915 ┆ 194         │
│     ┆ Ai…                           ┆         ┆          ┆            ┆            ┆             │
└─────┴───────────────────────────────┴─────────┴──────────┴────────────┴────────────┴─────────────┘

Live Feed¤

Live¤

This example is covered in detail in the quickstart.

from fr24 import FR24, FR24Cache, BoundingBox

bbox = BoundingBox(south=42, north=52, west=-8, east=10)


async def my_feed() -> None:
    async with FR24() as fr24:
        result = await fr24.live_feed.fetch(bbox)
        print(result)
        print(result.to_dict())
        print(result.to_polars())
        result.write_table(FR24Cache.default())


await my_feed()
LiveFeedResult(
    request=LiveFeedParams(
        bounding_box=BoundingBox(south=42, north=52, west=-8, east=10),
        stats=False,
        limit=1500,
        maxage=14400,
        fields={"reg", "route", "flight", "type"},
    ),
    response=<Response [200 OK]>,
    timestamp=1753150332,
)
{
    "flights_list": [
        {
            "flightid": 995827034,
            "lat": 43.11081,
            "lon": -4.72674,
            "track": 23,
            "alt": 43000,
            "speed": 513,
            "icon": "A330",
            "timestamp": 1753150329,
            "callsign": "AFR407",
            "extra_info": {
                "flight": "AF407",
                "reg": "F-HTYA",
                "route": {"from": "SCL", "to": "CDG"},
                "type": "A359",
            },
            "position_buffer": {
                "recent_positions_list": [
                    {"delta_lat": 247, "delta_lon": 146, "delta_ms": 1088},
                    {"delta_lat": 434, "delta_lon": 255, "delta_ms": 2013},
                    {"delta_lat": 664, "delta_lon": 392, "delta_ms": 3038},
                    {"delta_lat": 958, "delta_lon": 568, "delta_ms": 4375},
                    {"delta_lat": 1172, "delta_lon": 699, "delta_ms": 5375},
                    {"delta_lat": 1382, "delta_lon": 817, "delta_ms": 6313},
                    {"delta_lat": 1707, "delta_lon": 1013, "delta_ms": 7875},
                    {"delta_lat": 2000, "delta_lon": 1189, "delta_ms": 9163},
                    {"delta_lat": 2252, "delta_lon": 1334, "delta_ms": 10288},
                ]
            },
            "timestamp_ms": "1753150329391",
        },
        ...
    ],
    "server_time_ms": "1753150332065",
}
shape: (171, 18)
┌──────────────┬───────────┬───────────┬───────────┬───┬─────┬────────┬──────────────┬─────────────┐
│ timestamp    ┆ flightid  ┆ latitude  ┆ longitude ┆ … ┆ eta ┆ squawk ┆ vertical_spe ┆ position_bu │
│ ---          ┆ ---       ┆ ---       ┆ ---       ┆   ┆ --- ┆ ---    ┆ ed           ┆ ffer        │
│ datetime[ms, ┆ u32       ┆ f32       ┆ f32       ┆   ┆ u32 ┆ u16    ┆ ---          ┆ ---         │
│ UTC]         ┆           ┆           ┆           ┆   ┆     ┆        ┆ i16          ┆ list[struct │
│              ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ [3]]        │
╞══════════════╪═══════════╪═══════════╪═══════════╪═══╪═════╪════════╪══════════════╪═════════════╡
│ 2025-07-22   ┆ 995827034 ┆ 43.110809 ┆ -4.72674  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ [{247,146,1 │
│ 02:12:09.391 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 088}, {434, │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 255,2013…   │
│ 2025-07-22   ┆ 995947452 ┆ 43.176819 ┆ -3.079877 ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ [{210,95,10 │
│ 02:12:09.762 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 90}, {421,1 │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 91,2110}…   │
│ 2025-07-22   ┆ 995945816 ┆ 42.667923 ┆ -2.855509 ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ [{45,-137,1 │
│ 02:12:10.242 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 140}, {149, │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ -455,377…   │
│ 2025-07-22   ┆ 995924443 ┆ 45.168983 ┆ -3.100891 ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ [{299,307,1 │
│ 02:12:10.116 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 540}, {514, │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 529,2610…   │
│ 2025-07-22   ┆ 995916683 ┆ 45.573853 ┆ -2.016594 ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ [{192,174,9 │
│ 02:12:09.579 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 90}, {370,3 │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 28,1880}…   │
│ …            ┆ …         ┆ …         ┆ …         ┆ … ┆ …   ┆ …      ┆ …            ┆ …           │
│ 2025-07-22   ┆ 995956094 ┆ 51.458233 ┆ 5.390149  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ [{0,0,4902} │
│ 02:12:06.528 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ , {0,0,1000 │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 4}]         │
│ 2025-07-22   ┆ 995956104 ┆ 51.45718  ┆ 5.388998  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ [{0,0,5030} │
│ 02:12:06.722 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ , {0,0,1010 │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 0}]         │
│ 2025-07-22   ┆ 995957785 ┆ 51.915054 ┆ 6.172904  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ [{21,-324,9 │
│ 02:12:09.788 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 85}, {53,-6 │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 82,1980}…   │
│ 2025-07-22   ┆ 995959079 ┆ 51.789047 ┆ 8.022098  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ [{123,475,2 │
│ 02:12:09.029 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 309}, {186, │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 711,3455…   │
│ 2025-07-22   ┆ 995949304 ┆ 51.774536 ┆ 8.631542  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ [{27,-527,1 │
│ 02:12:09.460 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 535}, {45,- │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ 920,2677…   │
└──────────────┴───────────┴───────────┴───────────┴───┴─────┴────────┴──────────────┴─────────────┘
"""
# %%
from fr24 import FR24, BoundingBox
import time

yesterday = int(time.time() - 86400)
bbox = BoundingBox(south=42, north=52, west=-8, east=10)


async def my_feed() -> None:
    async with FR24() as fr24:
        result = await fr24.live_feed_playback.fetch(bbox, timestamp=yesterday)
        print(result.to_polars())


await my_feed()

# %%
"""
shape: (139, 18)
┌──────────────┬───────────┬───────────┬───────────┬───┬─────┬────────┬──────────────┬─────────────┐
│ timestamp    ┆ flightid  ┆ latitude  ┆ longitude ┆ … ┆ eta ┆ squawk ┆ vertical_spe ┆ position_bu │
│ ---          ┆ ---       ┆ ---       ┆ ---       ┆   ┆ --- ┆ ---    ┆ ed           ┆ ffer        │
│ datetime[ms, ┆ u32       ┆ f32       ┆ f32       ┆   ┆ u32 ┆ u16    ┆ ---          ┆ ---         │
│ UTC]         ┆           ┆           ┆           ┆   ┆     ┆        ┆ i16          ┆ list[struct │
│              ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ [3]]        │
╞══════════════╪═══════════╪═══════════╪═══════════╪═══╪═════╪════════╪══════════════╪═════════════╡
│ 2025-07-21   ┆ 995593418 ┆ 43.238297 ┆ -4.690012 ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:58.408 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995708427 ┆ 42.489532 ┆ 1.29364   ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:58.430 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995704634 ┆ 42.442608 ┆ -2.886849 ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:58.895 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995658391 ┆ 43.957397 ┆ -7.309677 ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:58.852 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995709110 ┆ 42.351471 ┆ 4.712822  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:59.310 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ …            ┆ …         ┆ …         ┆ …         ┆ … ┆ …   ┆ …      ┆ …            ┆ …           │
│ 2025-07-21   ┆ 995713747 ┆ 50.823303 ┆ 7.588361  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:59.020 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995713721 ┆ 50.925819 ┆ 7.402649  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:58.966 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995714247 ┆ 50.87875  ┆ 7.124541  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:54.967 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995715577 ┆ 50.983913 ┆ 7.240559  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:58.219 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995714961 ┆ 50.878696 ┆ 7.126026  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:59.524 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
└──────────────┴───────────┴───────────┴───────────┴───┴─────┴────────┴──────────────┴─────────────┘
"""

Playback¤

Fetches the live feed three days ago.

from fr24 import FR24, BoundingBox
import time

yesterday = int(time.time() - 86400)
bbox = BoundingBox(south=42, north=52, west=-8, east=10)


async def my_feed() -> None:
    async with FR24() as fr24:
        result = await fr24.live_feed_playback.fetch(bbox, timestamp=yesterday)
        print(result.to_polars())


await my_feed()
shape: (139, 18)
┌──────────────┬───────────┬───────────┬───────────┬───┬─────┬────────┬──────────────┬─────────────┐
│ timestamp    ┆ flightid  ┆ latitude  ┆ longitude ┆ … ┆ eta ┆ squawk ┆ vertical_spe ┆ position_bu │
│ ---          ┆ ---       ┆ ---       ┆ ---       ┆   ┆ --- ┆ ---    ┆ ed           ┆ ffer        │
│ datetime[ms, ┆ u32       ┆ f32       ┆ f32       ┆   ┆ u32 ┆ u16    ┆ ---          ┆ ---         │
│ UTC]         ┆           ┆           ┆           ┆   ┆     ┆        ┆ i16          ┆ list[struct │
│              ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆ [3]]        │
╞══════════════╪═══════════╪═══════════╪═══════════╪═══╪═════╪════════╪══════════════╪═════════════╡
│ 2025-07-21   ┆ 995593418 ┆ 43.238297 ┆ -4.690012 ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:58.408 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995708427 ┆ 42.489532 ┆ 1.29364   ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:58.430 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995704634 ┆ 42.442608 ┆ -2.886849 ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:58.895 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995658391 ┆ 43.957397 ┆ -7.309677 ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:58.852 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995709110 ┆ 42.351471 ┆ 4.712822  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:59.310 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ …            ┆ …         ┆ …         ┆ …         ┆ … ┆ …   ┆ …      ┆ …            ┆ …           │
│ 2025-07-21   ┆ 995713747 ┆ 50.823303 ┆ 7.588361  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:59.020 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995713721 ┆ 50.925819 ┆ 7.402649  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:58.966 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995714247 ┆ 50.87875  ┆ 7.124541  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:54.967 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995715577 ┆ 50.983913 ┆ 7.240559  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:58.219 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ 2025-07-21   ┆ 995714961 ┆ 50.878696 ┆ 7.126026  ┆ … ┆ 0   ┆ 0      ┆ 0            ┆ []          │
│ 02:15:59.524 ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
│ UTC          ┆           ┆           ┆           ┆   ┆     ┆        ┆              ┆             │
└──────────────┴───────────┴───────────┴───────────┴───┴─────┴────────┴──────────────┴─────────────┘

Nearest Flights¤

from fr24 import FR24, FR24Cache


async def my_nearest_flights() -> None:
    async with FR24() as fr24:
        result = await fr24.nearest_flights.fetch(
            lat=22.31257, lon=113.92708, radius=10000, limit=1500
        )
        print(result)
        print(result.to_dict())
        print(result.to_polars())
        result.write_table(FR24Cache.default())


await my_nearest_flights()
NearestFlightsResult(
    request=NearestFlightsParams(
        lat=22.31257,
        lon=113.92708,
        radius=10000,
        limit=1500
    ),
    response=<Response [200 OK]>,
    timestamp=1748177063
)
{
    'flights_list': [
        {
            'flight': {
                'flightid': 981376678,
                'lat': 22.315142,
                'lon': 113.92878,
                'track': 67,
                'timestamp': 1748178906,
                'on_ground': True,
                'extra_info': {'reg': 'B-18663', 'route': {'from': 'HKG'}, 'type': 'B738', 'logo_id': 86},
                'timestamp_ms': '1748178906661'
            },
            'distance': 334
        },
        ...
        {
            'flight': {
                'flightid': 981339515,
                'lat': 22.305908,
                'lon': 113.83389,
                'track': 71,
                'alt': 875,
                'speed': 130,
                'icon': 'A330',
                'timestamp': 1748178957,
                'callsign': 'CPA381',
                'extra_info': {
                    'flight': 'CX381',
                    'reg': 'B-LBJ',
                    'route': {'from': 'PVG', 'to': 'HKG'},
                    'type': 'A333',
                    'logo_id': 57
                },
                'timestamp_ms': '1748178957019'
            },
            'distance': 9629
        }
    ]
}
shape: (20, 19)
┌────────────┬───────────┬───────────┬────────────┬───┬────────────┬────────┬───────────┬──────────┐
│ timestamp  ┆ flightid  ┆ latitude  ┆ longitude  ┆ … ┆ vertical_s ┆ squawk ┆ position_ ┆ distance │
│ ---        ┆ ---       ┆ ---       ┆ ---        ┆   ┆ peed       ┆ ---    ┆ buffer    ┆ ---      │
│ u32        ┆ u32       ┆ f32       ┆ f32        ┆   ┆ ---        ┆ u16    ┆ ---       ┆ u32      │
│            ┆           ┆           ┆            ┆   ┆ i16        ┆        ┆ list[stru ┆          │
│            ┆           ┆           ┆            ┆   ┆            ┆        ┆ ct[3]]    ┆          │
╞════════════╪═══════════╪═══════════╪════════════╪═══╪════════════╪════════╪═══════════╪══════════╡
│ 1748178906 ┆ 981376678 ┆ 22.315142 ┆ 113.92878  ┆ … ┆ 0          ┆ 0      ┆ []        ┆ 334      │
│ 1748178954 ┆ 981376632 ┆ 22.313118 ┆ 113.923676 ┆ … ┆ 0          ┆ 0      ┆ []        ┆ 355      │
│ 1748178953 ┆ 981376221 ┆ 22.31551  ┆ 113.929932 ┆ … ┆ 0          ┆ 0      ┆ []        ┆ 438      │
│ 1748178957 ┆ 981355789 ┆ 22.315166 ┆ 113.923164 ┆ … ┆ 0          ┆ 0      ┆ []        ┆ 495      │
│ 1748178958 ┆ 981375544 ┆ 22.313187 ┆ 113.921371 ┆ … ┆ 0          ┆ 0      ┆ []        ┆ 591      │
│ …          ┆ …         ┆ …         ┆ …          ┆ … ┆ …          ┆ …      ┆ …         ┆ …        │
│ 1748178954 ┆ 981325451 ┆ 22.310371 ┆ 113.901993 ┆ … ┆ 0          ┆ 0      ┆ []        ┆ 2596     │
│ 1748178953 ┆ 981374338 ┆ 22.299173 ┆ 113.89856  ┆ … ┆ 0          ┆ 0      ┆ []        ┆ 3291     │
│ 1748178957 ┆ 981372281 ┆ 22.297474 ┆ 113.898857 ┆ … ┆ 0          ┆ 0      ┆ []        ┆ 3354     │
│ 1748178957 ┆ 981376434 ┆ 22.293045 ┆ 113.970421 ┆ … ┆ 0          ┆ 0      ┆ []        ┆ 4961     │
│ 1748178957 ┆ 981339515 ┆ 22.305908 ┆ 113.833893 ┆ … ┆ 0          ┆ 0      ┆ []        ┆ 9629     │
└────────────┴───────────┴───────────┴────────────┴───┴────────────┴────────┴───────────┴──────────┘

Live Flights Status¤

Retrieve the flight status for the closest flights from a location

from fr24 import FR24, FR24Cache


async def get_nearest_flight_ids(fr24: FR24) -> list[int]:
    nearest_result = await fr24.nearest_flights.fetch(
        lat=22.31257, lon=113.92708, radius=10000, limit=1500
    )
    return [
        flight.flight.flightid
        for flight in nearest_result.to_proto().flights_list
    ]


async def my_live_flights_status() -> None:
    async with FR24() as fr24:
        nearest_flight_ids = await get_nearest_flight_ids(fr24)
        result = await fr24.live_flights_status.fetch(
            flight_ids=nearest_flight_ids[:5]
        )
        print(result)
        print(result.to_dict())
        print(result.to_polars())
        result.write_table(FR24Cache.default())


await my_live_flights_status()
LiveFlightsStatusResult(
    request=LiveFlightsStatusParams(
        flight_ids=[981395112, 981399624, 981364304, 981357406, 981398399]
    ),
    response=<Response [200 OK]>,
    timestamp=1748186042
)
{
    'flights_map': [
        {'flight_id': 981395112, 'data': {'lat': 22.311754, 'lon': 113.92508, 'status': 'LIVE'}},
        {'flight_id': 981398399, 'data': {'lat': 22.313644, 'lon': 113.915115, 'status': 'LIVE'}},
        {'flight_id': 981364304, 'data': {'lat': 22.318283, 'lon': 113.928314, 'status': 'LIVE'}},
        {'flight_id': 981357406, 'data': {'lat': 22.313244, 'lon': 113.934654, 'status': 'LIVE'}},
        {'flight_id': 981399624, 'data': {'lat': 22.310404, 'lon': 113.93139, 'status': 'LIVE'}}
    ]
}
shape: (5, 5)
┌───────────┬───────────┬────────────┬────────┬────────┐
│ flight_id ┆ latitude  ┆ longitude  ┆ status ┆ squawk │
│ ---       ┆ ---       ┆ ---        ┆ ---    ┆ ---    │
│ u32       ┆ f32       ┆ f32        ┆ u8     ┆ u16    │
╞═══════════╪═══════════╪════════════╪════════╪════════╡
│ 981395112 ┆ 22.311754 ┆ 113.925079 ┆ 4      ┆ 0      │
│ 981398399 ┆ 22.313644 ┆ 113.915115 ┆ 4      ┆ 0      │
│ 981364304 ┆ 22.318283 ┆ 113.928314 ┆ 4      ┆ 0      │
│ 981357406 ┆ 22.313244 ┆ 113.934654 ┆ 4      ┆ 0      │
│ 981399624 ┆ 22.310404 ┆ 113.931389 ┆ 4      ┆ 0      │
└───────────┴───────────┴────────────┴────────┴────────┘

Follow Flight¤

Stream real-time updates to the state vector of an aircraft.

Note

This is a streaming service which endlessly yields the latest updates.

Unlike other services, it does not offer a default serialisation strategy (i.e. result.write_parquet does not exist). For a local setup, consider inserting the updates to a SQLite database manually.

The first packet of data contains useful initial metadata (aircraft_info, flight_plan and flight_trail_list), which will not be re-transmitted in the subsequent updates.

Tip

The server often sends state vector packets every 1-60 seconds, but httpx by default closes the stream after 5 seconds. We increase the timeout to 120 seconds to avoid premature closure.

import httpx

from fr24 import FR24
from fr24.proto.v1_pb2 import NearestFlightsResponse


async def get_nearest_flights(fr24: FR24) -> NearestFlightsResponse:
    nearest_result = await fr24.nearest_flights.fetch(
        lat=22.31257, lon=113.92708, radius=10000, limit=1500
    )
    return nearest_result.to_proto()


async def my_follow_flight() -> None:
    timeout = httpx.Timeout(5, read=120)
    async with FR24(client=httpx.AsyncClient(timeout=timeout)) as fr24:
        nearest_flights_result = await get_nearest_flights(fr24)
        flight_id = nearest_flights_result.flights_list[0].flight.flightid
        i = 0
        async for result in fr24.follow_flight.stream(flight_id=flight_id):
            print(f"##### {i} #####")
            print(result.to_proto())
            i += 1
            if i > 2:
                break


await my_follow_flight()
##### 0 #####
aircraft_info {
  icao_address: 7701252
  reg: "RP-C9903"
  type: "A321"
  icon: A320
  full_description: "Airbus A321-231"
  images_list {
    url: "https://www.jetphotos.com/photo/11825012"
    copyright: "yajoo"
    thumbnail: "https://cdn.jetphotos.com/200/5/2378185_1756401937_tb.jpg"
    medium: "https://cdn.jetphotos.com/400/5/2378185_1756401937.jpg"
    large: "https://cdn.jetphotos.com/640/5/2378185_1756401937.jpg"
  }
  images_list {
    url: "https://www.jetphotos.com/photo/11813525"
    copyright: "Landing HKG"
    thumbnail: "https://cdn.jetphotos.com/200/6/522343_1755503883_tb.jpg"
    medium: "https://cdn.jetphotos.com/400/6/522343_1755503883.jpg"
    large: "https://cdn.jetphotos.com/640/6/522343_1755503883.jpg"
  }
  images_list {
    url: "https://www.jetphotos.com/photo/11745327"
    copyright: "saTrL"
    thumbnail: "https://cdn.jetphotos.com/200/5/630999_1749204666_tb.jpg"
    medium: "https://cdn.jetphotos.com/400/5/630999_1749204666.jpg"
    large: "https://cdn.jetphotos.com/640/5/630999_1749204666.jpg"
  }
  msn_available: true
  age_available: true
  registered_owners: "Philippine Airlines"
  is_country_of_reg_available: true
}
schedule_info {
  flight_number: "PR311"
  operated_by_id: 98
  painted_as_id: 98
  origin_id: 1366
  destination_id: 2266
  scheduled_departure: 1758466800
  scheduled_arrival: 1758475200
  arr_terminal: "1"
}
flight_progress {
  traversed_distance: 657
  remaining_distance: 1143081
  great_circle_distance: 1143502
  mean_flight_time: 5886
  flight_stage: ON_GROUND
}
flight_info {
  flightid: 1011880908
  lat: 22.3098583
  lon: 113.922615
  track: 160
  speed: 8
  timestamp_ms: 1758466956660
  on_ground: true
  callsign: "PAL311"
  ems_availability {
    rs_availability: true
  }
  squawk_availability: true
  airspace_availability: true
  server_time_ms: 1758466960115
}
flight_trail_list {
  snapshot_id: 1758466272
  lat: 22.3157578
  lon: 113.932076
  spd: 3
  heading: 177
}
...
}
flight_trail_list {
  snapshot_id: 1758466950
  lat: 22.3100777
  lon: 113.922523
  spd: 9
  heading: 160
}
position_buffer {
  recent_positions_list {
    delta_lat: -5
    delta_lon: 2
    delta_ms: 1670
  }
  recent_positions_list {
    delta_lat: -9
    delta_lon: 3
    delta_ms: 2610
  }
  recent_positions_list {
    delta_lat: -21
    delta_lon: 9
    delta_ms: 6010
  }
  recent_positions_list {
    delta_lat: -47
    delta_lon: 18
    delta_ms: 12350
  }
}

##### 1 #####
schedule_info {
  flight_number: "PR311"
  operated_by_id: 98
  painted_as_id: 98
  origin_id: 1366
  destination_id: 2266
  scheduled_departure: 1758466800
  scheduled_arrival: 1758475200
  arr_terminal: "1"
}
flight_progress {
  traversed_distance: 662
  remaining_distance: 1143066
  great_circle_distance: 1143502
  mean_flight_time: 5886
  flight_stage: ON_GROUND
}
flight_info {
  flightid: 1011880908
  lat: 22.3097286
  lon: 113.922668
  track: 160
  speed: 8
  timestamp_ms: 1758466960150
  on_ground: true
  callsign: "PAL311"
  ems_availability {
    rs_availability: true
  }
  squawk_availability: true
  airspace_availability: true
  server_time_ms: 1758466963120
}

##### 2 #####
schedule_info {
  flight_number: "PR311"
  operated_by_id: 98
  painted_as_id: 98
  origin_id: 1366
  destination_id: 2266
  scheduled_departure: 1758466800
  scheduled_arrival: 1758475200
  arr_terminal: "1"
}
flight_progress {
  traversed_distance: 667
  remaining_distance: 1143051
  great_circle_distance: 1143502
  mean_flight_time: 5886
  flight_stage: ON_GROUND
}
flight_info {
  flightid: 1011880908
  lat: 22.3095818
  lon: 113.922714
  track: 160
  speed: 9
  timestamp_ms: 1758466963941
  on_ground: true
  callsign: "PAL311"
  ems_availability {
    rs_availability: true
  }
  squawk_availability: true
  airspace_availability: true
  server_time_ms: 1758466966122
}

Top Flights¤

from fr24 import FR24, FR24Cache
from rich import print


async def my_top_flights() -> None:
    async with FR24() as fr24:
        result = await fr24.top_flights.fetch(limit=10)
        print(result)
        print(result.to_dict())
        print(result.to_polars())
        result.write_table(FR24Cache.default())


await my_top_flights()
TopFlightsResult(
    request=TopFlightsParams(limit=10),
    response=<Response [200 OK]>,
    timestamp=1748188667
)
{
    'scoreboard_list': [
        {
            'flight_id': 981367259,
            'live_clicks': 1438,
            'total_clicks': 1438,
            'flight_number': 'DOC72',
            'callsign': 'DOC72',
            'from_iata': 'FRG',
            'from_city': 'Farmingdale',
            'to_iata': 'FRG',
            'to_city': 'Farmingdale',
            'type': 'B29',
            'full_description': 'Boeing TB-29 Superfortress'
        },
        ...
        {
            'flight_id': 981290224,
            'live_clicks': 514,
            'total_clicks': 514,
            'flight_number': 'SQ326',
            'callsign': 'SIA326',
            'from_iata': 'SIN',
            'from_city': 'Singapore',
            'to_iata': 'FRA',
            'to_city': 'Frankfurt',
            'type': 'A388',
            'full_description': 'Airbus A380-841'
        }
    ]
}
shape: (10, 12)
┌───────────┬─────────────┬────────────┬────────────┬───┬─────────┬────────────┬──────┬────────────┐
│ flight_id ┆ live_clicks ┆ total_clic ┆ flight_num ┆ … ┆ to_iata ┆ to_city    ┆ type ┆ full_descr │
│ ---       ┆ ---         ┆ ks         ┆ ber        ┆   ┆ ---     ┆ ---        ┆ ---  ┆ iption     │
│ u32       ┆ u32         ┆ ---        ┆ ---        ┆   ┆ str     ┆ str        ┆ str  ┆ ---        │
│           ┆             ┆ u32        ┆ str        ┆   ┆         ┆            ┆      ┆ str        │
╞═══════════╪═════════════╪════════════╪════════════╪═══╪═════════╪════════════╪══════╪════════════╡
│ 981367259 ┆ 1438        ┆ 1438       ┆ DOC72      ┆ … ┆ FRG     ┆ Farmingdal ┆ B29  ┆ Boeing     │
│           ┆             ┆            ┆            ┆   ┆         ┆ e          ┆      ┆ TB-29 Supe │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ rfortress  │
│ 981383686 ┆ 1066        ┆ 1066       ┆ RRR4952    ┆ … ┆ RZE     ┆ Rzeszow    ┆ A400 ┆ Airbus     │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ A400M      │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ Atlas      │
│ 981393352 ┆ 890         ┆ 890        ┆            ┆ … ┆         ┆            ┆ DC3  ┆ Douglas    │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ DC-3C      │
│ 981407748 ┆ 831         ┆ 831        ┆            ┆ … ┆         ┆            ┆ EC35 ┆ Airbus Hel │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ icopters   │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ H135       │
│ 981398120 ┆ 707         ┆ 707        ┆            ┆ … ┆ RTM     ┆ Rotterdam  ┆ SR22 ┆ Cirrus     │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ SR22       │
│ 981400483 ┆ 673         ┆ 673        ┆            ┆ … ┆         ┆            ┆ BR23 ┆ BRM Aero   │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ Bristell   │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ B23        │
│ 981402316 ┆ 616         ┆ 616        ┆            ┆ … ┆         ┆            ┆ DHC6 ┆ Viking     │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ DHC-6-400  │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ Twin Otter │
│ 981368239 ┆ 554         ┆ 554        ┆ VJT750     ┆ … ┆ GIG     ┆ Rio de     ┆ GL7T ┆ Bombardier │
│           ┆             ┆            ┆            ┆   ┆         ┆ Janeiro    ┆      ┆ Global     │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ 7500       │
│ 981404508 ┆ 535         ┆ 535        ┆            ┆ … ┆         ┆            ┆ GLID ┆ Alexander  │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ Schleicher │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ ASK-23B    │
│ 981290224 ┆ 514         ┆ 514        ┆ SQ326      ┆ … ┆ FRA     ┆ Frankfurt  ┆ A388 ┆ Airbus     │
│           ┆             ┆            ┆            ┆   ┆         ┆            ┆      ┆ A380-841   │
└───────────┴─────────────┴────────────┴────────────┴───┴─────────┴────────────┴──────┴────────────┘

Flight Details¤

Retrieve detailed information about a flight

from fr24 import FR24, FR24Cache


async def get_farthest_flight_id(fr24: FR24) -> int:
    nearest_result = await fr24.nearest_flights.fetch(
        lat=22.31257, lon=113.92708, radius=10000, limit=1500
    )
    return nearest_result.to_proto().flights_list[-1].flight.flightid


async def my_flight_details() -> None:
    async with FR24() as fr24:
        flight_id = await get_farthest_flight_id(fr24)
        result = await fr24.flight_details.fetch(flight_id=flight_id)
        print(result)
        print(result.to_dict())
        print(result.to_polars())
        result.write_table(FR24Cache.default())


await my_flight_details()
FlightDetailsResult(
    request=FlightDetailsParams(flight_id=1011852915, restriction_mode=0, verbose=True),
    response=<Response [200 OK]>,
    timestamp=1758466410
)
{
    "aircraft_info": {
        "icao_address": 7864687,
        "reg": "B-HNG",
        "type": "B773",
        "icon": "B777",
        "full_description": "Boeing 777-367",
        "images_list": [
            {
                "url": "https://www.jetphotos.com/photo/11821124",
                "copyright": "kuzuma",
                "thumbnail": "https://cdn.jetphotos.com/200/5/505864_1756100441_tb.jpg",
                "medium": "https://cdn.jetphotos.com/400/5/505864_1756100441.jpg",
                "large": "https://cdn.jetphotos.com/640/5/505864_1756100441.jpg",
            },
            {
                "url": "https://www.jetphotos.com/photo/11808578",
                "copyright": "tobiashsu1217_spotter",
                "thumbnail": "https://cdn.jetphotos.com/200/6/1544325_1755012630_tb.jpg",
                "medium": "https://cdn.jetphotos.com/400/6/1544325_1755012630.jpg",
                "large": "https://cdn.jetphotos.com/640/6/1544325_1755012630.jpg",
            },
            {
                "url": "https://www.jetphotos.com/photo/11804947",
                "copyright": "Stanley Joe Hidayat",
                "thumbnail": "https://cdn.jetphotos.com/200/5/389644_1754704150_tb.jpg",
                "medium": "https://cdn.jetphotos.com/400/5/389644_1754704150.jpg",
                "large": "https://cdn.jetphotos.com/640/5/389644_1754704150.jpg",
            },
        ],
        "msn_available": True,
        "age_available": True,
        "registered_owners": "Cathay Pacific",
        "is_country_of_reg_available": True,
    },
    "schedule_info": {
        "flight_number": "CX902",
        "operated_by_id": 57,
        "painted_as_id": 57,
        "origin_id": 2266,
        "destination_id": 1366,
        "scheduled_departure": 1758457200,
        "scheduled_arrival": 1758466500,
        "actual_departure": 1758460310,
        "arr_terminal": "1",
        "baggage_belt": "10",
    },
    "flight_progress": {
        "traversed_distance": 1146491,
        "remaining_distance": 3113,
        "elapsed_time": 6100,
        "remaining_time": 29,
        "eta": 1758466439,
        "great_circle_distance": 1143502,
        "mean_flight_time": 5846,
        "flight_stage": "AIRBORNE",
        "delay_status": "GREEN",
        "progress_pct": 99,
    },
    "flight_info": {
        "flightid": 1011852915,
        "lat": 22.324324,
        "lon": 113.89048,
        "track": 70,
        "speed": 120,
        "timestamp_ms": "1758466407324",
        "callsign": "CPA902",
        "ems_availability": {
            "qnh_availability": True,
            "amcp_availability": True,
            "oat_availability": True,
            "ias_availability": True,
            "tas_availability": True,
            "mach_availability": True,
            "agps_availability": True,
            "agpsdiff_availability": True,
            "wind_dir_availability": True,
            "wind_speed_availability": True,
        },
        "squawk_availability": True,
        "airspace_availability": True,
        "server_time_ms": "1758466410387",
    },
    "flight_plan": {},
    "flight_trail_list": [
        {
            "snapshot_id": "1758458895",
            "lat": 14.517563,
            "lon": 121.01436,
            "spd": 1,
            "heading": 101,
        },
        ...
        {
            "snapshot_id": "1758466399",
            "lat": 22.322754,
            "lon": 113.88553,
            "altitude": 100,
            "spd": 141,
            "heading": 70,
        },
    ],
    "position_buffer": {
        "recent_positions_list": [
            {"delta_lat": 43, "delta_lon": 131, "delta_ms": 2079},
            {"delta_lat": 94, "delta_lon": 294, "delta_ms": 4660},
            {"delta_lat": 112, "delta_lon": 350, "delta_ms": 5589},
            {"delta_lat": 156, "delta_lon": 495, "delta_ms": 7660},
            {"delta_lat": 196, "delta_lon": 614, "delta_ms": 9579},
            {"delta_lat": 234, "delta_lon": 721, "delta_ms": 11019},
        ]
    },
}
shape: (1, 32)
┌─────────────┬───────┬──────────┬─────────────┬───┬────────┬────────────┬────────────┬────────────┐
│ icao_addres ┆ reg   ┆ typecode ┆ flight_numb ┆ … ┆ squawk ┆ ems        ┆ flight_tra ┆ position_b │
│ s           ┆ ---   ┆ ---      ┆ er          ┆   ┆ ---    ┆ ---        ┆ il_list    ┆ uffer      │
│ ---         ┆ str   ┆ str      ┆ ---         ┆   ┆ u16    ┆ struct[13] ┆ ---        ┆ ---        │
│ u32         ┆       ┆          ┆ str         ┆   ┆        ┆            ┆ list[struc ┆ list[struc │
│             ┆       ┆          ┆             ┆   ┆        ┆            ┆ t[8]]      ┆ t[3]]      │
╞═════════════╪═══════╪══════════╪═════════════╪═══╪════════╪════════════╪════════════╪════════════╡
│ 7864687     ┆ B-HNG ┆ B773     ┆ CX902       ┆ … ┆ 0      ┆ {0,0,0,0,0 ┆ [{17584588 ┆ [{43,131,2 │
│             ┆       ┆          ┆             ┆   ┆        ┆ ,0,0,0,0,0 ┆ 95,14.5175 ┆ 079}, {94, │
│             ┆       ┆          ┆             ┆   ┆        ┆ ,0,0,0}    ┆ 63,121.014 ┆ 294,4660}, │
│             ┆       ┆          ┆             ┆   ┆        ┆            ┆ …          ┆ …          │
└─────────────┴───────┴──────────┴─────────────┴───┴────────┴────────────┴────────────┴────────────┘

Playback Flight¤

Retrieve detailed historical flight information including complete trail

from fr24 import FR24, FR24Cache
import polars as pl


async def get_last_flight(fr24: FR24, *, reg: str = "B-LRA") -> tuple[int, int]:
    flight_list_result = await fr24.flight_list.fetch(reg=reg)
    df = flight_list_result.to_polars()

    landed = df.filter(pl.col("status").str.starts_with("Landed"))
    assert landed.height > 0, "no landed flights found"

    flight_id = landed[0, "flight_id"]
    stod = int(landed[0, "ATOD"].timestamp())
    return flight_id, stod


async def my_playback_flight() -> None:
    async with FR24() as fr24:
        flight_id, timestamp = await get_last_flight(fr24)
        result = await fr24.playback_flight.fetch(
            flight_id=flight_id, timestamp=timestamp
        )
        print(result)
        print(result.to_dict())
        print(result.to_polars())
        result.write_table(FR24Cache.default())


await my_playback_flight()
PlaybackFlightResult(
    request=PlaybackFlightParams(flight_id=1011667820, timestamp=1758386815),
    response=<Response [200 OK]>
)
{
    "aircraft_info": {
        "icao_address": 7867035,
        "reg": "B-LRA",
        "type": "A359",
        "icon": "A330",
        "full_description": "Airbus A350-941",
        "images_list": [
            {
                "url": "https://www.jetphotos.com/photo/11806625",
                "copyright": "EthanLi",
                "thumbnail": "https://cdn.jetphotos.com/200/5/682006_1754851444_tb.jpg",
                "medium": "https://cdn.jetphotos.com/400/5/682006_1754851444.jpg",
                "large": "https://cdn.jetphotos.com/640/5/682006_1754851444.jpg",
            },
            {
                "url": "https://www.jetphotos.com/photo/11728089",
                "copyright": "Hypocrite",
                "thumbnail": "https://cdn.jetphotos.com/200/6/1954570_1747460006_tb.jpg",
                "medium": "https://cdn.jetphotos.com/400/6/1954570_1747460006.jpg",
                "large": "https://cdn.jetphotos.com/640/6/1954570_1747460006.jpg",
            },
            {
                "url": "https://www.jetphotos.com/photo/11721357",
                "copyright": "Steven-lzy",
                "thumbnail": "https://cdn.jetphotos.com/200/5/778073_1746782825_tb.jpg",
                "medium": "https://cdn.jetphotos.com/400/5/778073_1746782825.jpg",
                "large": "https://cdn.jetphotos.com/640/5/778073_1746782825.jpg",
            },
        ],
        "msn_available": True,
        "age_available": True,
        "registered_owners": "Cathay Pacific",
        "is_country_of_reg_available": True,
    },
    "schedule_info": {
        "flight_number": "CX170",
        "operated_by_id": 57,
        "painted_as_id": 57,
        "origin_id": 2730,
        "destination_id": 1366,
        "scheduled_departure": 1758384600,
        "scheduled_arrival": 1758412500,
        "actual_departure": 1758386815,
        "actual_arrival": 1758414073,
        "arr_terminal": "1",
        "baggage_belt": "14",
    },
    "flight_info": {
        "flightid": 1011667820,
        "lat": -31.94989,
        "lon": 115.962234,
        "track": 194,
        "speed": 168,
        "timestamp_ms": "1758386809081",
        "callsign": "CPA170",
        "ems_availability": {
            "qnh_availability": True,
            "amcp_availability": True,
            "mach_availability": True,
            "agps_availability": True,
            "agpsdiff_availability": True,
            "rs_availability": True,
        },
        "squawk_availability": True,
        "vspeed_availability": True,
        "airspace_availability": True,
        "server_time_ms": "1758466605103",
    },
    "flight_trail_list": [
        {
            "snapshot_id": "1758385543",
            "lat": -31.94054,
            "lon": 115.973206,
            "heading": 151,
        },
        ...
        {
            "snapshot_id": "1758415950",
            "lat": 22.31186,
            "lon": 113.92748,
            "spd": 1,
            "heading": 295,
        },
    ],
}
shape: (1, 24)
┌─────────────┬───────┬──────────┬─────────────┬───┬──────────┬────────┬─────────────┬─────────────┐
│ icao_addres ┆ reg   ┆ typecode ┆ flight_numb ┆ … ┆ callsign ┆ squawk ┆ ems         ┆ flight_trai │
│ s           ┆ ---   ┆ ---      ┆ er          ┆   ┆ ---      ┆ ---    ┆ ---         ┆ l_list      │
│ ---         ┆ str   ┆ str      ┆ ---         ┆   ┆ str      ┆ u16    ┆ struct[13]  ┆ ---         │
│ u32         ┆       ┆          ┆ str         ┆   ┆          ┆        ┆             ┆ list[struct │
│             ┆       ┆          ┆             ┆   ┆          ┆        ┆             ┆ [7]]        │
╞═════════════╪═══════╪══════════╪═════════════╪═══╪══════════╪════════╪═════════════╪═════════════╡
│ 7867035     ┆ B-LRA ┆ A359     ┆ CX758       ┆ … ┆ CPA758   ┆ 0      ┆ {0,0,0,0,0, ┆ [{174815111 │
│             ┆       ┆          ┆             ┆   ┆          ┆        ┆ 0,0,0,0,0,0 ┆ 3,1.341973, │
│             ┆       ┆          ┆             ┆   ┆          ┆        ┆ ,0,0}       ┆ 103.9865…   │
└─────────────┴───────┴──────────┴─────────────┴───┴──────────┴────────┴─────────────┴─────────────┘

Low Level API¤

For maximum control, you can also use fr24 in a procedural style. You will have to manage the headers, authentication yourself. It is highly recommended to use services instead.

Flight list¤

import httpx
from datetime import datetime

from fr24.authentication import login
from fr24.json import flight_list, flight_list_df, FlightListParams
from fr24.types.json import FlightList
from fr24.proto.headers import get_grpc_headers


async def my_list() -> FlightList:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        auth = await login(client)
        if auth is not None:
            print(auth.get("message"))
        response = await flight_list(
            client,
            FlightListParams(
                flight="AF291",
                timestamp=datetime.strptime("2025-01-16", "%Y-%m-%d"),  # (1)!
            ),
            headers=headers,
            auth=auth,
        )
        response.raise_for_status()
        list_ = response.json()
        return list_  # type: ignore


list_ = await my_list()
df = flight_list_df(list_)
df
  1. Replace it with the current time.
shape: (6, 15)
┌───────────┬────────┬──────────┬─────────┬───┬─────────────┬────────────┬────────────┬────────────┐
│ flight_id ┆ number ┆ callsign ┆ icao24  ┆ … ┆ ATOD        ┆ STOA       ┆ ETOA       ┆ ATOA       │
│ ---       ┆ ---    ┆ ---      ┆ ---     ┆   ┆ ---         ┆ ---        ┆ ---        ┆ ---        │
│ u64       ┆ str    ┆ str      ┆ u32     ┆   ┆ datetime[ms ┆ datetime[m ┆ datetime[m ┆ datetime[m │
│           ┆        ┆          ┆         ┆   ┆ , UTC]      ┆ s, UTC]    ┆ s, UTC]    ┆ s, UTC]    │
╞═══════════╪════════╪══════════╪═════════╪═══╪═════════════╪════════════╪════════════╪════════════╡
│ null      ┆ AF291  ┆ null     ┆ null    ┆ … ┆ null        ┆ 2025-01-24 ┆ null       ┆ null       │
│           ┆        ┆          ┆         ┆   ┆             ┆ 18:00:00   ┆            ┆            │
│           ┆        ┆          ┆         ┆   ┆             ┆ UTC        ┆            ┆            │
│ null      ┆ AF291  ┆ null     ┆ null    ┆ … ┆ null        ┆ 2025-01-22 ┆ null       ┆ null       │
│           ┆        ┆          ┆         ┆   ┆             ┆ 18:00:00   ┆            ┆            │
│           ┆        ┆          ┆         ┆   ┆             ┆ UTC        ┆            ┆            │
│ null      ┆ AF291  ┆ null     ┆ null    ┆ … ┆ null        ┆ 2025-01-19 ┆ null       ┆ null       │
│           ┆        ┆          ┆         ┆   ┆             ┆ 18:00:00   ┆            ┆            │
│           ┆        ┆          ┆         ┆   ┆             ┆ UTC        ┆            ┆            │
│ 952249857 ┆ AF291  ┆ AFR291   ┆ 3789477 ┆ … ┆ 2025-01-17  ┆ 2025-01-17 ┆ null       ┆ 2025-01-17 │
│           ┆        ┆          ┆         ┆   ┆ 05:13:55    ┆ 18:00:00   ┆            ┆ 19:30:15   │
│           ┆        ┆          ┆         ┆   ┆ UTC         ┆ UTC        ┆            ┆ UTC        │
│ 951756645 ┆ AF291  ┆ AFR291   ┆ 3789486 ┆ … ┆ 2025-01-15  ┆ 2025-01-15 ┆ null       ┆ 2025-01-15 │
│           ┆        ┆          ┆         ┆   ┆ 03:45:20    ┆ 18:00:00   ┆            ┆ 17:58:06   │
│           ┆        ┆          ┆         ┆   ┆ UTC         ┆ UTC        ┆            ┆ UTC        │
│ 951093039 ┆ AF291  ┆ AFR291   ┆ 3789475 ┆ … ┆ 2025-01-12  ┆ 2025-01-12 ┆ null       ┆ 2025-01-12 │
│           ┆        ┆          ┆         ┆   ┆ 05:15:13    ┆ 18:00:00   ┆            ┆ 19:03:13   │
│           ┆        ┆          ┆         ┆   ┆ UTC         ┆ UTC        ┆            ┆ UTC        │
└───────────┴────────┴──────────┴─────────┴───┴─────────────┴────────────┴────────────┴────────────┘

Playback¤

import httpx

from fr24.authentication import login
from fr24.json import playback, playback_df, PlaybackParams
from fr24.types.json import Playback
from fr24.proto.headers import get_grpc_headers


async def my_playback() -> Playback:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        auth = await login(client)
        if auth is not None:
            print(auth.get("message"))
        response = await playback(
            client,
            PlaybackParams(flight_id="38c59db3"),
            headers=headers,
            auth=auth,
        )
        response.raise_for_status()
        list_ = response.json()
        return list_  # type: ignore


list_ = await my_playback()
df = playback_df(list_)
df
shape: (203, 9)
┌────────────┬───────────┬────────────┬──────────┬───┬───────────────┬───────┬────────┬────────────┐
│ timestamp  ┆ latitude  ┆ longitude  ┆ altitude ┆ … ┆ vertical_spee ┆ track ┆ squawk ┆ ems        │
│ ---        ┆ ---       ┆ ---        ┆ ---      ┆   ┆ d             ┆ ---   ┆ ---    ┆ ---        │
│ u32        ┆ f32       ┆ f32        ┆ i32      ┆   ┆ ---           ┆ i16   ┆ u16    ┆ struct[18] │
│            ┆           ┆            ┆          ┆   ┆ i16           ┆       ┆        ┆            │
╞════════════╪═══════════╪════════════╪══════════╪═══╪═══════════════╪═══════╪════════╪════════════╡
│ 1737166526 ┆ 22.313072 ┆ 113.931381 ┆ 0        ┆ … ┆ 0             ┆ 317   ┆ 0      ┆ null       │
│ 1737166557 ┆ 22.312778 ┆ 113.931618 ┆ 0        ┆ … ┆ 0             ┆ 270   ┆ 0      ┆ null       │
│ 1737166584 ┆ 22.312763 ┆ 113.931953 ┆ 0        ┆ … ┆ 0             ┆ 250   ┆ 0      ┆ null       │
│ 1737166816 ┆ 22.312626 ┆ 113.931557 ┆ 0        ┆ … ┆ 0             ┆ 250   ┆ 3041   ┆ null       │
│ 1737166864 ┆ 22.312477 ┆ 113.931068 ┆ 0        ┆ … ┆ 0             ┆ 250   ┆ 3041   ┆ null       │
│ …          ┆ …         ┆ …          ┆ …        ┆ … ┆ …             ┆ …     ┆ …      ┆ …          │
│ 1737167965 ┆ 22.200348 ┆ 114.345802 ┆ 13500    ┆ … ┆ 3328          ┆ 142   ┆ 3041   ┆ null       │
│ 1737167997 ┆ 22.154388 ┆ 114.382454 ┆ 14850    ┆ … ┆ 1536          ┆ 143   ┆ 3041   ┆ null       │
│ 1737168028 ┆ 22.107239 ┆ 114.419304 ┆ 16050    ┆ … ┆ 2368          ┆ 143   ┆ 3041   ┆ null       │
│ 1737168060 ┆ 22.059942 ┆ 114.456535 ┆ 17200    ┆ … ┆ 2048          ┆ 143   ┆ 3041   ┆ null       │
│ 1737168092 ┆ 22.008501 ┆ 114.497017 ┆ 18350    ┆ … ┆ 2048          ┆ 143   ┆ 3041   ┆ null       │
└────────────┴───────────┴────────────┴──────────┴───┴───────────────┴───────┴────────┴────────────┘

Airport List¤

import httpx

from fr24.types.json import AirportList
from fr24.json import airport_list, AirportListParams
from fr24.proto.headers import get_grpc_headers

import polars as pl


async def my_arrivals() -> AirportList:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        response = await airport_list(
            client,
            AirportListParams(airport="tls", mode="arrivals"),
            headers=headers,
            auth=None,
        )
        response.raise_for_status()
        list_ = response.json()
        return list_  # type: ignore


airports = await my_arrivals()
arrivals = airports["result"]["response"]["airport"]["pluginData"]["schedule"][
    "arrivals"
]["data"]
assert arrivals is not None
df = pl.json_normalize(arrivals)
print(df)
shape: (10, 76)
┌───────────┬───────────┬───────────┬───────────┬───┬───────────┬───────────┬───────────┬──────────┐
│ flight.id ┆ flight.id ┆ flight.id ┆ flight.id ┆ … ┆ flight.ti ┆ flight.ai ┆ flight.ow ┆ flight.a │
│ entificat ┆ entificat ┆ entificat ┆ entificat ┆   ┆ me.other. ┆ rcraft.im ┆ ner       ┆ irline   │
│ ion.id    ┆ ion.row   ┆ ion.numbe ┆ ion.numbe ┆   ┆ duration  ┆ ages      ┆ ---       ┆ ---      │
│ ---       ┆ ---       ┆ r.d…      ┆ r.a…      ┆   ┆ ---       ┆ ---       ┆ null      ┆ null     │
│ str       ┆ i64       ┆ ---       ┆ ---       ┆   ┆ null      ┆ null      ┆           ┆          │
│           ┆           ┆ str       ┆ str       ┆   ┆           ┆           ┆           ┆          │
╞═══════════╪═══════════╪═══════════╪═══════════╪═══╪═══════════╪═══════════╪═══════════╪══════════╡
│ 3963916d  ┆ 563063588 ┆ AF6132    ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 1         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ null      ┆ 563365562 ┆ null      ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 4         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 39638d76  ┆ 563085809 ┆ T71527    ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 2         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 3963a803  ┆ 563063662 ┆ AF7408    ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 2         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 396399a4  ┆ 563087474 ┆ U24849    ┆ EC4849    ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 7         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ null      ┆ 563088423 ┆ V72371    ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 4         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 3963978d  ┆ 563085809 ┆ T73718    ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 1         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 3963ab98  ┆ 563089434 ┆ XK720     ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 8         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 396398ab  ┆ 563071223 ┆ FR3903    ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 6         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
│ 3963b61f  ┆ 563072081 ┆ GP155     ┆ null      ┆ … ┆ null      ┆ null      ┆ null      ┆ null     │
│           ┆ 9         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │
└───────────┴───────────┴───────────┴───────────┴───┴───────────┴───────────┴───────────┴──────────┘

Airport Search¤

from fr24.types.json import Find
from fr24.json import find, FindParams
from fr24.proto.headers import get_grpc_headers

import polars as pl
import httpx


async def my_find() -> Find:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        response = await find(
            client, FindParams(query="paris"), headers=headers, auth=None
        )
        response.raise_for_status()
        results = response.json()
        return results  # type: ignore


results = await my_find()
df = pl.json_normalize(results["results"])
print(df)
shape: (9, 7)
┌─────┬───────────────────────────────┬─────────┬──────────┬────────────┬────────────┬─────────────┐
│ id  ┆ label                         ┆ type    ┆ match    ┆ detail.lat ┆ detail.lon ┆ detail.size │
│ --- ┆ ---                           ┆ ---     ┆ ---      ┆ ---        ┆ ---        ┆ ---         │
│ str ┆ str                           ┆ str     ┆ str      ┆ f64        ┆ f64        ┆ i64         │
╞═════╪═══════════════════════════════╪═════════╪══════════╪════════════╪════════════╪═════════════╡
│ CDG ┆ Paris Charles de Gaulle       ┆ airport ┆ begins   ┆ 49.012516  ┆ 2.555752   ┆ 201280      │
│     ┆ Airpor…                       ┆         ┆          ┆            ┆            ┆             │
│ ORY ┆ Paris Orly Airport (ORY /     ┆ airport ┆ begins   ┆ 48.723331  ┆ 2.379444   ┆ 84510       │
│     ┆ LFPO…                         ┆         ┆          ┆            ┆            ┆             │
│ LBG ┆ Paris Le Bourget Airport (LBG ┆ airport ┆ begins   ┆ 48.958801  ┆ 2.4336     ┆ 24465       │
│     ┆ …                             ┆         ┆          ┆            ┆            ┆             │
│ BVA ┆ Paris Beauvais-Tille Airport  ┆ airport ┆ begins   ┆ 49.453465  ┆ 2.115138   ┆ 15939       │
│     ┆ (…                            ┆         ┆          ┆            ┆            ┆             │
│ VIY ┆ Paris Villacoublay Velizy Air ┆ airport ┆ begins   ┆ 48.774399  ┆ 2.20154    ┆ 1038        │
│     ┆ …                             ┆         ┆          ┆            ┆            ┆             │
│ PRX ┆ Paris Cox Field (PRX / KPRX)  ┆ airport ┆ begins   ┆ 33.636665  ┆ -95.450279 ┆ 953         │
│ XCR ┆ Paris Vatry Chalons Airport   ┆ airport ┆ begins   ┆ 48.759998  ┆ 4.2        ┆ 710         │
│     ┆ (X…                           ┆         ┆          ┆            ┆            ┆             │
│ PHT ┆ Paris Henry County Airport    ┆ airport ┆ begins   ┆ 36.336384  ┆ -88.38427  ┆ 199         │
│     ┆ (PH…                          ┆         ┆          ┆            ┆            ┆             │
│ OPL ┆ Opelousas St. Landry Parish   ┆ airport ┆ contains ┆ 30.555695  ┆ -92.098915 ┆ 194         │
│     ┆ Ai…                           ┆         ┆          ┆            ┆            ┆             │
└─────┴───────────────────────────────┴─────────┴──────────┴────────────┴────────────┴─────────────┘

Live feed¤

Demonstrates custom bounding boxes.

import httpx
from fr24.grpc import LiveFeedParams, BoundingBox, live_feed
from fr24.proto.v1_pb2 import LiveFeedResponse
from fr24.proto import parse_data
from fr24.proto.headers import get_grpc_headers


async def france_data() -> LiveFeedResponse:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        params = LiveFeedParams(
            bounding_box=BoundingBox(north=50, west=-7, south=40, east=10)
        )
        response = await live_feed(client, params, headers)
        result = parse_data(response.content, LiveFeedResponse)
        return result.unwrap()  # (1)!


data = await france_data()
data
  1. The type is a Result[LiveFeedResponse, ProtoError], calling the .unwrap() method raises an exception if there is an error.
flights_list {
  flightid: 941292228
  lat: 40.0058289
  lon: -5.02393532
  track: 225
  alt: 26800
  speed: 427
  icon: A320
  timestamp: 1732481230
  callsign: "IBS15MA"
  extra_info {
    flight: "IB1589"
    reg: "EC-OAS"
    route {
      from: "MAD"
      to: "TFN"
    }
    type: "A21N"
  }
  position_buffer {
    recent_positions_list {
      delta_lat: -418
      delta_lon: -562
      delta_ms: 3000
    }
...
      delta_lon: -1958
      delta_ms: 10000
    }
  }
}

In JSON format:

from google.protobuf.json_format import MessageToDict

MessageToDict(data)["flightsList"]
[{'flightid': 941292228,
  'lat': 40.00583,
  'lon': -5.0239353,
  'track': 225,
  'alt': 26800,
  'speed': 427,
  'icon': 'A320',
  'timestamp': 1732481230,
  'callsign': 'IBS15MA',
  'extraInfo': {'flight': 'IB1589',
   'reg': 'EC-OAS',
   'route': {'from': 'MAD', 'to': 'TFN'},
   'type': 'A21N'},
  'positionBuffer': {'recentPositionsList': [{'deltaLat': -418,
     'deltaLon': -562,
     'deltaMs': 3000}]}},
 {'flightid': 941277503,
  'lat': 40.050613,
  'lon': -6.7190137,
  'track': 24,
  'alt': 38000,
  'speed': 481,
  'icon': 'A320',
  'timestamp': 1732481230,
  'callsign': 'VOE2RY',
...
  'positionBuffer': {'recentPositionsList': [{'deltaLat': 315,
     'deltaLon': -660,
     'deltaMs': 3000},
    {'deltaLat': 553, 'deltaLon': -1170, 'deltaMs': 6000},
    {'deltaLat': 929, 'deltaLon': -1958, 'deltaMs': 10000}]}}]

Nearest Flights¤

import httpx
from fr24.grpc import nearest_flights
from fr24.proto.v1_pb2 import (
    NearestFlightsResponse,
    NearestFlightsRequest,
    Geolocation,
)
from fr24.proto import parse_data
from fr24.proto.headers import get_grpc_headers


async def nearest_flights_data() -> NearestFlightsResponse:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        message = NearestFlightsRequest(
            location=Geolocation(lat=22.31257, lon=113.92708),
            radius=1000,
            limit=1500,
        )
        response = await nearest_flights(client, message, headers)
        return parse_data(response.content, NearestFlightsResponse).unwrap()


data = await nearest_flights_data()
data
flights_list {
  flight {
    flightid: 905701578
    lat: 22.3095245
    lon: 113.930717
    track: 78
    speed: 9
    timestamp: 1720071634
    on_ground: true
    callsign: "CES502"
    extra_info {
      flight: "MU502"
      reg: "B-1908"
      route {
        from: "HKG"
        to: "PVG"
      }
      type: "B738"
      logo_id: 131
    }
  }
  distance: 504
}
flights_list {
  flight {
...
      logo_id: 335
    }
  }
  distance: 783
}

Live Flight Status¤

import httpx
from fr24.grpc import live_flights_status
from fr24.proto.v1_pb2 import (
    LiveFlightsStatusRequest,
    LiveFlightsStatusResponse,
)
from fr24.proto import parse_data
from fr24.proto.headers import get_grpc_headers


async def live_flights_status_data() -> LiveFlightsStatusResponse:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        message = LiveFlightsStatusRequest(
            flight_ids_list=[0x35FBC363, 0x35FBF180]
        )
        response = await live_flights_status(client, message, headers)
        return parse_data(response.content, LiveFlightsStatusResponse).unwrap()


data = await live_flights_status_data()
data
flights_map {
  flight_id: 905703808
  data {
    lat: 21.7237415
    lon: 114.917908
    status: LIVE
  }
}
flights_map {
  flight_id: 905692003
  data {
    lat: 21.9285736
    lon: 113.912445
    status: LIVE
  }
}

Search Index¤

Unstable API: returns empty DATA frame

import httpx
from fr24.grpc import search_index
from fr24.proto.v1_pb2 import FetchSearchIndexRequest, FetchSearchIndexResponse
from fr24.proto import parse_data
from fr24.proto.headers import get_grpc_headers


async def search_index_data() -> FetchSearchIndexResponse:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        message = FetchSearchIndexRequest()
        response = await search_index(client, message, headers)
        return parse_data(response.content, FetchSearchIndexResponse).unwrap()


data = await search_index_data()
data
GrpcError('empty DATA frame')

Follow Flight¤

See above for more information.

import httpx
from fr24.grpc import follow_flight_stream
from fr24.proto.v1_pb2 import FollowFlightRequest, FollowFlightResponse
from fr24.proto import parse_data
from fr24.proto.headers import get_grpc_headers


async def follow_flight_data() -> None:
    timeout = httpx.Timeout(5, read=120)
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient(timeout=timeout) as client:
        message = FollowFlightRequest(flight_id=0x3C500FDB)
        i = 0
        async for response in follow_flight_stream(client, message, headers):
            print(f"##### {i} #####")
            print(parse_data(response, FollowFlightResponse))
            i += 1
            if i > 3:
                break


await follow_flight_data()
##### 0 #####
Ok(_value=aircraft_info {
  icao_address: 7866977
  reg: "B-KQM"
  type: "B77W"
  icon: B777
  full_description: "Boeing 777-367(ER)"
  images_list {
    url: "https://www.jetphotos.com/photo/11825817"
    copyright: "ZSHC_Linzx"
    thumbnail: "https://cdn.jetphotos.com/200/5/1291679_1756473618_tb.jpg"
    medium: "https://cdn.jetphotos.com/400/5/1291679_1756473618.jpg"
    large: "https://cdn.jetphotos.com/640/5/1291679_1756473618.jpg"
  }
  images_list {
    url: "https://www.jetphotos.com/photo/11813969"
    copyright: "CAN-Eric"
    thumbnail: "https://cdn.jetphotos.com/200/5/967682_1755532162_tb.jpg"
    medium: "https://cdn.jetphotos.com/400/5/967682_1755532162.jpg"
    large: "https://cdn.jetphotos.com/640/5/967682_1755532162.jpg"
  }
  images_list {
    url: "https://www.jetphotos.com/photo/11803561"
    copyright: "cc12214"
    thumbnail: "https://cdn.jetphotos.com/200/6/585221_1754572527_tb.jpg"
    medium: "https://cdn.jetphotos.com/400/6/585221_1754572527.jpg"
    large: "https://cdn.jetphotos.com/640/6/585221_1754572527.jpg"
  }
  msn_available: true
  age_available: true
  registered_owners: "Cathay Pacific (Oneworld Livery)"
  is_country_of_reg_available: true
}
schedule_info {
  flight_number: "CX251"
  operated_by_id: 57
  painted_as_id: 57
  origin_id: 1366
  destination_id: 1942
  scheduled_departure: 1758465600
  scheduled_arrival: 1758516000
  actual_departure: 1758466901
  arr_terminal: "3"
}
flight_progress {
  traversed_distance: 21783
  remaining_distance: 9668300
  elapsed_time: 295
  remaining_time: 51569
  eta: 1758518765
  great_circle_distance: 9647791
  mean_flight_time: 48161
  flight_stage: ASCENDING
  delay_status: RED
}
flight_info {
  flightid: 1011879899
  lat: 22.1949
  lon: 114.087921
  track: 169
  alt: 7525
  speed: 303
  timestamp_ms: 1758467194561
  callsign: "CPA251"
  ems_availability {
    qnh_availability: true
    amcp_availability: true
    oat_availability: true
    ias_availability: true
    tas_availability: true
    mach_availability: true
    agps_availability: true
    agpsdiff_availability: true
    wind_dir_availability: true
    wind_speed_availability: true
    rs_availability: true
  }
  squawk_availability: true
  vspeed_availability: true
  airspace_availability: true
  server_time_ms: 1758467196527
}
flight_trail_list {
  snapshot_id: 1758465991
  lat: 22.3132782
  lon: 113.934616
  heading: 70
}
flight_trail_list {
  snapshot_id: 1758466089
  lat: 22.3131981
  lon: 113.934303
  spd: 2
  heading: 70
}
...
flight_trail_list {
  snapshot_id: 1758467188
  lat: 22.2043304
  lon: 114.086678
  altitude: 7450
  spd: 300
  heading: 179
}
position_buffer {
  recent_positions_list {
    delta_lat: -155
    delta_lon: 34
    delta_ms: 1090
  }
  recent_positions_list {
    delta_lat: -517
    delta_lon: 94
    delta_ms: 3710
  }
  recent_positions_list {
    delta_lat: -746
    delta_lon: 119
    delta_ms: 5270
  }
  recent_positions_list {
    delta_lat: -942
    delta_lon: 124
    delta_ms: 6700
  }
  recent_positions_list {
    delta_lat: -1107
    delta_lon: 129
    delta_ms: 7870
  }
  recent_positions_list {
    delta_lat: -1364
    delta_lon: 129
    delta_ms: 9710
  }
  recent_positions_list {
    delta_lat: -1597
    delta_lon: 129
    delta_ms: 11380
  }
}
)
##### 1 #####
Ok(_value=schedule_info {
  flight_number: "CX251"
  operated_by_id: 57
  painted_as_id: 57
  origin_id: 1366
  destination_id: 1942
  scheduled_departure: 1758465600
  scheduled_arrival: 1758516000
  actual_departure: 1758466901
  arr_terminal: "3"
}
flight_progress {
  traversed_distance: 21940
  remaining_distance: 9668494
  elapsed_time: 298
  remaining_time: 51566
  eta: 1758518765
  great_circle_distance: 9647791
  mean_flight_time: 48161
  flight_stage: ASCENDING
  delay_status: RED
}
flight_info {
  flightid: 1011879899
  lat: 22.1930809
  lon: 114.088387
  track: 167
  alt: 7550
  speed: 303
  timestamp_ms: 1758467195921
  callsign: "CPA251"
  ems_availability {
    qnh_availability: true
    amcp_availability: true
    oat_availability: true
    ias_availability: true
    tas_availability: true
    mach_availability: true
    agps_availability: true
    agpsdiff_availability: true
    wind_dir_availability: true
    wind_speed_availability: true
    rs_availability: true
  }
  squawk_availability: true
  vspeed_availability: true
  airspace_availability: true
  server_time_ms: 1758467199530
}
)
##### 2 #####
Ok(_value=schedule_info {
  flight_number: "CX251"
  operated_by_id: 57
  painted_as_id: 57
  origin_id: 1366
  destination_id: 1942
  scheduled_departure: 1758465600
  scheduled_arrival: 1758516000
  actual_departure: 1758466901
  arr_terminal: "3"
}
flight_progress {
  traversed_distance: 22437
  remaining_distance: 9669070
  elapsed_time: 301
  remaining_time: 51563
  eta: 1758518765
  great_circle_distance: 9647791
  mean_flight_time: 48161
  flight_stage: ASCENDING
  delay_status: RED
}
flight_info {
  flightid: 1011879899
  lat: 22.1880341
  lon: 114.09037
  track: 158
  alt: 7600
  speed: 305
  timestamp_ms: 1758467199681
  callsign: "CPA251"
  ems_availability {
    qnh_availability: true
    amcp_availability: true
    oat_availability: true
    ias_availability: true
    tas_availability: true
    mach_availability: true
    agps_availability: true
    agpsdiff_availability: true
    wind_dir_availability: true
    wind_speed_availability: true
    rs_availability: true
  }
  squawk_availability: true
  vspeed_availability: true
  airspace_availability: true
  server_time_ms: 1758467202532
}
)
##### 3 #####
Ok(_value=schedule_info {
  flight_number: "CX251"
  operated_by_id: 57
  painted_as_id: 57
  origin_id: 1366
  destination_id: 1942
  scheduled_departure: 1758465600
  scheduled_arrival: 1758516000
  actual_departure: 1758466901
  arr_terminal: "3"
}
flight_progress {
  traversed_distance: 22657
  remaining_distance: 9669316
  elapsed_time: 304
  remaining_time: 51560
  eta: 1758518765
  great_circle_distance: 9647791
  mean_flight_time: 48161
  flight_stage: ASCENDING
  delay_status: RED
}
flight_info {
  flightid: 1011879899
  lat: 22.1859741
  lon: 114.09137
  track: 154
  alt: 7625
  speed: 305
  timestamp_ms: 1758467201271
  callsign: "CPA251"
  ems_availability {
    qnh_availability: true
    amcp_availability: true
    oat_availability: true
    ias_availability: true
    tas_availability: true
    mach_availability: true
    agps_availability: true
    agpsdiff_availability: true
    wind_dir_availability: true
    wind_speed_availability: true
    rs_availability: true
  }
  squawk_availability: true
  vspeed_availability: true
  airspace_availability: true
  server_time_ms: 1758467205534
}
)

Top Flights¤

import httpx
from fr24.grpc import top_flights
from fr24.proto.v1_pb2 import TopFlightsRequest, TopFlightsResponse
from fr24.proto import parse_data
from fr24.proto.headers import get_grpc_headers


async def top_flights_data() -> TopFlightsResponse:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        message = TopFlightsRequest(limit=10)
        response = await top_flights(client, message, headers)
        return parse_data(response.content, TopFlightsResponse).unwrap()


data = await top_flights_data()
data
scoreboard_list {
  flight_id: 911336284
  live_clicks: 1648
  total_clicks: 6664
  callsign: "LEE92"
  from_iata: "QKG"
  from_city: "Leeming"
  type: "HUNT"
  full_description: "Hawker Hunter T2"
}
scoreboard_list {
  flight_id: 911326556
  live_clicks: 1144
  total_clicks: 8848
  callsign: "SARAB"
  type: "HAWK"
  full_description: "British Aerospace Hawk Mk167"
}
scoreboard_list {
  flight_id: 911338539
  live_clicks: 904
  total_clicks: 1764
  flight_number: "TN80001"
  callsign: "TN080001"
  from_iata: "QCY"
...
  to_iata: "RMQ"
  to_city: "Taichung"
  type: "B738"
  full_description: "Boeing 737-8AL"
}

Live Trail¤

Unstable API: returns empty DATA frame as of Sep 2024

import httpx
from fr24.grpc import live_trail
from fr24.proto.v1_pb2 import LiveTrailRequest, LiveTrailResponse
from fr24.proto import parse_data
from fr24.proto.headers import get_grpc_headers


async def live_trail_data() -> LiveTrailResponse:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        message = LiveTrailRequest(flight_id=0x395C43CF)
        response = await live_trail(client, message, headers)
        return parse_data(response.content, LiveTrailResponse).unwrap()


data = await live_trail_data()
data
radar_records_list {
  timestamp: 1720064455
  lat: 30.2406578
  lon: 120.420403
  spd: 15
  heading: 61
  callsign: "CPA959"
}
radar_records_list {
  timestamp: 1720064462
  lat: 30.2408924
  lon: 120.420937
  heading: 61
  callsign: "CPA959"
}
radar_records_list {
  timestamp: 1720064480
  lat: 30.2415791
  lon: 120.422478
  spd: 18
  heading: 61
  callsign: "CPA959"
}
radar_records_list {
  timestamp: 1720064488
...
  heading: 269
  vspd: -960
  squawk: 13874
  callsign: "CPA959"
}
...

Historic Trail¤

Unstable API: gateway timeout

import httpx
from fr24.grpc import historic_trail
from fr24.proto.v1_pb2 import HistoricTrailRequest, HistoricTrailResponse
from fr24.proto import parse_data
from fr24.proto.headers import get_grpc_headers


async def historic_trail_data() -> HistoricTrailResponse:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        message = HistoricTrailRequest(flight_id=0x395C43CF)
        response = await historic_trail(client, message, headers)
        return parse_data(response.content, HistoricTrailResponse).unwrap()


data = await historic_trail_data()
data
504 GATEWAY TIMEOUT

Flight Details¤

import httpx
from fr24.grpc import FlightDetailsParams, flight_details
from fr24.proto.v1_pb2 import FlightDetailsResponse
from fr24.proto import parse_data
from fr24.proto.headers import get_grpc_headers


async def flight_details_data() -> FlightDetailsResponse:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        params = FlightDetailsParams(flight_id=0x3C500FDB)
        response = await flight_details(client, params, headers)
        return parse_data(response.content, FlightDetailsResponse).unwrap()


data = await flight_details_data()
data
aircraft_info {
  icao_address: 7866977
  reg: "B-KQM"
  type: "B77W"
  icon: B777
  full_description: "Boeing 777-367(ER)"
  images_list {
    url: "https://www.jetphotos.com/photo/11825817"
    copyright: "ZSHC_Linzx"
    thumbnail: "https://cdn.jetphotos.com/200/5/1291679_1756473618_tb.jpg"
    medium: "https://cdn.jetphotos.com/400/5/1291679_1756473618.jpg"
    large: "https://cdn.jetphotos.com/640/5/1291679_1756473618.jpg"
  }
  images_list {
    url: "https://www.jetphotos.com/photo/11813969"
    copyright: "CAN-Eric"
    thumbnail: "https://cdn.jetphotos.com/200/5/967682_1755532162_tb.jpg"
    medium: "https://cdn.jetphotos.com/400/5/967682_1755532162.jpg"
    large: "https://cdn.jetphotos.com/640/5/967682_1755532162.jpg"
  }
  images_list {
    url: "https://www.jetphotos.com/photo/11803561"
    copyright: "cc12214"
    thumbnail: "https://cdn.jetphotos.com/200/6/585221_1754572527_tb.jpg"
    medium: "https://cdn.jetphotos.com/400/6/585221_1754572527.jpg"
    large: "https://cdn.jetphotos.com/640/6/585221_1754572527.jpg"
  }
  msn_available: true
  age_available: true
  registered_owners: "Cathay Pacific (Oneworld Livery)"
  is_country_of_reg_available: true
}
schedule_info {
  flight_number: "CX251"
  operated_by_id: 57
  painted_as_id: 57
  origin_id: 1366
  destination_id: 1942
  scheduled_departure: 1758465600
  scheduled_arrival: 1758516000
  actual_departure: 1758466901
  arr_terminal: "3"
}
flight_progress {
  traversed_distance: 13728
  remaining_distance: 9652855
  elapsed_time: 156
  remaining_time: 51708
  eta: 1758518765
  great_circle_distance: 9647791
  mean_flight_time: 48161
  flight_stage: ASCENDING
  delay_status: RED
}
flight_info {
  flightid: 1011879899
  lat: 22.3374939
  lon: 114.046074
  track: 99
  alt: 4975
  speed: 205
  timestamp_ms: 1758467055960
  callsign: "CPA251"
  ems_availability {
    qnh_availability: true
    amcp_availability: true
    oat_availability: true
    ias_availability: true
    tas_availability: true
    mach_availability: true
    agps_availability: true
    agpsdiff_availability: true
    wind_dir_availability: true
    wind_speed_availability: true
    rs_availability: true
  }
  squawk_availability: true
  vspeed_availability: true
  airspace_availability: true
  server_time_ms: 1758467057331
}
flight_plan {
}
flight_trail_list {
  snapshot_id: 1758465991
  lat: 22.3132782
  lon: 113.934616
  heading: 70
}
...
flight_trail_list {
  snapshot_id: 1758467049
  lat: 22.3383179
  lon: 114.039337
  altitude: 4800
  spd: 206
  heading: 91
}
position_buffer {
  recent_positions_list {
    delta_lat: -45
    delta_lon: 274
    delta_ms: 2710
  }
  recent_positions_list {
    delta_lat: -50
    delta_lon: 324
    delta_ms: 3180
  }
  recent_positions_list {
    delta_lat: -78
    delta_lon: 585
    delta_ms: 5720
  }
  recent_positions_list {
    delta_lat: -86
    delta_lon: 778
    delta_ms: 7570
  }
  recent_positions_list {
    delta_lat: -92
    delta_lon: 976
    delta_ms: 9540
  }
  recent_positions_list {
    delta_lat: -91
    delta_lon: 1073
    delta_ms: 10500
  }
}

Playback Flight¤

import httpx
from fr24.grpc import PlaybackFlightParams, playback_flight
from fr24.proto.v1_pb2 import PlaybackFlightResponse
from fr24.proto import parse_data
from fr24.proto.headers import get_grpc_headers


async def playback_flight_data() -> PlaybackFlightResponse:
    headers = httpx.Headers(get_grpc_headers(auth=None))
    async with httpx.AsyncClient() as client:
        message = PlaybackFlightParams(
            flight_id=0x3C500FDB, timestamp=1758467125
        )
        response = await playback_flight(client, message, headers)
        return parse_data(response.content, PlaybackFlightResponse).unwrap()


data = await playback_flight_data()
data
aircraft_info {
  icao_address: 7866977
  reg: "B-KQM"
  type: "B77W"
  icon: B777
  full_description: "Boeing 777-367(ER)"
  images_list {
    url: "https://www.jetphotos.com/photo/11825817"
    copyright: "ZSHC_Linzx"
    thumbnail: "https://cdn.jetphotos.com/200/5/1291679_1756473618_tb.jpg"
    medium: "https://cdn.jetphotos.com/400/5/1291679_1756473618.jpg"
    large: "https://cdn.jetphotos.com/640/5/1291679_1756473618.jpg"
  }
  images_list {
    url: "https://www.jetphotos.com/photo/11813969"
    copyright: "CAN-Eric"
    thumbnail: "https://cdn.jetphotos.com/200/5/967682_1755532162_tb.jpg"
    medium: "https://cdn.jetphotos.com/400/5/967682_1755532162.jpg"
    large: "https://cdn.jetphotos.com/640/5/967682_1755532162.jpg"
  }
  images_list {
    url: "https://www.jetphotos.com/photo/11803561"
    copyright: "cc12214"
    thumbnail: "https://cdn.jetphotos.com/200/6/585221_1754572527_tb.jpg"
    medium: "https://cdn.jetphotos.com/400/6/585221_1754572527.jpg"
    large: "https://cdn.jetphotos.com/640/6/585221_1754572527.jpg"
  }
  msn_available: true
  age_available: true
  registered_owners: "Cathay Pacific (Oneworld Livery)"
  is_country_of_reg_available: true
}
schedule_info {
  flight_number: "CX251"
  operated_by_id: 57
  painted_as_id: 57
  origin_id: 1366
  destination_id: 1942
  scheduled_departure: 1758465600
  scheduled_arrival: 1758516000
  actual_departure: 1758466901
  arr_terminal: "3"
}
flight_info {
  flightid: 1011879899
  lat: 22.2923298
  lon: 114.087372
  track: 173
  alt: 6325
  speed: 242
  timestamp_ms: 1758467118710
  callsign: "CPA251"
  ems_availability {
    qnh_availability: true
    amcp_availability: true
    oat_availability: true
    ias_availability: true
    tas_availability: true
    mach_availability: true
    agps_availability: true
    agpsdiff_availability: true
    wind_dir_availability: true
    wind_speed_availability: true
    rs_availability: true
  }
  squawk_availability: true
  vspeed_availability: true
  airspace_availability: true
  server_time_ms: 1758467148386
}
flight_trail_list {
  snapshot_id: 1758465991
  lat: 22.3132782
  lon: 113.934616
  heading: 70
}
...
flight_trail_list {
  snapshot_id: 1758467147
  lat: 22.2578888
  lon: 114.087273
  altitude: 6800
  spd: 267
  heading: 180
}
"""