Filtering
Filters narrow the stream to only the aircraft you care about. They run server-side, so a tight filter reduces both bandwidth and per-batch processing on your client.
Filters apply at the moment a stream is opened and stay in effect for the duration of that session. To change what you receive, update the filter and reopen the stream — either by calling SubscriptionService.UpdateSubscription and reconnecting, or by passing a new filter when opening the next stream (depending on your client library).
Filter shape
A filter is a JSON document with a single root_group. A group combines a logical_operator with a list of leaf conditions and optional nested sub-groups:
{
"root_group": {
"logical_operator": "and",
"conditions": [
{ "property": "alt_baro", "operator": "lt", "value": "5000" }
],
"groups": []
}
}
A group has:
| Field | Description |
|---|---|
logical_operator | and or or — how the entries below are combined. |
conditions | Array of leaf conditions (see below). |
groups | Array of nested sub-groups, each itself a group with the same shape. |
A condition has:
| Field | Description |
|---|---|
property | The aircraft JSON field name (e.g. alt_baro, hex, flight, gs). See Aircraft for the full list. |
operator | One of the comparison operators listed below. |
value | The value to compare against, as a string (numeric values are accepted as numeric strings). |
Operators
| Operator | Description |
|---|---|
eq | Equals |
ne | Not equals |
gt | Greater than |
ge | Greater than or equal |
lt | Less than |
le | Less than or equal |
contains | String contains (case-insensitive) |
notcontains | String does not contain |
startswith | String starts with |
notstartswith | String does not start with |
endswith | String ends with |
notendswith | String does not end with |
isnull | Property is missing or null |
isnotnull | Property is present and not null |
String comparisons are case-insensitive. Numeric comparisons apply to fields whose values are numbers (alt_baro, gs, lat, lon, etc.). For alt_baro, the value "ground" is treated as 0 — so alt_baro lt 1000 will include grounded aircraft.
Examples
Aircraft below 5,000 ft
{
"root_group": {
"logical_operator": "and",
"conditions": [
{ "property": "alt_baro", "operator": "lt", "value": "5000" }
]
}
}
Airborne aircraft below 5,000 ft moving faster than 100 kt
Combines two conditions with and. Useful for excluding stationary or taxiing aircraft from a low-altitude filter.
{
"root_group": {
"logical_operator": "and",
"conditions": [
{ "property": "alt_baro", "operator": "lt", "value": "5000" },
{ "property": "alt_baro", "operator": "ne", "value": "ground" },
{ "property": "gs", "operator": "gt", "value": "100" }
]
}
}
Specific aircraft by ICAO hex
{
"root_group": {
"logical_operator": "or",
"conditions": [
{ "property": "hex", "operator": "eq", "value": "a1b2c3" },
{ "property": "hex", "operator": "eq", "value": "d4e5f6" }
]
}
}
Nested groups: heavy aircraft OR fast aircraft
Use the groups array on a parent group to combine sub-expressions with mixed and/or. Here: aircraft categorised as heavy (category A5), or any aircraft above Mach 0.85.
{
"root_group": {
"logical_operator": "or",
"groups": [
{
"logical_operator": "and",
"conditions": [
{ "property": "category", "operator": "eq", "value": "A5" }
]
},
{
"logical_operator": "and",
"conditions": [
{ "property": "mach", "operator": "gt", "value": "0.85" }
]
}
]
}
}
Aircraft type code matches a pattern
{
"root_group": {
"logical_operator": "and",
"conditions": [
{ "property": "t", "operator": "startswith", "value": "B7" }
]
}
}
Matches Boeing 7-series types (B737, B738, B744, B777, B788, etc.).
How to apply a filter
Call SubscriptionService.UpdateSubscription with the filter on the request, then open a new stream — the filter applies to subsequent StartStream calls.
The protobuf wire shape uses slightly different field names than the examples above:
| In examples above | On the wire (proto JSON) |
|---|---|
root_group | rootGroup |
logical_operator | op (with values "AND" or "OR") |
property | field |
operator | op |
Full grpcurl invocation that applies the "below 5,000 ft" filter from the first example:
grpcurl \
-import-path . -proto subscription.proto \
-H "client-id: <YOUR_CLIENT_ID>" \
-d '{
"subscriptionId": "<YOUR_SUBSCRIPTION_ID>",
"filters": {
"rootGroup": {
"op": "AND",
"conditions": [
{ "field": "alt_baro", "op": "lt", "value": "5000" }
]
}
}
}' \
stream.adsbexchange.com:443 \
jetnet.streaming.SubscriptionService/UpdateSubscription
The server responds with the updated Subscription message confirming the change. Reconnect your stream to start receiving filtered data.