Overview¤
Name | Core functions | 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.lower()}.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 |
gRPC |
search_index |
- |
Follow Flight gRPC |
follow_flight_stream |
FollowFlightService |
Top Flights gRPC |
top_flights |
TopFlightsService Cache Location: top_flights/ └── {timestamp_s}.parquet |
gRPC |
live_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/
.
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(fr24.playback.metadata(result.to_dict()))
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¤
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.find 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
async def my_feed() -> None:
async with FR24() as fr24:
result = await fr24.live_feed.fetch()
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', 'flight', 'type', 'route'}
),
response=<Response [200 OK]>,
base_dir=PosixPath('/home/user/.cache/fr24'),
timestamp=1737360998
)
{
'flightsList': [
{
'flightid': 952888097,
'lat': 42.467102,
'lon': -6.0266876,
'track': 210,
'alt': 39000,
'speed': 437,
'timestamp': 1737360996,
'callsign': 'TVF96CL',
'extra_info': {
'flight': 'TO3080',
'reg': 'F-HTVR',
'route': {'from': 'ORY', 'to': 'VIL'},
'type': 'B738'
},
'position_buffer': {
'recent_positions_list': [
{'deltaLat': -306, 'deltaLon': -241, 'deltaMs': 2100},
{'deltaLat': -566, 'deltaLon': -445, 'deltaMs': 3110},
{'deltaLat': -732, 'deltaLon': -574, 'deltaMs': 4260},
{'deltaLat': -897, 'deltaLon': -707, 'deltaMs': 5280},
{'deltaLat': -1055, 'deltaLon': -828, 'deltaMs': 6470},
{'deltaLat': -1297, 'deltaLon': -1020, 'deltaMs': 7470},
{'deltaLat': -1493, 'deltaLon': -1173, 'deltaMs': 8570},
{'deltaLat': -1657, 'deltaLon': -1304, 'deltaMs': 9801}
]
}
},
{
'flightid': 952890068,
'lat': 42.7418,
'lon': -5.856479,
'track': 276,
'alt': 41750,
'speed': 449,
'icon': 'LJ60',
'timestamp': 1737360995,
'callsign': 'QQE210',
'extra_info': {
'flight': 'QE210',
'reg': 'A7-CGC',
'route': {'from': 'BCN', 'to': 'IAD'},
'type': 'GLF6'
},
'position_buffer': {
'recent_positions_list': [
{'deltaLat': 22, 'deltaLon': -276, 'deltaMs': 1106},
{'deltaLat': 46, 'deltaLon': -562, 'deltaMs': 2187},
{'deltaLat': 67, 'deltaLon': -838, 'deltaMs': 3189},
{'deltaLat': 95, 'deltaLon': -1175, 'deltaMs': 4369},
{'deltaLat': 130, 'deltaLon': -1564, 'deltaMs': 5481},
{'deltaLat': 158, 'deltaLon': -1903, 'deltaMs': 6522},
{'deltaLat': 177, 'deltaLon': -2126, 'deltaMs': 7540},
{'deltaLat': 200, 'deltaLon': -2404, 'deltaMs': 8565}
]
}
},
]
'server_time_ms': '1737360998825'
}
shape: (899, 18)
┌────────────┬───────────┬───────────┬───────────┬───┬─────┬───────────────┬────────┬──────────────┐
│ timestamp ┆ flightid ┆ latitude ┆ longitude ┆ … ┆ eta ┆ vertical_spee ┆ squawk ┆ position_buf │
│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ d ┆ --- ┆ fer │
│ u32 ┆ u32 ┆ f32 ┆ f32 ┆ ┆ u32 ┆ --- ┆ u16 ┆ --- │
│ ┆ ┆ ┆ ┆ ┆ ┆ i16 ┆ ┆ list[struct[ │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 3]] │
╞════════════╪═══════════╪═══════════╪═══════════╪═══╪═════╪═══════════════╪════════╪══════════════╡
│ 1737360996 ┆ 952888097 ┆ 42.467102 ┆ -6.026688 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [{-306,-241, │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 2100}, │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ {-566,-445,… │
│ 1737360995 ┆ 952890068 ┆ 42.741798 ┆ -5.856479 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [{22,-276,11 │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 06}, {46,-56 │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 2,2187… │
│ 1737360995 ┆ 952889599 ┆ 43.295025 ┆ -5.364467 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [{-279,-228, │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 1120}, │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ {-374,-307,… │
│ 1737360996 ┆ 952886169 ┆ 42.944916 ┆ -5.611012 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [{-256,-210, │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 1004}, │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ {-445,-366,… │
│ 1737360996 ┆ 952881151 ┆ 43.920135 ┆ -7.713935 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [{210,178,13 │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 66}, {379,32 │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 5,2442… │
│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │
│ 1737360996 ┆ 952890387 ┆ 51.8517 ┆ 8.181763 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [{-170,-208, │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 2208}, │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ {-312,-386,… │
│ 1737360995 ┆ 952894571 ┆ 51.961933 ┆ 8.233468 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [{58,257,101 │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 5}, {127,577 │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ,2055}… │
│ 1737360995 ┆ 952889383 ┆ 51.81115 ┆ 9.978867 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [{-14,283,11 │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 35}, {-32,57 │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 2,2170… │
│ 1737360996 ┆ 952883520 ┆ 51.52737 ┆ 9.759674 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [{400,68,204 │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 0}, {597,99, │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 3163},… │
│ 1737360995 ┆ 952894664 ┆ 51.909981 ┆ 9.415519 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [{-167,-31,1 │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 009}, {-409, │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ -78,20… │
└────────────┴───────────┴───────────┴───────────┴───┴─────┴───────────────┴────────┴──────────────┘
Playback¤
Fetches the live feed three days ago.
from fr24 import FR24
import time
yesterday = int(time.time() - 86400)
async def my_feed() -> None:
async with FR24() as fr24:
result = await fr24.live_feed_playback.fetch(timestamp=yesterday)
print(result.to_polars())
await my_feed()
shape: (940, 18)
┌────────────┬───────────┬───────────┬───────────┬───┬─────┬───────────────┬────────┬──────────────┐
│ timestamp ┆ flightid ┆ latitude ┆ longitude ┆ … ┆ eta ┆ vertical_spee ┆ squawk ┆ position_buf │
│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ d ┆ --- ┆ fer │
│ u32 ┆ u32 ┆ f32 ┆ f32 ┆ ┆ u32 ┆ --- ┆ u16 ┆ --- │
│ ┆ ┆ ┆ ┆ ┆ ┆ i16 ┆ ┆ list[struct[ │
│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 3]] │
╞════════════╪═══════════╪═══════════╪═══════════╪═══╪═════╪═══════════════╪════════╪══════════════╡
│ 1737104838 ┆ 952273942 ┆ 43.187767 ┆ -7.548785 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [] │
│ 1737104838 ┆ 952254140 ┆ 43.458115 ┆ -7.056863 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [] │
│ 1737104838 ┆ 952267277 ┆ 42.048569 ┆ -6.353781 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [] │
│ 1737104838 ┆ 952267720 ┆ 42.491348 ┆ -6.816059 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [] │
│ 1737104838 ┆ 952254919 ┆ 42.357601 ┆ -6.892963 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [] │
│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │
│ 1737104824 ┆ 952275115 ┆ 51.653938 ┆ 8.602921 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [] │
│ 1737104838 ┆ 952276824 ┆ 51.864647 ┆ 8.417774 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [] │
│ 1737104838 ┆ 952276666 ┆ 51.788548 ┆ 8.350671 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [] │
│ 1737104838 ┆ 952271643 ┆ 43.356052 ┆ 9.972774 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [] │
│ 1737104839 ┆ 952265180 ┆ 42.819351 ┆ 9.988424 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ [] │
└────────────┴───────────┴───────────┴───────────┴───┴─────┴───────────────┴────────┴──────────────┘
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… │
└─────────────┴───────┴──────────┴─────────────┴───┴──────────┴────────┴─────────────┴─────────────┘
Core functions¤
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.flight_list import FlightList
async def my_list() -> FlightList:
async with httpx.AsyncClient() as client:
auth = await login(client)
if auth is not None:
print(auth["message"])
response = await flight_list(
client,
FlightListParams(
flight="AF291",
timestamp=datetime.strptime("2025-01-16", "%Y-%m-%d"), # (1)!
),
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.playback import Playback
async def my_playback() -> Playback:
async with httpx.AsyncClient() as client:
auth = await login(client)
if auth is not None:
print(auth["message"])
response = await playback(
client,
PlaybackParams(flight_id="38c59db3"),
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.airport_list import AirportList
from fr24.json import airport_list, AirportListParams
import polars as pl
async def my_arrivals() -> AirportList:
async with httpx.AsyncClient() as client:
response = await airport_list(
client,
AirportListParams(airport="tls", mode="arrivals"),
)
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.find import Find
from fr24.json import find, FindParams
import polars as pl
import httpx
async def my_find() -> Find:
async with httpx.AsyncClient() as client:
response = await find(client, FindParams(query="paris"))
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
async def france_data() -> LiveFeedResponse:
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)
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
async def nearest_flights_data() -> NearestFlightsResponse:
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)
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
async def live_flights_status_data() -> LiveFlightsStatusResponse:
async with httpx.AsyncClient() as client:
message = LiveFlightsStatusRequest(
flight_ids_list=[0x35FBC363, 0x35FBF180]
)
response = await live_flights_status(client, message)
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
async def search_index_data() -> FetchSearchIndexResponse:
async with httpx.AsyncClient() as client:
message = FetchSearchIndexRequest()
response = await search_index(client, message)
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
async def follow_flight_data() -> None:
timeout = httpx.Timeout(5, read=120)
async with httpx.AsyncClient(timeout=timeout) as client:
message = FollowFlightRequest(flight_id=0x395C43CF)
i = 0
async for response in follow_flight_stream(client, message):
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
async def top_flights_data() -> TopFlightsResponse:
async with httpx.AsyncClient() as client:
message = TopFlightsRequest(limit=10)
response = await top_flights(client, message)
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
async def live_trail_data() -> LiveTrailResponse:
async with httpx.AsyncClient() as client:
message = LiveTrailRequest(flight_id=0x395c43cf)
response = await live_trail(client, message)
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
async def historic_trail_data() -> HistoricTrailResponse:
async with httpx.AsyncClient() as client:
message = HistoricTrailRequest(flight_id=0x395c43cf)
response = await historic_trail(client, message)
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
async def flight_details_data() -> FlightDetailsResponse:
async with httpx.AsyncClient() as client:
params = FlightDetailsParams(flight_id=0x3a7e02c1)
response = await flight_details(client, params)
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
async def playback_flight_data() -> PlaybackFlightResponse:
async with httpx.AsyncClient() as client:
message = PlaybackFlightParams(flight_id=0x3a6d881a, timestamp=1747794900)
response = await playback_flight(client, message)
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
}
"""