Aircraft
The aircraft.proto contract defines how to start the stream (the StartStream RPC) and the JsonAircraftBatch messages it delivers. Copy it into your project; your gRPC tooling generates a client from it.
syntax = "proto3";
package jetnet.aircraft;
message StartStreamRequest {
string subscription_id = 1;
}
message JsonAircraftBatch {
bytes json_data = 1;
}
service AircraftStreamingService {
rpc StartStream(StartStreamRequest) returns (stream JsonAircraftBatch);
}
Response payload
The json_data field of each JsonAircraftBatch is a UTF-8 JSON array of records. Every record carries an event_type discriminator telling you which kind of data it is.
| event_type | Description |
|---|---|
"position" | An Aircraft State update — the current known state of one aircraft. |
Today only "position" is emitted; the fields below describe that record shape.
Every field is optional except the ones listed below. When a value isn't available the key is omitted entirely — the stream does not send null, 0, or an empty string as a placeholder. So an absent key means only "not currently known for this aircraft."
Emitted on every record:
event_type,hex,type— identity (always a value)messages,seen,rssi— reception metadata (always a value)mlat,tisb— source-field arrays (present, but[]when empty)now— the per-record server timestamp
Every other field below is optional — build your client to null-check before use. Two typing edge cases follow from this: records with no lat/lon (see Position) and alt_baro arriving as either a number or the string "ground" (see Altitude). The full typed contract is the Record model at the bottom of this page.
Sample response payload
A single batch typically looks like this:
[
{
"event_type": "position",
"hex": "a1b2c3",
"type": "adsb_icao",
"flight": "AAL123",
"r": "N123AA",
"t": "B738",
"squawk": "1234",
"category": "A3",
"lat": 37.7749,
"lon": -122.4194,
"alt_baro": 35000,
"alt_geom": 35225,
"gs": 450.2,
"track": 270.5,
"baro_rate": 0,
"nav_qnh": 1013.2,
"nav_altitude_mcp": 35008,
"nav_heading": 271,
"mach": 0.78,
"ias": 280,
"tas": 470,
"wd": 270,
"ws": 25,
"oat": -52,
"nic": 8,
"rc": 186,
"nac_p": 9,
"nac_v": 2,
"sil": 3,
"sil_type": "perhour",
"version": 2,
"messages": 12345,
"seen": 0.1,
"seen_pos": 0.5,
"rssi": -2.5
},
{
"event_type": "position",
"hex": "d4e5f6",
"type": "mlat",
"flight": "DAL456",
"lat": 33.9416,
"lon": -118.4085,
"alt_baro": 12025,
"gs": 320.1,
"track": 95.0,
"seen": 0.3,
"seen_pos": 1.2
}
]
The first aircraft is a fully-populated ADS-B target. The second is a sparser MLAT target — most fields are absent because the underlying source provided less. Both forms are valid; client code should treat every field except hex, type, and event_type as optional.
Identity
| Field | Type | Description |
|---|---|---|
event_type | string | Discriminator for future event kinds. Currently always "position". |
hex | string | ICAO 24-bit address (e.g. "a1b2c3"). Prefixed with ~ for a non-ICAO address. |
type | string | How this aircraft's data was obtained — see Source types below. |
flight | string | Callsign or flight number. Fixed 8-character field, space-padded (e.g. "BMA551 ") — trim trailing whitespace before use. |
r | string | Registration / tail number. |
t | string | Aircraft type code (e.g. B38M, A320). |
dbFlags | number | Database flags bitfield. |
squawk | string | Transponder squawk code (e.g. "1200"). |
emergency | string | Emergency status: none, general, lifeguard, minfuel, nordo, unlawful, downed, reserved. |
category | string | Aircraft category based on ADS-B emitter category (e.g. "A1" light, "A5" heavy). |
Source types
The type field tells you how each aircraft's data was obtained, which is your best cue to its accuracy. The most common — and most precise — is adsb_icao: the position is broadcast directly by the aircraft. Other types are derived from ground stations, other receivers, or radar, and vary in accuracy and update rate.
A quick naming guide: a _icao suffix means the aircraft is identified by its real 24-bit ICAO address; an _other suffix means a non-ICAO address (often anonymised or temporary).
type | What it means |
|---|---|
adsb_icao | Position broadcast directly by the aircraft's ADS-B transponder. The most common and most accurate source. |
adsb_icao_nt | ADS-B from a non-transponder emitter (e.g. a ground vehicle), real ICAO address. |
adsb_other | ADS-B from a transponder using a non-ICAO (e.g. anonymised) address. |
adsr_icao | ADS-R: an ADS-B report originally sent on another link (e.g. UAT) and rebroadcast by a ground station; real ICAO address. |
adsr_other | Same as adsr_icao but with a non-ICAO address. |
tisb_icao | TIS-B: a ground station relaying traffic info about a non-ADS-B aircraft (e.g. one seen by radar); real ICAO address. |
tisb_other | TIS-B about a non-ADS-B target using a non-ICAO address. |
tisb_trackfile | TIS-B about a target identified only by a radar track/file number (typically primary or Mode A/C radar). |
adsc | ADS-C: position reported over a long-range satellite link, typically over oceans; updates are infrequent (minutes apart). |
mlat | Multilateration: position computed from the timing differences of a Mode S signal across several ground receivers. |
mode_s | Mode S transponder data only (identity, altitude, etc.) — this source carries no position. |
other | Miscellaneous data; source and quality unknown. |
Position
lat and lon are the aircraft's current position; the other fields tell you how accurate that position is and what to fall back on when it isn't available.
| Field | Type | Description |
|---|---|---|
lat | number | Current latitude, in decimal degrees. |
lon | number | Current longitude, in decimal degrees. |
nic | number | Navigation Integrity Category — how trustworthy the position is, on a 0–11 scale; higher is better. |
rc | number | Radius of Containment, in metres — the aircraft is within this distance of the reported point; smaller is more precise. |
seen_pos | number | How many seconds ago this position was measured (relative to now — see Timestamps). |
rr_lat | number | Rough fallback latitude, estimated from which ground receivers heard the aircraft — low precision; use only when nothing better is available. |
rr_lon | number | Rough fallback longitude (see rr_lat). |
lastPosition | object | The last known precise position, used when no current one is available. Contains lat, lon, nic, rc, seen_pos — its seen_pos is the age, which can be up to 14 days. |
When lat/lon are absent
A record is emitted as soon as any message is heard from an aircraft — even before a valid position is available — so it is normal to receive records with no lat/lon. This happens when the aircraft is tracked via Mode S only, or when its last fix has aged out (current lat/lon are dropped once the position is older than ~60 seconds). When this happens you may still have:
lastPosition— the last precise fix, with its ownseen_posgiving the age (can be up to 14 days old). Use it when a stale position is acceptable, and always check the age.rr_lat/rr_lon— a rough position derived from receiver geometry (low precision), present when no ADS-B/MLAT fix is available.
If your pipeline only wants live positions, dropping records that lack lat/lon is a reasonable and expected choice. A typical "best available position" helper:
function pickPosition(r: AircraftRecord) {
if (r.lat != null && r.lon != null) return { lat: r.lat, lon: r.lon, stale: false };
if (r.lastPosition) return { lat: r.lastPosition.lat, lon: r.lastPosition.lon, stale: true };
return null; // no usable position — drop, or use rr_lat/rr_lon as a rough fallback
}
Altitude
| Field | Type | Description |
|---|---|---|
alt_baro | number | "ground" | Barometric altitude in feet, or the string "ground" when the aircraft reports it is on the surface. |
alt_geom | number | Geometric (GNSS) altitude in feet. |
alt_baro is the one field whose JSON type varies, so handle it as a union:
- A number (feet) — e.g.
35000— when a reliable barometric altitude is available. - The string
"ground"when the aircraft's transponder reports an on-surface (air/ground) state. This is not the same as "altitude is 0" — it is a distinct surface indicator. Barometric altitude near the ground is unreliable, so the surface state is reported as this sentinel rather than a misleading number. - Absent when no reliable barometric altitude is available and the aircraft is not reporting on-ground — there is no
nullplaceholder, the key is simply omitted.
A typical way to collapse it to a numeric altitude plus an on-ground flag:
function altitude(altBaro: number | "ground" | undefined) {
if (altBaro === "ground") return { altFt: 0, onGround: true };
if (typeof altBaro === "number") return { altFt: altBaro, onGround: false };
return { altFt: null, onGround: false }; // absent — unknown
}
Movement
| Field | Type | Description |
|---|---|---|
gs | number | Ground speed in knots. |
ias | number | Indicated airspeed in knots. |
tas | number | True airspeed in knots. |
mach | number | Mach number. |
track | number | Track angle over ground in degrees (0-360). |
calc_track | number | Calculated track (present when track is unavailable). |
track_rate | number | Rate of change of track in degrees/second. |
roll | number | Roll angle in degrees (negative = left roll). |
mag_heading | number | Magnetic heading in degrees. |
true_heading | number | True heading in degrees. |
baro_rate | number | Barometric vertical rate in feet/minute. |
geom_rate | number | Geometric vertical rate in feet/minute. |
Navigation & Autopilot
| Field | Type | Description |
|---|---|---|
nav_qnh | number | Altimeter setting (QNH/QFE) in hPa. |
nav_altitude_mcp | number | Altitude selected on the Mode Control Panel / FCU, in feet. |
nav_altitude_fms | number | Altitude selected by the Flight Management System, in feet. |
nav_heading | number | Selected heading from the autopilot, in degrees. |
nav_modes | string[] | Engaged automation modes (e.g. ["autopilot","vnav","lnav"]). |
Atmospheric (derived)
| Field | Type | Description |
|---|---|---|
wd | number | Wind direction in degrees. |
ws | number | Wind speed in knots. |
oat | number | Outside (static) air temperature in Celsius. Derived from Mach and true airspeed — unreliable at low speed (the calculation is inhibited below ~Mach 0.4), so occasional out-of-range values appear; sanity-filter before use. |
tat | number | Total air temperature in Celsius. Same derived-value caveat as oat. |
GPS Integrity
| Field | Type | Description |
|---|---|---|
gpsOkBefore | number | Unix timestamp (seconds) of last reliable ADS-B position before GPS degradation was detected. |
gpsOkLat | number | Last known latitude before GPS was lost. |
gpsOkLon | number | Last known longitude before GPS was lost. |
Data Quality & Integrity
| Field | Type | Description |
|---|---|---|
version | number | ADS-B version (0, 1, or 2). |
nic_baro | number | Navigation Integrity Category for barometric altitude. |
nac_p | number | Navigation Accuracy Category for position. |
nac_v | number | Navigation Accuracy Category for velocity. |
sil | number | Source Integrity Level. |
sil_type | string | SIL interpretation: unknown, perhour, persample. |
gva | number | Geometric Vertical Accuracy. |
sda | number | System Design Assurance. |
alert | number | Transponder alert flag. |
spi | number | Special Position Identification flag. |
Source Indicators
| Field | Type | Description |
|---|---|---|
mlat | string[] | Names of the fields whose values were derived from MLAT. Entries are source labels, which differ slightly from the JSON keys (e.g. altitude → alt_baro, callsign → flight). Always present; [] when none. |
tisb | string[] | Names of the fields whose values were derived from TIS-B (same label convention as mlat). Always present; [] when none. |
Timing & Metadata
| Field | Type | Description |
|---|---|---|
now | number | Unix timestamp in seconds (millisecond precision, e.g. 1743600000.123) marking when this record was generated on the server. Carried on every record — see Timestamps. |
seen | number | Seconds since last message of any type, relative to now. |
seen_pos | number | Seconds since last position update, relative to now. |
messages | number | Total Mode S messages received from this aircraft. |
rssi | number | Signal strength in dBFS. |
ACAS / TCAS
| Field | Type | Description |
|---|---|---|
acas_ra | object | ACAS Resolution Advisory data (experimental, subject to change). Contains: utc, unix_timestamp, bytes, ara, rat, mte, rac, advisory_complement, advisory, tti, threat_id_hex. |
Record model (TypeScript)
The complete record contract, ready to copy into a client. Fields without ? are emitted on every record; everything with ? is omitted when unavailable (never null). alt_baro is the one union type. This is the full payload — there are no other fields in this feed.
interface AircraftRecord {
// ---- always present ----
event_type: "position"; // discriminator for future event kinds
hex: string; // ICAO 24-bit address; "~" prefix = non-ICAO address
type: string; // source type, e.g. "adsb_icao", "mlat", "mode_s"
now: number; // server timestamp for this record (Unix seconds, ms precision)
messages: number; // total messages received from this aircraft
seen: number; // seconds since last message of any type
rssi: number; // signal strength (dBFS)
mlat: string[]; // field names sourced from MLAT ([] when none)
tisb: string[]; // field names sourced from TIS-B ([] when none)
// ---- identity (optional) ----
flight?: string; // callsign / flight number (8-char, space-padded)
r?: string; // registration / tail number
t?: string; // aircraft type code, e.g. "B738"
dbFlags?: number; // database flags bitfield
squawk?: string; // transponder code, e.g. "1200"
emergency?: string; // none|general|lifeguard|minfuel|nordo|unlawful|downed|reserved
category?: string; // emitter category, e.g. "A3"
// ---- position (optional) ----
lat?: number;
lon?: number;
nic?: number; // navigation integrity category (0-11, higher = better)
rc?: number; // radius of containment (metres, smaller = better)
seen_pos?: number; // seconds since last position update
rr_lat?: number; // rough receiver-derived latitude (low precision)
rr_lon?: number; // rough receiver-derived longitude (low precision)
lastPosition?: LastPosition; // last precise fix when no current position
// ---- altitude (optional) ----
alt_baro?: number | "ground"; // feet, or "ground" on the surface
alt_geom?: number; // geometric (GNSS) altitude, feet
// ---- movement (optional) ----
gs?: number; // ground speed (knots)
ias?: number; // indicated airspeed (knots)
tas?: number; // true airspeed (knots)
mach?: number;
track?: number; // track over ground (degrees, 0-360)
calc_track?: number; // calculated track when `track` unavailable
track_rate?: number; // degrees/second
roll?: number; // degrees (negative = left)
mag_heading?: number;
true_heading?: number;
baro_rate?: number; // barometric vertical rate (ft/min)
geom_rate?: number; // geometric vertical rate (ft/min)
// ---- navigation & autopilot (optional) ----
nav_qnh?: number; // altimeter setting (hPa)
nav_altitude_mcp?: number;
nav_altitude_fms?: number;
nav_heading?: number;
nav_modes?: string[]; // autopilot|vnav|althold|approach|lnav|tcas
// ---- atmospheric, derived (optional) ----
wd?: number; // wind direction (degrees)
ws?: number; // wind speed (knots)
oat?: number; // outside air temp (C)
tat?: number; // total air temp (C)
// ---- GPS integrity (optional) ----
gpsOkBefore?: number;
gpsOkLat?: number;
gpsOkLon?: number;
// ---- data quality (optional) ----
version?: number; // ADS-B version (0,1,2)
nic_baro?: number;
nac_p?: number;
nac_v?: number;
sil?: number;
sil_type?: string; // unknown|perhour|persample
gva?: number;
sda?: number;
alert?: number;
spi?: number;
// ---- ACAS / TCAS (optional, experimental) ----
acas_ra?: AcasRa;
}
interface LastPosition {
lat: number;
lon: number;
nic?: number;
rc?: number;
seen_pos: number; // age of this fix in seconds — can be up to 14 days
}
interface AcasRa {
utc?: string;
unix_timestamp?: number;
bytes?: string;
ARA?: string;
RAT?: string;
MTE?: string;
RAC?: string;
advisory_complement?: string;
advisory?: string;
TTI?: string;
threat_id_hex?: string;
}
Related
- Examples of how to use this — see Quickstart.