L logiover
data · Jul 9, 2026 · 8 min read

How to Scrape Live Aircraft & ADS-B Flight Data in 2026

Pull live aircraft positions worldwide — callsign, registration, altitude, speed and heading — from a keyless ADS-B feed. How the global grid works, cleanly.

Live flight data looks like it should be easy — aircraft broadcast their position in the clear on 1090 MHz, and community networks aggregate it for free. Then you try to pull a global snapshot and hit the wall every flight-tracking developer knows: the official state endpoint hands unauthenticated callers a thin, heavily rate-limited slice, and a single request for “the whole world” times out or comes back throttled. This guide covers how to get a clean, deduplicated snapshot of global air traffic — thousands of aircraft per run — keyless, without fighting per-endpoint limits.

The approach is a global grid: instead of one giant query, the scraper fans out concurrent requests to a network of 52 regional aviation centers across six continents, then merges and dedupes the results by ICAO24 hex address. Each aircraft that appears in range of two adjacent centers is pushed once. The output is a flat, sixteen-field record per aircraft — everything you need for a live map, a research dataset, or an analytics pipeline.

What’s worth extracting

Each aircraft record carries 16 fields, straight from the ADS-B feed:

Identity

  • icao24 — the 24-bit ICAO Mode S transponder address in hex. This is the stable, unique key for an airframe.
  • callsign — the flight callsign or airline designator, trimmed (e.g. BAW19N).
  • registration — the aircraft tail number (e.g. G-VIIE, N12345).
  • aircraftType — the ICAO type code (B738, A320, B77W, C172).
  • category — the ADS-B emitter category (A1 = light, A3 = medium, A5 = heavy, B1 = glider, C0 = surface vehicle).

Position and motion

  • latitude, longitude — WGS-84 decimal degrees.
  • baroAltitude, geoAltitude — barometric and GPS/geometric altitude, in meters.
  • velocity — ground speed in m/s.
  • trueTrack — track angle in degrees (0 = north, 90 = east).
  • verticalRate — climb/descent rate in m/s (positive = climbing).
  • onGround"true" if on the ground, "false" if airborne.

Context

  • squawk — the ATC transponder squawk code.
  • snapshotTime — Unix timestamp of the snapshot.
  • region — the nearest aviation center label (e.g. London, Paris, Tokyo), which gives you geographic grouping for free, without geocoding.

Note the numeric-looking fields (velocity, trueTrack, verticalRate, onGround, snapshotTime) come through as strings — cast them before you do math.

How the source actually works

There is no single “give me the world” call that works reliably unauthenticated. The scraper’s engine is the workaround: it queries a global grid of 52 aviation centers concurrently — Europe, North America, the Middle East, Asia, Africa, Oceania, South America — and deduplicates aircraft by icao24 so an aircraft seen by two neighboring centers isn’t double-counted.

You control scope three ways, all through one mode (currently liveStates):

Full global snapshot — leave the geographic fields empty:

{
  "mode": "liveStates"
}

Bounding box — restrict to grid centers inside a lat/lon box. This is the example input for central Europe:

{
  "mode": "liveStates",
  "lamin": 45.0,
  "lomin": -5.0,
  "lamax": 55.0,
  "lomax": 15.0
}

Single center point — one location plus a radius in nautical miles (default 100):

{
  "mode": "liveStates",
  "centerLat": 25.2,
  "centerLon": 55.4,
  "radius": 150
}

The bounding box is the throughput lever: for a continental region it cuts the query from all 52 centers down to roughly 8–14, so results come back faster. A single center point plus a tight radius (say 50 nm) is how you isolate one airport’s approach and departure corridor — for Heathrow that’s centerLat: 51.477, centerLon: -0.461, radius: 50.

The region field on every record tells you which of the 52 grid centers detected the aircraft, so you get coarse geographic grouping (London, Paris, Tokyo) without running a geocoder over the coordinates. That’s useful when you want per-region counts but don’t need precise reverse geocoding.

Run the OpenSky Flight Scraper on Apify — one run captures thousands of live aircraft with position, altitude, speed and registration. No API key, no login. Export to JSON, CSV, Excel or Google Sheets.

The access reality

The honest friction here is source rate limits and transponder coverage, not an anti-bot wall. ADS-B broadcasts are public radio signals, and the scraper reads a public, unauthenticated feed — no key, no signup. The reasons a naive single request fails, and how the grid handles them:

  • Response-size and radius limits. Ask one endpoint for too large an area and it times out. The grid keeps each regional query bounded, and on a single center point you should keep radius at 100–120 nm — above roughly 150 nm the response can be too large and time out.
  • Snapshot, not stream. Each run is a single point-in-time snapshot. The underlying ADS-B receivers refresh every 8–12 seconds, so for near-real-time tracking you schedule the run every 5–10 minutes rather than polling in a loop.
  • Time-of-day volume. A full global run typically returns 1,000–6,000+ unique aircraft, but that swings with the clock. A European or North American bbox returns 500–1,500; a single city center at 100 nm returns 50–300. Overnight snapshots are thin — run during peak hours (roughly 06:00–22:00 UTC) to maximize counts.
  • Not every field is always present. Older Mode C transponders don’t broadcast registration or type, and military aircraft often suppress fields. Nulls are normal, not errors. Country of registration isn’t a named field at all — infer it from the registration prefix (G- = UK, D- = Germany, N = USA, F- = France).

Example output

One airborne aircraft record:

{
  "icao24": "4070e3",
  "callsign": "EXS22AP",
  "registration": "G-JZHO",
  "aircraftType": "B738",
  "longitude": -2.447724,
  "latitude": 51.38118,
  "baroAltitude": 1120,
  "geoAltitude": 1280,
  "onGround": "false",
  "velocity": "108",
  "trueTrack": "340.44",
  "verticalRate": "-6",
  "squawk": "5310",
  "category": "A3",
  "snapshotTime": "1783521184",
  "region": "London"
}

Use cases

  • Live flight-map dashboards — pull thousands of aircraft positions every few minutes to render a moving map without paying per API call.
  • Regional traffic monitoring — track a specific region (Europe, APAC, North America) for capacity planning with a bounding box.
  • Fleet-mix analysis — separate commercial from private from cargo by aircraftType and category (heavy A5 vs medium A3 vs light C172).
  • Airline tracking — filter on callsign prefix to follow a carrier (BAW = British Airways, UAL = United, DLH = Lufthansa).
  • Longitudinal traffic studies — export daily snapshots to a database or Google Sheets and build a trend archive over time.
  • Airport operations — a centerLat/centerLon point at a tight radius gives a programmable feed of the airspace around one facility.

Cost and effort math

Building this yourself means more than calling one endpoint — it means constructing the 52-center grid, tuning each region’s query so it doesn’t time out, running them concurrently, deduping by icao24 across overlapping centers, and scheduling snapshots to fake a live feed. That’s the real work, and it’s separate from the maintenance of keeping regional endpoints and their limits straight.

The managed scraper is pay-per-result: you’re charged for actual aircraft records, not compute time. Schedule it every 5–10 minutes for near-real-time tracking and you’re paying fractions of a cent per aircraft with the grid, dedup and concurrency already solved. A regional bbox run is cheaper and faster than global; a single airport point is cheapest. Because it’s keyless, there’s no source-side subscription on top — the only bill is per row returned.

Common pitfalls

  • Units are metric — convert before you display. baroAltitude and geoAltitude are in meters (multiply by 3.28084 for feet); velocity is m/s. Users expect feet and knots.
  • String-typed numbers. velocity, trueTrack, verticalRate, onGround, snapshotTime and squawk come as strings. Cast them; don’t compare onGround to a boolean, compare to "false".
  • Snapshot, not history. There is no historical endpoint. To study trends, run the scraper on a schedule and accumulate your own archive — a single call only ever gives you “now”.
  • Filter airborne yourself. Parked aircraft are included. Post-process on onGround === "false" to exclude them.
  • Radius above ~150 nm times out. On a single center point, keep radius at 100–120 nm for reliable results; go wider with a bounding box instead.
  • Thin overnight counts are expected. Fewer aircraft fly at night, so off-peak snapshots are naturally sparse — that’s not a scraper fault.
  • Airline and type filtering happens after the run. There’s no in-actor filter for a specific carrier or airframe. Pull the region you want, then filter your dataset on callsign prefix (BAW, UAL, DLH) or on aircraftType — either in Apify’s dataset view or after export.
  • Parallelize by region, not by giant radius. To cover several regions at high resolution, run multiple tasks each with its own bounding box and trigger them in parallel, rather than pushing one radius past its safe ceiling. The grid already parallelizes within a single run for you.

Scheduling and integration

For continuous tracking, the natural pattern is the Apify scheduler: run the scraper every 5–10 minutes and each finish is a fresh global (or regional) snapshot. From there the built-in integrations do the rest — stream rows to Google Sheets on each run, fire a Slack or generic webhook with the aircraft count and defaultDatasetId on success, or trigger a downstream Zapier / Make workflow to write to a database. Because the data is a point-in-time snapshot, this scheduled cadence is how you turn discrete runs into a rolling, near-real-time feed or a longitudinal archive for trend analysis.

Wrapping up

Free ADS-B data is genuinely open, but “pull the whole world at once” is exactly the request the source throttles. The value is in the grid: fanning out to 52 centers, deduping by hex address, and scheduling snapshots into a near-real-time feed. Build it yourself for a one-off, or run a keyless, pay-per-result scraper that has the grid and dedup solved when you need a live feed for production.

Open the OpenSky Flight Scraper on Apify — thousands of live aircraft per run with position, altitude, speed and registration; global, regional or single-airport. Keyless, pay per aircraft. Start on Apify’s free monthly credit.

Related guides