Why I stopped checking flight status manually
There’s a specific kind of annoyance that comes with airport pickups. You check the flight tracker app ten minutes before you’d need to leave, it says “on time,” you drive out, and then at some point the gate agent updates the status to a 40-minute delay that was probably known two hours ago.
The airline apps are almost always the last to update. ADS-B receivers on the ground see the aircraft position in real time — when a plane is still somewhere over the Baltic and descending, you know it’s going to land early before the app figures it out.
What ADS-B is
Modern commercial aircraft broadcast their position, altitude, speed, and identifier (a 24-bit ICAO address) constantly over 1090 MHz. Anyone with a cheap software-defined radio dongle can receive these signals. A €25 RTL-SDR stick and a simple antenna is enough.
The open source tool that decodes these signals into something usable is dump1090. It runs continuously, decodes the ADS-B messages, and exposes the current aircraft data as a JSON endpoint at http://localhost:8080/data/aircraft.json.
The setup
Hardware: a Raspberry Pi 3B that was already running other things, and an RTL-SDR Blog V3 dongle plugged into a USB port with a telescoping whip antenna sitting near a window.
Installation on the Pi:
sudo apt install rtl-sdr
# build dump1090-fa (FlightAware's fork is the most maintained)
git clone https://github.com/flightaware/dump1090.git
cd dump1090
make
sudo make install
# run as a service
sudo systemctl enable --now dump1090-fa
With the antenna near a window I can see aircraft up to about 200 km away on a clear day, which covers all the approach paths for the airport I care about.
The notification script
The JSON endpoint from dump1090 updates every second. Each aircraft entry has its ICAO hex address, callsign, lat/lon, altitude, and speed. A simple polling loop does the job:
import requests
import math
import time
HOME_LAT = 60.1699
HOME_LON = 24.9384
ALERT_RADIUS_KM = 80
ALERT_ALTITUDE_FT = 10000 # below this, it's on approach
DUMP1090_URL = "http://localhost:8080/data/aircraft.json"
# specific ICAO addresses or callsigns to watch
WATCH_LIST = {"3c675a", "4ca845"}
seen = set()
def haversine(lat1, lon1, lat2, lon2):
R = 6371
dlat = math.radians(lat2 - lat1)
dlon = math.radians(lon2 - lon1)
a = math.sin(dlat/2)**2 + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(dlon/2)**2
return R * 2 * math.asin(math.sqrt(a))
while True:
try:
data = requests.get(DUMP1090_URL, timeout=2).json()
for ac in data.get("aircraft", []):
icao = ac.get("hex", "").lower()
lat = ac.get("lat")
lon = ac.get("lon")
alt = ac.get("alt_baro", 99999)
if icao not in WATCH_LIST or lat is None:
continue
dist = haversine(HOME_LAT, HOME_LON, lat, lon)
if dist < ALERT_RADIUS_KM and alt < ALERT_ALTITUDE_FT and icao not in seen:
seen.add(icao)
notify(f"{icao} is {dist:.0f} km out, {alt} ft — probably 20 min to landing")
except Exception:
pass
time.sleep(10)
The seen set prevents repeat notifications for the same aircraft. It clears when the script restarts, which is daily via a cron job.
Finding the ICAO address for a specific flight
If you know the flight number, you can look up the ICAO 24-bit address for that specific aircraft with any of the open tracking databases. Or you can just watch what callsigns appear in your dump1090 feed around the expected arrival time and match by flight number. Takes about two minutes the first time.
For recurring flights on the same route, the airline often uses a small pool of aircraft — the same tail number shows up again within a few weeks, so your watch list stays useful.
What works well
The main benefit is lead time. When a flight is 80 km out at 8,000 ft and descending, I know I have about 20 minutes before wheels down. That’s a more reliable trigger for leaving the house than any status page.
It also works for arrivals that are running ahead of schedule, which the apps handle badly — they show “on time” even when the aircraft is clearly 15 minutes early based on its position.
What it doesn’t cover
Departure delays are harder — you’d need to watch for the aircraft appearing at the origin airport, which requires a receiver there or an API. For those I still use a flight tracker app or check the airport’s departure board directly.
If you’re building monitoring infrastructure for something at your company — flights, vehicles, or any asset that broadcasts position — feel free to reach out.