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
      )
../_images/opensky_rest_0_1.png

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'