OpenSky Flight Scraper: Live Aircraft Positions
Under maintenancePricing
from $0.37 / 1,000 state scrapeds
OpenSky Flight Scraper: Live Aircraft Positions
Under maintenanceScrape live ADS-B aircraft states from the OpenSky Network: ICAO24, callsign, origin country, latitude, longitude, altitude, velocity and heading. Filter by bounding box.
Pricing
from $0.37 / 1,000 state scrapeds
Rating
0.0
(0)
Developer
Arman Hossain
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
18 days ago
Last modified
Categories
Share

Takes a snapshot of every aircraft currently transmitting inside a geographic box: ICAO24 address, callsign, origin country, latitude, longitude, barometric and geometric altitude, ground speed, heading and vertical rate.
The OpenSky Network is a community ADS-B receiver network that publishes its live state vectors over a plain HTTP API. This Actor calls that API directly, so there is no browser, no proxy, no login and no scraping of a rendered map. A box covering the Alps returns roughly 240 aircraft.
Agent skill: SKILL.md
https://api.apify.com/v2/key-value-stores/t7YoTxpZEJOWvw4Ug/records/opensky-flights-scraper.md
What you get
| Field | What it holds |
|---|---|
icao24 | 24-bit ICAO transponder address in lowercase hex, the stable aircraft identifier |
callsign | Flight callsign as broadcast, trimmed. null when the aircraft is not transmitting one |
originCountry | Country the transponder address is registered to |
timePosition, timePositionIso | When the position fix was taken, as Unix seconds and ISO 8601 |
lastContact, lastContactIso | Last time any message was received from this aircraft |
latitude, longitude | WGS84 position in decimal degrees |
baroAltitude, geoAltitude | Barometric and geometric altitude in metres |
onGround | Whether the network places the aircraft on a surface |
velocity | Ground speed in metres per second |
trueTrack | Track over ground in degrees clockwise from true north |
verticalRate | Metres per second, positive climbing |
squawk | Transponder code |
spi | Special-purpose indicator flag |
positionSource, positionSourceLabel | 0 to 3 and its name: ADS-B, ASTERIX, MLAT or FLARM |
snapshotAt | The single timestamp the whole snapshot belongs to |
scrapedAt | Run timestamp |
RUN_SUMMARY in the key-value store holds counts, whether the run was authenticated, the API credits left, the filters you used, and any request that failed.
Use cases
- Regional traffic monitoring. Schedule a run every few minutes over one box and build a time series.
- Airport apron analytics. A tight box plus
onGroundOnlygives taxiing and parked aircraft. - Fleet tracking. Pass a list of
icao24addresses and follow specific airframes. - Live displays. Feed a map or dashboard with a current snapshot on demand.
- Aviation research. Sample altitude, speed and vertical-rate distributions over a corridor.
Quick start
Everything over the Alps:
{"boundingBox": { "lamin": 45, "lomin": 5, "lamax": 48, "lomax": 10 }}
Aircraft on the ground around a UK box, capped:
{"boundingBox": { "lamin": 49.9, "lomin": -6.4, "lamax": 55.8, "lomax": 1.8 },"onGroundOnly": true,"maxResults": 200}
Named airframes, authenticated for the higher quota:
{"icao24": ["4b4072", "3c6444"],"clientId": "your-opensky-client-id","clientSecret": "your-opensky-client-secret"}
Input
| Field | Type | Default | Notes |
|---|---|---|---|
boundingBox | object | none | { lamin, lomin, lamax, lomax } in WGS84 degrees. Omit for a worldwide query, which costs 4 credits instead of 1. |
icao24 | array | [] | 6-hex-character ICAO addresses. Batched 50 per request. Combines with boundingBox if both are set. |
onGroundOnly | boolean | false | Keep only aircraft reported on a surface. Off returns airborne and grounded alike. |
maxResults | integer | 500 | Cap on states saved, applied after filtering. |
clientId | string (secret) | none | Optional OAuth2 client ID. |
clientSecret | string (secret) | none | Optional OAuth2 client secret. Both must be present or the run stays anonymous. |
boundingBox is validated before any request goes out: latitudes must be -90 to 90, longitudes -180 to 180, and lamin/lomin must be below lamax/lomax. An inverted or out-of-range box fails immediately rather than silently returning nothing.
Output example
{"icao24": "39de43","callsign": "TVF99KE","originCountry": "France","timePosition": 1786016349,"timePositionIso": "2026-08-06T11:39:09.000Z","lastContact": 1786016350,"lastContactIso": "2026-08-06T11:39:10.000Z","longitude": 9.2508,"latitude": 45.3561,"baroAltitude": 11574.78,"geoAltitude": 12230.1,"onGround": false,"velocity": 220.77,"trueTrack": 288.9,"verticalRate": 0,"squawk": "5515","spi": false,"positionSource": 0,"positionSourceLabel": "ADS-B","snapshotAt": "2026-08-06T11:39:10.000Z","scrapedAt": "2026-08-06T11:39:11.586Z"}
Units are SI throughout: metres for altitude, metres per second for velocity and vertical rate, degrees for position and track. Nothing is converted to feet or knots, so convert on your side if you need to and no precision is lost here.
Credits and rate limits
OpenSky meters /states/all in credits, and the cost depends on how much sky you ask for:
| Query | Credits |
|---|---|
| Box of 25 square degrees or less | 1 |
| Box up to 100 square degrees | 2 |
| Box up to 400 square degrees | 3 |
| Larger box or worldwide | 4 |
| Access | Daily credits | Snapshot resolution |
|---|---|---|
| Anonymous (by IP) | 400 | 10 seconds |
| OAuth2 client credentials | 4,000 | 5 seconds |
Anonymous access is shared per source IP, and Apify runs go out through shared addresses, so the 400 you nominally get may already be partly spent. The Actor logs the x-rate-limit-remaining value OpenSky returns and stores it in RUN_SUMMARY.creditsRemaining, so you can see exactly where you stand after every run. If you plan to schedule this, register a free OpenSky account, create an API client, and paste the client ID and secret in. The Actor then fetches an OAuth2 token itself.
API example
curl -X POST "https://api.apify.com/v2/acts/arman-bd~opensky-flights-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"boundingBox": { "lamin": 45, "lomin": 5, "lamax": 48, "lomax": 10 },"maxResults": 100}'
JavaScript example
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_TOKEN' });const run = await client.actor('arman-bd/opensky-flights-scraper').call({boundingBox: { lamin: 49.9, lomin: -6.4, lamax: 55.8, lomax: 1.8 },maxResults: 500,});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const state of items) {console.log(`${state.callsign ?? state.icao24} - ${state.baroAltitude} m at ${state.velocity} m/s`);}
Notes
- One snapshot gets one timestamp. Every record in a run shares the same
snapshotAt, so the dataset is a coherent instant rather than a smear. - Positional arrays are decoded for you. The API returns each aircraft as a bare 17-element array, and the Actor maps it against the documented state-vector contract and hands you named fields.
- Nulls are real.
baroAltitude,squawk,velocityandverticalRateare absent for many aircraft, and an aircraft on the ground usually has no barometric altitude. Those staynullrather than being coerced to zero. - Duplicate addresses collapse. If the same
icao24appears twice in one snapshot only the first is saved. - Transient errors get retried. 429 and 5xx responses get three attempts with linear backoff. A 401 or 403 is fatal, because it means credentials or quota, not a blip.
- Public data only. ADS-B is broadcast unencrypted by aircraft, and OpenSky aggregates it from volunteer receivers.
FAQ
Do I need an OpenSky account? No. You supply no credentials.
Why did I get zero aircraft? Either the box is over empty airspace or your IP's daily credits ran out. RUN_SUMMARY.creditsRemaining tells you which.
Can I get historical flights? No. This Actor reads the live state snapshot only. OpenSky's historical endpoints need an authenticated account and a different query model.
Are altitudes in feet? No, metres, exactly as the API delivers them. Multiply by 3.28084 for feet.
Why is callsign empty for some aircraft? Not every transponder broadcasts one, particularly general aviation and aircraft on the ground. icao24 is always present and is the field to key on.
Can I schedule it? Yes, and that is the point. A run every five minutes over one small box costs about 288 credits a day, which fits inside the anonymous allowance if the IP is not shared. Authenticate for anything tighter than that.