DEV Community

Cover image for I drew 47 million aircraft positions from my home tracker
Andrew Yong
Andrew Yong

Posted on

I drew 47 million aircraft positions from my home tracker

I run a flight and ship tracker at home that writes every position it sees to disk. After two months I had a 27 GB SQLite file and no idea what was in it, so I started drawing it. No basemap, no coastlines, just one pixel per position bucket on a log scale.

Six hours of global air traffic

World map drawn only from aircraft positions

47.6 million positions from 50,202 aircraft, 10 October 2026, 11:00 to 17:00 UTC. The data comes from public ADS-B aggregators (adsb.lol, OpenSky and a few others), which collect what volunteers' receivers pick up.

I posted this on r/dataisbeautiful and the comments taught me more about my own data than I knew:

  • China and Russia look almost empty. That's coverage, not traffic. Very few people there feed public aggregators, so the map mostly shows where receivers are.
  • Melbourne to Sydney is one of the busiest routes in the world and barely shows up. The window is 10pm to 4am there, and Sydney airport has a curfew from 11pm.
  • Six hours skews everything. It's afternoon in Europe, morning in the Americas and night in East Asia. A full 24 hours is next.

Europe, same six hours

Europe drawn only from aircraft tracks

14.6 million positions from 11,127 aircraft. With no coastlines it took one commenter a moment to find Europe at all. London is the brightest knot top left, and once you have it Paris, Frankfurt and Madrid fall into place.

Ships along the Norwegian coast

Ship positions along Norway's coast

3.4 million AIS positions over 12 days from Kystverket, the Norwegian Coastal Administration, which publishes a free live AIS feed. The bright dots out at sea are oil and gas fields. I looked up the ships parked at the brightest ones: drilling rigs like Deepsea Stavanger and Scarabeo 8, the Alvheim production ship, and the supply and standby boats that sit next to them for days. A ship that doesn't move piles up thousands of positions in one pixel.

How the maps are made

The tracker stores positions in a positions table with lon, lat, t and kind. The whole map is a 2D histogram:

W, H = 3600, 1800  # 0.1 degree cells
cur = db.execute("select lon, lat from positions where t >= ? and t < ? and kind = 'aircraft'", (t0, t1))
hist = np.zeros((H, W))
while rows := cur.fetchmany(2_000_000):
    a = np.asarray(rows)
    x = ((a[:, 0] + 180) / 360 * W).astype(int)
    y = ((90 - a[:, 1]) / 180 * H).astype(int)
    ok = (x >= 0) & (x < W) & (y >= 0) & (y < H)
    np.add.at(hist, (y[ok], x[ok]), 1)
Enter fullscreen mode Exit fullscreen mode

Then np.log1p, divide by the 99.7th percentile so a few airports don't blow out the scale, map through a colour ramp, and save with Pillow. Reading 47 million rows in 2-million-row chunks keeps memory flat. For the Norway map I scaled longitude by cos(63°) so the coast isn't stretched.

The tracker

It's called Velocity and it's open source (AGPL). I built it because free trackers keep shrinking how far back you can look: Flightradar24 gives 7 days of replay free, MarineTraffic 24 hours. Velocity pulls the same public feeds, needs no API keys, and keeps whatever you tell it to on your own disk, with a scrubber to rewind the map.

If you want to make your own version of these maps, docker compose up and leave it running for a day. Next up is the full 24-hour world map and a Nordic one with Danish waters filled in.

Top comments (0)