Overview¤
| Name | Low-level API | Service and Cache Location |
|---|---|---|
| Flight List JSON |
flight_listflight_list_df |
FlightListServiceCache Location: flight_list/└── reg/└── {reg.upper()}.parquet└── flight_list/└── {iata_flight_num.upper()}.parquet |
| Playback JSON |
playbackplayback_df |
PlaybackServiceCache Location: playback/└── {fr24_hex_id.upper()}.parquet |
| Live Feed gRPC |
live_feedlive_feed_df |
LiveFeedServiceCache Location: feed/└── {timestamp_s}.parquet |
| Live Feed Playback gRPC |
live_feed_playbacklive_feed_df |
LiveFeedPlaybackServiceCache Location: feed/└── {timestamp_s}.parquet |
| Airport List JSON |
airport_list |
AirportListService |
| Airport Search JSON |
find |
FindService |
| Nearest Flights gRPC |
nearest_flights |
NearestFlightsServiceCache Location: nearest_flights/└── {lon_x1e6}_{lat_x1e6}_{timestamp_s}.parquet |
| Live Flight Status gRPC |
live_flights_status |
LiveFlightsStatusServiceCache Location: live_flights_status/└── {timestamp_s}.parquet |
gRPC |
search_index |
- |
| Follow Flight gRPC |
follow_flight_stream |
FollowFlightService |
| Top Flights gRPC |
top_flights |
TopFlightsServiceCache Location: top_flights/└── {timestamp_s}.parquet |
gRPC |
live_trail |
- |
gRPC |
historic_trail |
- |
| Flight Details gRPC |
flight_details |
FlightDetailsServiceCache Location: flight_details/└── {flight_id}_{timestamp_s}.parquet |
| Playback Flight gRPC |
playback_flight |
PlaybackFlightServiceCache Location: playback_flight/└── {flight_id}_{timestamp_s}.parquet |
You can find even more usage examples under tests/.
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")
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[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 │
│ 951575574 ┆ CX372 ┆ CPA372 ┆ 7867035 ┆ … ┆ 2025-01-14 ┆ 2025-01-14 ┆ null ┆ 2025-01-14 │
│ ┆ ┆ ┆ ┆ ┆ 10:48:22 ┆ 22:55:00 ┆ ┆ 23:04:26 │
│ ┆ ┆ ┆ ┆ ┆ UTC ┆ UTC ┆ ┆ UTC │
│ 951418869 ┆ CX315 ┆ CPA315 ┆ 7867035 ┆ … ┆ 2025-01-13 ┆ 2025-01-14 ┆ null ┆ 2025-01-14 │
│ ┆ ┆ ┆ ┆ ┆ 17:21:14 ┆ 07:30:00 ┆ ┆ 07:00:28 │
│ ┆ ┆ ┆ ┆ ┆ 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 │
└───────────┴────────┴──────────┴─────────┴───┴─────────────┴────────────┴────────────┴────────────┘
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()
- Create a new result collections, a list under the hood.
- Appends the current flight list to the collection. Note that it does not remove duplicates.
- 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()
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()
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 ┆ ┆ ┆ ┆ ┆ ┆ ┆ │
└───────────┴───────────┴───────────┴───────────┴───┴───────────┴───────────┴───────────┴──────────┘
Airport Search¤
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: 5031041
type: "B744"
icon: B747
full_description: "Boeing 747-48EF"
service: CARGO
images_list {
url: "https://www.jetphotos.com/photo/11372499"
copyright: "R Skywalker"
thumbnail: "https://cdn.jetphotos.com/200/5/609890_1717848712_tb.jpg"
medium: "https://cdn.jetphotos.com/400/5/609890_1717848712.jpg"
large: "https://cdn.jetphotos.com/640/5/609890_1717848712.jpg"
}
images_list {
url: "https://www.jetphotos.com/photo/11358154"
copyright: "Tim-Patrick Müller"
thumbnail: "https://cdn.jetphotos.com/200/5/1615840_1716633484_tb.jpg"
medium: "https://cdn.jetphotos.com/400/5/1615840_1716633484.jpg"
large: "https://cdn.jetphotos.com/640/5/1615840_1716633484.jpg"
}
images_list {
url: "https://www.jetphotos.com/photo/11337719"
copyright: "Siegi N."
thumbnail: "https://cdn.jetphotos.com/200/6/417379_1714816605_tb.jpg"
medium: "https://cdn.jetphotos.com/400/6/417379_1714816605.jpg"
large: "https://cdn.jetphotos.com/640/6/417379_1714816605.jpg"
}
msn_available: true
age_available: true
registered_owners: "Network Aviation"
}
flight_plan {
}
schedule_info {
flight_number: "CC4400"
operated_by_id: 437
origin_id: 1366
actual_departure: 1720074023
}
flight_progress {
elapsed_time: 1611
}
flight_info {
flightid: 905705829
lat: 21.2512665
lon: 112.568764
track: 278
alt: 31000
speed: 512
timestamp: 1720075629
callsign: "ABD4400"
ems_availability {
amcp_availability: true
oat_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
vspeed_availability: true
airspace_availability: true
}
flight_trail_list {
snapshot_id: 1720073072
lat: 22.3014889
lon: 113.923706
heading: 340
}
flight_trail_list {
snapshot_id: 1720073114
lat: 22.3012848
lon: 113.92379
spd: 3
heading: 340
}
...
altitude: 31000
spd: 512
heading: 278
}
##### 1 #####
schedule_info {
flight_number: "CC4400"
operated_by_id: 437
origin_id: 1366
actual_departure: 1720074023
}
flight_progress {
elapsed_time: 1615
}
flight_info {
flightid: 905705829
lat: 21.2530975
lon: 112.555733
track: 278
alt: 31000
speed: 512
timestamp: 1720075634
callsign: "ABD4400"
ems_availability {
amcp_availability: true
oat_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
vspeed_availability: true
airspace_availability: true
}
##### 2 #####
schedule_info {
flight_number: "CC4400"
operated_by_id: 437
origin_id: 1366
actual_departure: 1720074023
}
flight_progress {
elapsed_time: 1619
}
flight_info {
flightid: 905705829
lat: 21.2530975
lon: 112.555733
track: 278
alt: 31000
speed: 512
timestamp: 1720075634
callsign: "ABD4400"
ems_availability {
amcp_availability: true
oat_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
vspeed_availability: true
airspace_availability: true
}
##### 3 #####
schedule_info {
flight_number: "CC4400"
operated_by_id: 437
origin_id: 1366
actual_departure: 1720074023
}
flight_progress {
elapsed_time: 1623
}
flight_info {
flightid: 905705829
lat: 21.2557068
lon: 112.537407
track: 278
alt: 31000
speed: 512
timestamp: 1720075641
callsign: "ABD4400"
...
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=981435745, restriction_mode=0, verbose=True),
response=<Response [200 OK]>,
timestamp=1748198596
)
{
'aircraft_info': {
'icao_address': 7901836,
'reg': 'B-LPR',
'type': 'A321',
'icon': 'A320',
'full_description': 'Airbus A321-231',
'images_list': [
{
'url': 'https://www.jetphotos.com/photo/11710285',
'copyright': 'Hayashi_008',
'thumbnail': 'https://cdn.jetphotos.com/200/5/1052205_1745736486_tb.jpg',
'medium': 'https://cdn.jetphotos.com/400/5/1052205_1745736486.jpg',
'large': 'https://cdn.jetphotos.com/640/5/1052205_1745736486.jpg'
},
{
'url': 'https://www.jetphotos.com/photo/11710266',
'copyright': 'Jhang yao yun',
'thumbnail': 'https://cdn.jetphotos.com/200/6/430972_1745733519_tb.jpg',
'medium': 'https://cdn.jetphotos.com/400/6/430972_1745733519.jpg',
'large': 'https://cdn.jetphotos.com/640/6/430972_1745733519.jpg'
},
{
'url': 'https://www.jetphotos.com/photo/11701103',
'copyright': 'verduyn',
'thumbnail': 'https://cdn.jetphotos.com/200/6/862976_1744865774_tb.jpg',
'medium': 'https://cdn.jetphotos.com/400/6/862976_1744865774.jpg',
'large': 'https://cdn.jetphotos.com/640/6/862976_1744865774.jpg'
}
],
'msn_available': True,
'age_available': True,
'registered_owners': 'Hong Kong Airlines',
'is_country_of_reg_available': True
},
'schedule_info': {
'flight_number': 'HX606',
'operated_by_id': 641,
'painted_as_id': 641,
'origin_id': 1366,
'destination_id': 2505,
'scheduled_departure': 1748198100,
'scheduled_arrival': 1748215200,
'arr_terminal': '1'
},
'flight_progress': {
'traversed_distance': 2389,
'remaining_distance': 2964062,
'great_circle_distance': 2963825,
'mean_flight_time': 13490,
'flight_stage': 'ON_GROUND'
},
'flight_info': {
'flightid': 981435745,
'lat': 22.325708,
'lon': 113.90078,
'track': 250,
'speed': 14,
'timestamp_ms': '1748198593883',
'on_ground': True,
'callsign': 'CRK606',
'ems_availability': {},
'squawk_availability': True,
'airspace_availability': True,
'server_time_ms': '1748198596450'
},
'flight_plan': {},
'flight_trail_list': [
{'snapshot_id': '1748197476', 'lat': 22.30672, 'lon': 113.9181, 'heading': 180},
...
{'snapshot_id': '1748198570', 'lat': 22.32614, 'lon': 113.90211, 'spd': 9, 'heading': 247},
{'snapshot_id': '1748198575', 'lat': 22.32605, 'lon': 113.901855, 'spd': 10, 'heading': 250}
]
}
shape: (1, 31)
┌─────────────┬───────┬──────────┬─────────────┬───┬──────────┬────────┬─────────────┬─────────────┐
│ 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]] │
╞═════════════╪═══════╪══════════╪═════════════╪═══╪══════════╪════════╪═════════════╪═════════════╡
│ 7901836 ┆ B-LPR ┆ A321 ┆ HX606 ┆ … ┆ CRK606 ┆ 0 ┆ {0,0,0,0,0, ┆ [{174819747 │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 0,0,0,0,0,0 ┆ 6,22.306721 │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ,0,0} ┆ ,113.918… │
└─────────────┴───────┴──────────┴─────────────┴───┴──────────┴────────┴─────────────┴─────────────┘
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=981308334, timestamp=1748151914),
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/11633658',
'copyright': 'lix1aolu',
'thumbnail': 'https://cdn.jetphotos.com/200/6/850117_1739185739_tb.jpg',
'medium': 'https://cdn.jetphotos.com/400/6/850117_1739185739.jpg',
'large': 'https://cdn.jetphotos.com/640/6/850117_1739185739.jpg'
},
{
'url': 'https://www.jetphotos.com/photo/11634217',
'copyright': 'Waibibabu',
'thumbnail': 'https://cdn.jetphotos.com/200/6/591483_1739217827_tb.jpg',
'medium': 'https://cdn.jetphotos.com/400/6/591483_1739217827.jpg',
'large': 'https://cdn.jetphotos.com/640/6/591483_1739217827.jpg'
},
{
'url': 'https://www.jetphotos.com/photo/11620028',
'copyright': 'ZBAA cao',
'thumbnail': 'https://cdn.jetphotos.com/200/6/723478_1737987561_tb.jpg',
'medium': 'https://cdn.jetphotos.com/400/6/723478_1737987561.jpg',
'large': 'https://cdn.jetphotos.com/640/6/723478_1737987561.jpg'
}
],
'msn_available': True,
'age_available': True,
'registered_owners': 'Cathay Pacific',
'is_country_of_reg_available': True
},
'schedule_info': {
'flight_number': 'CX758',
'operated_by_id': 57,
'painted_as_id': 57,
'origin_id': 3182,
'destination_id': 1366,
'scheduled_departure': 1748150700,
'scheduled_arrival': 1748165700,
'actual_departure': 1748151914,
'actual_arrival': 1748164743,
'arr_terminal': '1',
'baggage_belt': '5'
},
'flight_info': {
'flightid': 981308334,
'lat': 1.3314638,
'lon': 103.986115,
'track': 22,
'speed': 55,
'timestamp_ms': '1748151902672',
'on_ground': True,
'callsign': 'CPA758',
'ems_availability': {},
'squawk_availability': True,
'vspeed_availability': True,
'airspace_availability': True,
'server_time_ms': '1748202193168'
},
'flight_trail_list': [
{'snapshot_id': '1748151113', 'lat': 1.341973, 'lon': 103.98659, 'heading': 202},
{'snapshot_id': '1748151183', 'lat': 1.342232, 'lon': 103.98668, 'heading': 208},
...
{'snapshot_id': '1748165435', 'lat': 22.314384, 'lon': 113.92283, 'spd': 3, 'heading': 42}
]
}
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
- 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
- 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=0x395C43CF)
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 #####
aircraft_info {
icao_address: 5031041
type: "B744"
icon: B747
full_description: "Boeing 747-48EF"
service: CARGO
images_list {
url: "https://www.jetphotos.com/photo/11372499"
copyright: "R Skywalker"
thumbnail: "https://cdn.jetphotos.com/200/5/609890_1717848712_tb.jpg"
medium: "https://cdn.jetphotos.com/400/5/609890_1717848712.jpg"
large: "https://cdn.jetphotos.com/640/5/609890_1717848712.jpg"
}
images_list {
url: "https://www.jetphotos.com/photo/11358154"
copyright: "Tim-Patrick Müller"
thumbnail: "https://cdn.jetphotos.com/200/5/1615840_1716633484_tb.jpg"
medium: "https://cdn.jetphotos.com/400/5/1615840_1716633484.jpg"
large: "https://cdn.jetphotos.com/640/5/1615840_1716633484.jpg"
}
images_list {
url: "https://www.jetphotos.com/photo/11337719"
copyright: "Siegi N."
thumbnail: "https://cdn.jetphotos.com/200/6/417379_1714816605_tb.jpg"
medium: "https://cdn.jetphotos.com/400/6/417379_1714816605.jpg"
large: "https://cdn.jetphotos.com/640/6/417379_1714816605.jpg"
}
msn_available: true
age_available: true
registered_owners: "Network Aviation"
}
flight_plan {
}
schedule_info {
flight_number: "CC4400"
operated_by_id: 437
origin_id: 1366
actual_departure: 1720074023
}
flight_progress {
elapsed_time: 1611
}
flight_info {
flightid: 905705829
lat: 21.2512665
lon: 112.568764
track: 278
alt: 31000
speed: 512
timestamp: 1720075629
callsign: "ABD4400"
ems_availability {
amcp_availability: true
oat_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
vspeed_availability: true
airspace_availability: true
}
flight_trail_list {
snapshot_id: 1720073072
lat: 22.3014889
lon: 113.923706
heading: 340
}
flight_trail_list {
snapshot_id: 1720073114
lat: 22.3012848
lon: 113.92379
spd: 3
heading: 340
}
...
altitude: 31000
spd: 512
heading: 278
}
##### 1 #####
schedule_info {
flight_number: "CC4400"
operated_by_id: 437
origin_id: 1366
actual_departure: 1720074023
}
flight_progress {
elapsed_time: 1615
}
flight_info {
flightid: 905705829
lat: 21.2530975
lon: 112.555733
track: 278
alt: 31000
speed: 512
timestamp: 1720075634
callsign: "ABD4400"
ems_availability {
amcp_availability: true
oat_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
vspeed_availability: true
airspace_availability: true
}
##### 2 #####
schedule_info {
flight_number: "CC4400"
operated_by_id: 437
origin_id: 1366
actual_departure: 1720074023
}
flight_progress {
elapsed_time: 1619
}
flight_info {
flightid: 905705829
lat: 21.2530975
lon: 112.555733
track: 278
alt: 31000
speed: 512
timestamp: 1720075634
callsign: "ABD4400"
ems_availability {
amcp_availability: true
oat_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
vspeed_availability: true
airspace_availability: true
}
##### 3 #####
schedule_info {
flight_number: "CC4400"
operated_by_id: 437
origin_id: 1366
actual_departure: 1720074023
}
flight_progress {
elapsed_time: 1623
}
flight_info {
flightid: 905705829
lat: 21.2557068
lon: 112.537407
track: 278
alt: 31000
speed: 512
timestamp: 1720075641
callsign: "ABD4400"
...
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=0x3a7e02c1)
response = await flight_details(client, params, headers)
return parse_data(response.content, FlightDetailsResponse).unwrap()
data = await flight_details_data()
data
aircraft_info {
icao_address: 7901761
reg: "B-LQD"
type: "A359"
icon: A330
full_description: "Airbus A350-941"
images_list {
url: "https://www.jetphotos.com/photo/11697954"
copyright: "David Li"
thumbnail: "https://cdn.jetphotos.com/200/5/675179_1744593599_tb.jpg"
medium: "https://cdn.jetphotos.com/400/5/675179_1744593599.jpg"
large: "https://cdn.jetphotos.com/640/5/675179_1744593599.jpg"
}
images_list {
url: "https://www.jetphotos.com/photo/11703546"
copyright: "Michael Eaton"
thumbnail: "https://cdn.jetphotos.com/200/6/528687_1745054061_tb.jpg"
medium: "https://cdn.jetphotos.com/400/6/528687_1745054061.jpg"
large: "https://cdn.jetphotos.com/640/6/528687_1745054061.jpg"
}
images_list {
url: "https://www.jetphotos.com/photo/11682674"
copyright: "Dominic Oakes"
thumbnail: "https://cdn.jetphotos.com/200/6/649488_1743374705_tb.jpg"
medium: "https://cdn.jetphotos.com/400/6/649488_1743374705.jpg"
large: "https://cdn.jetphotos.com/640/6/649488_1743374705.jpg"
}
msn_available: true
age_available: true
registered_owners: "Cathay Pacific"
is_country_of_reg_available: true
}
schedule_info {
flight_number: "CX748"
operated_by_id: 57
painted_as_id: 57
origin_id: 1627
destination_id: 1366
scheduled_departure: 1748164800
scheduled_arrival: 1748212200
actual_departure: 1748165560
arr_terminal: "1"
}
flight_progress {
traversed_distance: 8271718
remaining_distance: 2474032
elapsed_time: 33428
remaining_time: 11700
eta: 1748210688
great_circle_distance: 10671581
mean_flight_time: 44471
flight_stage: AIRBORNE
delay_status: GREEN
progress_pct: 74
}
flight_info {
flightid: 981336769
lat: 7.2621026
lon: 96.8550873
track: 60
alt: 41000
speed: 446
timestamp_ms: 1748198985330
callsign: "CPA748"
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
vspeed_availability: true
airspace_availability: true
server_time_ms: 1748198988037
}
flight_plan {
}
flight_trail_list {
snapshot_id: 1748164567
lat: -26.1300163
lon: 28.23349
heading: 320
}
...
flight_trail_list {
snapshot_id: 1748198963
lat: 7.23896599
lon: 96.814743
altitude: 41000
spd: 445
heading: 60
}
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=0x3a6d881a, timestamp=1747794900)
response = await playback_flight(client, message, headers)
return parse_data(response.content, PlaybackFlightResponse).unwrap()
data = await playback_flight_data()
data
aircraft_info {
icao_address: 7867035
type: "A359"
icon: A330
full_description: "Airbus A350-941"
images_list {
url: "https://www.jetphotos.com/photo/11633658"
copyright: "lix1aolu"
thumbnail: "https://cdn.jetphotos.com/200/6/850117_1739185739_tb.jpg"
medium: "https://cdn.jetphotos.com/400/6/850117_1739185739.jpg"
large: "https://cdn.jetphotos.com/640/6/850117_1739185739.jpg"
}
images_list {
url: "https://www.jetphotos.com/photo/11634217"
copyright: "Waibibabu"
thumbnail: "https://cdn.jetphotos.com/200/6/591483_1739217827_tb.jpg"
medium: "https://cdn.jetphotos.com/400/6/591483_1739217827.jpg"
large: "https://cdn.jetphotos.com/640/6/591483_1739217827.jpg"
}
images_list {
url: "https://www.jetphotos.com/photo/11620028"
copyright: "ZBAA cao"
thumbnail: "https://cdn.jetphotos.com/200/6/723478_1737987561_tb.jpg"
medium: "https://cdn.jetphotos.com/400/6/723478_1737987561.jpg"
large: "https://cdn.jetphotos.com/640/6/723478_1737987561.jpg"
}
msn_available: true
age_available: true
registered_owners: "Cathay Pacific"
is_country_of_reg_available: true
}
schedule_info {
flight_number: "CX150"
operated_by_id: 57
painted_as_id: 57
origin_id: 431
destination_id: 1366
scheduled_departure: 1747794900
scheduled_arrival: 1747827000
actual_departure: 1747796246
actual_arrival: 1747826241
arr_terminal: "1"
baggage_belt: "2"
}
flight_info {
flightid: 980256794
lat: -27.4022541
lon: 153.113098
track: 30
speed: 1
timestamp_ms: 1747794874975
on_ground: true
callsign: "CPA150"
ems_availability {
}
squawk_availability: true
vspeed_availability: true
airspace_availability: true
server_time_ms: 1747895055592
}
flight_trail_list {
snapshot_id: 1747794677
lat: -27.4009781
lon: 153.112823
heading: 306
}
flight_trail_list {
snapshot_id: 1747794731
lat: -27.4011135
lon: 153.113037
spd: 2
heading: 312
}
...
flight_trail_list {
snapshot_id: 1747827307
lat: 22.3126259
lon: 113.925751
heading: 53
}
"""