How to access ADS-B data from OpenSky live API?
Warning
OpenSky data are subject to particular terms of use. In particular, if you plan to use data for commercial purposes, you should contact them.
Anonymous access to the OpenSky live API is possible, but functionalities may be limited. The first thing to do once you have an account is to put your credentials in you configuration file. Add the following lines to the [opensky] section of your configuration file.
[opensky]
username =
password =
You can check the path to your configuration file here. The path is different according to OS versions so do not assume anything and check the contents of the variable.
>>> import traffic
>>> traffic.config_file
PosixPath('/home/xo/.config/traffic/traffic.conf')
State vectors
The most basic usage for the OpenSky REST API is to get the instant position for all aircraft. This part actually does not require authentication.
import matplotlib.pyplot as plt
import pandas as pd
from cartes.crs import EuroPP
from cartes.utils.features import countries
from traffic.data import opensky
sv = opensky.api_states()
with plt.style.context('traffic'):
fig, ax = plt.subplots(subplot_kw=dict(projection=EuroPP()))
ax.add_feature(countries())
ax.gridlines()
ax.set_extent((-7, 15, 40, 55))
ax.spines['geo'].set_visible(False)
sv.plot(ax, s=10, color="#4c78a8")
now = pd.Timestamp("now", tz="utc")
ax.set_title(
f"Snapshot generated at {now:%Y-%m-%d %H:%MZ}",
fontsize=14
)

Flight tables
Flight tables are accessible by airport (use the ICAO code) given temporal bounds:
# Have you seen Santa Claus coming to Toulouse?
opensky.api_arrival("LFBO", "2021-12-24 20:00", "2021-12-25 06:00")
---------------------------------------------------------------------------
HTTPStatusError Traceback (most recent call last)
Cell In[2], line 2
1 # Have you seen Santa Claus coming to Toulouse?
----> 2 opensky.api_arrival("LFBO", "2021-12-24 20:00", "2021-12-25 06:00")
File ~/work/traffic/traffic/src/traffic/data/adsb/opensky.py:231, in OpenSky.api_arrival(self, airport, begin, end)
224 @copy_documentation(rest.REST.arrival)
225 def api_arrival(
226 self,
(...) 229 end: None | timelike = None,
230 ) -> pd.DataFrame:
--> 231 return self.rest_client.arrival(
232 airport if isinstance(airport, str) else airport.icao, begin, end
233 )
File ~/work/traffic/traffic/.venv/lib/python3.11/site-packages/pyopensky/rest.py:461, in REST.arrival(self, airport, begin, end)
458 else:
459 end_ts = to_datetime(end)
--> 461 json = self.get(
462 f"https://opensky-network.org/api/flights/arrival"
463 f"?begin={begin_ts.timestamp():.0f}&airport={airport}&"
464 f"end={end_ts.timestamp():.0f}"
465 )
467 return (
468 pd.DataFrame.from_records(json)
469 .convert_dtypes(dtype_backend="pyarrow")[
(...) 489 .sort_values("lastSeen")
490 )
File ~/work/traffic/traffic/.venv/lib/python3.11/site-packages/pyopensky/rest.py:118, in REST.get(self, query, retry)
116 if limit < 100:
117 _log.warning(f"Rate limiting: Only {limit} calls remaining")
--> 118 c.raise_for_status()
119 return c.json()
120 except httpx.HTTPStatusError:
File ~/work/traffic/traffic/.venv/lib/python3.11/site-packages/httpx/_models.py:829, in Response.raise_for_status(self)
827 error_type = error_types.get(status_class, "Invalid status code")
828 message = message.format(self, error_type=error_type)
--> 829 raise HTTPStatusError(message, request=request, response=self)
HTTPStatusError: Client error '403 ' for url 'https://opensky-network.org/api/flights/arrival?begin=1640376000&airport=LFBO&end=1640412000'
For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403
# Or maybe leaving?
opensky.api_departure("LFBO", "2021-12-24 20:00", "2021-12-25 06:00")
---------------------------------------------------------------------------
HTTPStatusError Traceback (most recent call last)
Cell In[3], line 2
1 # Or maybe leaving?
----> 2 opensky.api_departure("LFBO", "2021-12-24 20:00", "2021-12-25 06:00")
File ~/work/traffic/traffic/src/traffic/data/adsb/opensky.py:242, in OpenSky.api_departure(self, airport, begin, end)
235 @copy_documentation(rest.REST.departure)
236 def api_departure(
237 self,
(...) 240 end: None | timelike = None,
241 ) -> pd.DataFrame:
--> 242 return self.rest_client.departure(
243 airport if isinstance(airport, str) else airport.icao, begin, end
244 )
File ~/work/traffic/traffic/.venv/lib/python3.11/site-packages/pyopensky/rest.py:521, in REST.departure(self, airport, begin, end)
518 else:
519 end_ts = to_datetime(end)
--> 521 json = self.get(
522 f"https://opensky-network.org/api/flights/departure"
523 f"?begin={begin_ts.timestamp():.0f}&airport={airport}&"
524 f"end={end_ts.timestamp():.0f}"
525 )
527 return (
528 pd.DataFrame.from_records(json)
529 .convert_dtypes(dtype_backend="pyarrow")[
(...) 549 .sort_values("firstSeen")
550 )
File ~/work/traffic/traffic/.venv/lib/python3.11/site-packages/pyopensky/rest.py:118, in REST.get(self, query, retry)
116 if limit < 100:
117 _log.warning(f"Rate limiting: Only {limit} calls remaining")
--> 118 c.raise_for_status()
119 return c.json()
120 except httpx.HTTPStatusError:
File ~/work/traffic/traffic/.venv/lib/python3.11/site-packages/httpx/_models.py:829, in Response.raise_for_status(self)
827 error_type = error_types.get(status_class, "Invalid status code")
828 message = message.format(self, error_type=error_type)
--> 829 raise HTTPStatusError(message, request=request, response=self)
HTTPStatusError: Client error '403 ' for url 'https://opensky-network.org/api/flights/departure?begin=1640376000&airport=LFBO&end=1640412000'
For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403
A basic route database is also accessible through the REST API:
opensky.api_routes("AFR292")
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[4], line 1
----> 1 opensky.api_routes("AFR292")
AttributeError: 'OpenSky' object has no attribute 'api_routes'