flyitalyadsb 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ # Your API key never goes in git. Keep it in an environment variable or in one of these files.
2
+ .env
3
+ .env.*
4
+ !.env.example
5
+ *.key
6
+ api-key.txt
7
+ examples/esp32/planes-overhead/secrets.h
8
+
9
+ # Python
10
+ __pycache__/
11
+ *.py[cod]
12
+ .venv/
13
+ dist/
14
+
15
+ # Node
16
+ node_modules/
17
+
18
+ # Arduino / PlatformIO builds
19
+ build/
20
+ .pio/
21
+
22
+ # Editors and OS
23
+ .vscode/
24
+ .idea/
25
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nesso Labs S.r.l.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ Code and data are licensed separately.
2
+
3
+ The code of this package (flyitalyadsb, the Python client) is MIT licensed:
4
+ see LICENSE.
5
+
6
+ The flight data the API returns is NOT covered by the MIT licence. It is
7
+ published under Creative Commons Attribution-ShareAlike 4.0 (CC BY-SA 4.0)
8
+ and served under the API terms of service:
9
+ https://flyitalyadsb.com/en/terms/
10
+
11
+ Credit it where your users see the data:
12
+
13
+ Flight data: FlyItalyADSB (flyitalyadsb.com), CC BY-SA 4.0
@@ -0,0 +1,198 @@
1
+ Metadata-Version: 2.4
2
+ Name: flyitalyadsb
3
+ Version: 0.1.0
4
+ Summary: Official Python client for the FlyItalyADSB ADS-B API: live aircraft positions worldwide, history, overflights and events. Commercial use on every plan, Free included.
5
+ Project-URL: Homepage, https://flyitalyadsb.com/en/data/api/
6
+ Project-URL: Documentation, https://flyitalyadsb.com/en/data/api/docs/
7
+ Project-URL: Source, https://github.com/flyitalyadsb/adsb-api/tree/main/python
8
+ Project-URL: Issues, https://github.com/flyitalyadsb/adsb-api/issues
9
+ Project-URL: Plans and pricing, https://flyitalyadsb.com/en/data/api/#piani
10
+ Project-URL: MCP server, https://flyitalyadsb.com/en/data/mcp/
11
+ Project-URL: OpenAPI, https://flyitalyadsb.com/openapi.json
12
+ Author-email: FlyItalyADSB <info@flyitalyadsb.com>
13
+ License-Expression: MIT
14
+ License-File: LICENSE
15
+ License-File: NOTICE
16
+ Keywords: ads-b,adsb,aircraft,aircraft tracking,api client,aviation,flight data,flight tracking,mcp,military aircraft,mlat,mode-s,squawk
17
+ Classifier: Development Status :: 4 - Beta
18
+ Classifier: Intended Audience :: Developers
19
+ Classifier: Intended Audience :: Science/Research
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3 :: Only
23
+ Classifier: Programming Language :: Python :: 3.9
24
+ Classifier: Programming Language :: Python :: 3.10
25
+ Classifier: Programming Language :: Python :: 3.11
26
+ Classifier: Programming Language :: Python :: 3.12
27
+ Classifier: Programming Language :: Python :: 3.13
28
+ Classifier: Programming Language :: Python :: 3.14
29
+ Classifier: Programming Language :: Python :: 3.15
30
+ Classifier: Topic :: Internet :: WWW/HTTP
31
+ Classifier: Topic :: Scientific/Engineering :: GIS
32
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
33
+ Classifier: Typing :: Typed
34
+ Requires-Python: >=3.9
35
+ Description-Content-Type: text/markdown
36
+
37
+ # flyitalyadsb: official Python client for the FlyItalyADSB ADS-B API
38
+
39
+ **flyitalyadsb** is the official Python client for the [FlyItalyADSB](https://flyitalyadsb.com/en/data/api/?utm_source=pypi&utm_campaign=python-client) ADS-B API: live and historical aircraft positions as JSON for any point on Earth, from a community network of about 3,200 ADS-B and MLAT receivers. Commercial use is allowed on every plan, Free included. The Free key is self-serve and answers up to 500 km around a point; the Pro plan (€49/month) returns the whole world in one request. The data is unfiltered: military, PIA and LADD aircraft are flagged, not removed, and the network's own MLAT locates aircraft that don't broadcast a position. Beyond live positions there are per-aircraft history, overflights of a place, notable-traffic events and an MCP server for AI assistants. Standard library only (no dependencies), fully typed, Python 3.9+.
40
+
41
+ ```bash
42
+ pip install flyitalyadsb
43
+ ```
44
+
45
+ ## Quickstart
46
+
47
+ Get a free key with your email on the [API page](https://flyitalyadsb.com/en/data/api/?utm_source=pypi&utm_campaign=python-client#api-key) (no approval step), then:
48
+
49
+ ```python
50
+ from flyitalyadsb import Client
51
+
52
+ client = Client() # reads the key from FLYITALYADSB_API_KEY, or Client(api_key="...")
53
+
54
+ # Every aircraft within 25 km of London Heathrow, right now
55
+ for a in client.near(51.47, -0.45, 25):
56
+ print(a.callsign, a.registration, a.icao_type, a.altitude, "MIL" if a.military else "")
57
+
58
+ print(client.limits) # your plan and usage this month, from the X-FIA-* headers
59
+ ```
60
+
61
+ Keep the key out of your code and out of git: an environment variable, or your secret store.
62
+
63
+ ## Methods
64
+
65
+ Every method is one request on your key; the account calls through `request()` (`/me/location`, `/webhooks`) are not counted. Radii are in kilometres.
66
+
67
+ | Method | Endpoint | Returns |
68
+ | --- | --- | --- |
69
+ | `near(lat, lon, radius_km)` | `/lat/{lat}/lon/{lon}/dist/{km}` | `AircraftList`: every aircraft within the radius, anywhere on Earth |
70
+ | `world()` | `/lat/0/lon/0/dist/20040` | `AircraftList`: the whole world in one request (Pro and Business plans) |
71
+ | `by_icao(icao)` | `/icao/{hex}` | `Aircraft`, or `None` if it isn't seen now |
72
+ | `by_callsign(callsign)` | `/callsign/{callsign}` | `Aircraft` or `None` |
73
+ | `by_registration(registration)` | `/reg/{reg}` | `Aircraft` or `None` |
74
+ | `military()`, `pia()`, `ladd()` | `/mil`, `/pia`, `/ladd` | `AircraftList`: military, PIA and LADD aircraft seen now, network-wide |
75
+ | `squawk(code)` | `/sqk/{squawk}` | `AircraftList`: e.g. `7700`, `7600`, `7500`, network-wide |
76
+ | `aircraft_type(designator)` | `/type/{type}` | `AircraftList`: an ICAO type, e.g. `"A320"`, `"B738"`, `"EC35"` |
77
+ | `history(icao)` | `/history/{icao}` | `HistoryDates`: the UTC days with a track |
78
+ | `history(icao, day)` | `/history/{icao}/{date}` | `Trace` or `None`: one day's track, `positions()` for the points |
79
+ | `profile(icao)` | `/profile/{icao}` | `Profile` or `None`: identity, live status, history summary, links |
80
+ | `overflights(lat, lon, radius_km, start, end)` | `/overflights` | `Overflights`: the aircraft that flew over a place between two times |
81
+ | `events(lat, lon, radius_km, since=, until=, kinds=)` | `/events` | `Events`: emergencies, military and other notable traffic, up to 7 days back |
82
+ | `request(method, path, params=, body=)` | any other, e.g. `/me/location`, `/webhooks` | the parsed JSON |
83
+ | `request_key(email, found_via="pypi")` (a function) | `POST /keys` | asks for a free key: the address gets a one-time link. Never called for you |
84
+
85
+ `Aircraft` has typed fields with readable names (`callsign`, `registration`, `icao_type`, `lat`, `lon`, `altitude` in feet or `"ground"`, `ground_speed` in knots, `vertical_rate` in ft/min, `squawk`, `source` such as `adsb_icao` or `mlat`, `db_flags`) and the flags `military`, `interesting`, `pia`, `ladd`, `on_ground` and `from_mlat`. Every field the API sent stays available with its own name in `raw` and through `get()`, e.g. `a.get("nav_altitude_mcp")`. Lists are iterable and have `len()`. Every result keeps the full JSON in `raw`. The fields and units: [fields and units](https://flyitalyadsb.com/en/data/api/docs/fields/?utm_source=pypi&utm_campaign=python-client).
86
+
87
+ ```python
88
+ from datetime import datetime, timedelta, timezone
89
+
90
+ now = datetime.now(timezone.utc)
91
+
92
+ # What flew within 3 km of a place in the last 2 hours, with the lowest altitude in the circle
93
+ for o in client.overflights(45.4642, 9.19, 3, now - timedelta(hours=2), now):
94
+ print(o.closest_time, o.registration, o.icao_type, o.callsigns, o.min_alt_ft, o.closest_km)
95
+
96
+ # Emergencies and military traffic within 100 km in the last 24 hours
97
+ for e in client.events(45.54, 10.22, 100, kinds=["emergency", "military"]):
98
+ print(e.time, e.kind, e.reason, e.callsign, e.registration, e.map_url)
99
+
100
+ # One aircraft's days with a track, and its last day's track
101
+ dates = client.history("4ca7b5")
102
+ if dates.dates:
103
+ track = client.history("4ca7b5", dates.dates[-1])
104
+ print(len(track.positions()) if track else 0, "points")
105
+ ```
106
+
107
+ ## Plans and limits
108
+
109
+ Choose mostly by area: each request asks for the aircraft in a circle, and the largest circle depends on the plan. Commercial use is allowed on every plan, Free included.
110
+
111
+ | Plan | Price per month (before tax) | Requests/min (per key) | Requests/month | Radius per request | Overflights |
112
+ | --- | --- | --- | --- | --- | --- |
113
+ | Free | €0 | 30 | 300,000 | up to 500 km | 10 km, 6 h window |
114
+ | Starter | €9 | 60 | 1,000,000 | up to 1,000 km | 25 km, 24 h |
115
+ | Pro | €49 | 300 | 10,000,000 | whole world | 50 km, 24 h |
116
+ | Business | €249 | 1,000 | 50,000,000 | whole world | 50 km, 24 h |
117
+
118
+ - The Free plan also has a cap of 100 requests a minute per IP.
119
+ - A paid plan raises the limits of the key you already have.
120
+ - Requests refused for a limit are not counted, and nothing is ever billed beyond the plan.
121
+ - The monthly counter resets on the 1st. No plan includes an SLA: the service is best effort.
122
+ - Current prices and limits are always on the [plans page](https://flyitalyadsb.com/en/data/api/?utm_source=pypi&utm_campaign=python-client#piani).
123
+
124
+ `client.limits` (and `.limits` on every result) reports the key's state from the `X-FIA-Plan`, `X-FIA-Limit-Per-Min`, `X-FIA-Quota-Month` and `X-FIA-Used-Month` headers: `plan`, `limit_per_min`, `quota_month`, `used_month` and `remaining_month`.
125
+
126
+ ## Errors
127
+
128
+ | Exception | When | Useful attributes |
129
+ | --- | --- | --- |
130
+ | `PlanLimitError` | 403 or 429: a limit of the plan | `reason` (`"radius"`, `"overflights"`, `"paid_plan"`, `"rate_limit"`, `"monthly_quota"`), `max_radius_km`, `retry_after`, `resets`, `plans_url` |
131
+ | `AuthError` | 401: missing or invalid key | `help_url` |
132
+ | `NotFoundError` | 404 (the lookups return `None` instead) | |
133
+ | `ApiError` | any other error answer, e.g. 400 | `status`, `message`, `code`, `body`, `limits` |
134
+ | `TransportError` | no usable answer: network, timeout, not JSON | |
135
+
136
+ All of them are `FlyItalyADSBError`.
137
+
138
+ ```python
139
+ from flyitalyadsb import Client, PlanLimitError
140
+
141
+ client = Client(user_agent="my-app/1.0") # name your app in the User-Agent
142
+ try:
143
+ everything = client.world()
144
+ except PlanLimitError as e:
145
+ if e.reason == "radius": # Free and Starter: 500 and 1,000 km per request
146
+ print(f"Up to {e.max_radius_km:g} km on this plan; the whole world needs Pro: {e.plans_url}")
147
+ elif e.reason == "monthly_quota":
148
+ print("Monthly quota used up until", e.resets, e.plans_url)
149
+ else:
150
+ print(e)
151
+ ```
152
+
153
+ The client never hammers the API. On a 429 or 503 that carries `Retry-After` of at most `max_retry_wait` seconds (default 30), it waits once and tries again; otherwise it raises. Radius and monthly-quota errors are never retried. The timeout is 30 seconds by default (`Client(timeout=...)`).
154
+
155
+ ## What's in the data
156
+
157
+ - One record per aircraft in readsb's aircraft.json format: ICAO address, position, altitude, speed, track, vertical rate, squawk, category, and the military, PIA and LADD flags. Registration and ICAO type are present for about 99% of aircraft, callsign for about 98%.
158
+ - Unfiltered: military, PIA and LADD aircraft are flagged, not hidden. Positions from ADS-B and from the network's own MLAT, which covers many military aircraft.
159
+ - The picture is rebuilt every 2 seconds. Coverage follows the receivers, worldwide: check an area with the [coverage tool](https://flyitalyadsb.com/en/data/coverage/?utm_source=pypi&utm_campaign=python-client) before you build on it.
160
+ - History: per-aircraft daily tracks for every day since 2026-08-17, plus 2022 to 2024 with gaps. Overflights of a place since 2026-08-17.
161
+ - Not included: routes (departure and arrival airports), schedules and photos.
162
+
163
+ ## Licence and credit
164
+
165
+ The flight data is licensed [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/). The only thing asked is a credit with the licence where your users see the data (in the app, on the device or in its manual, on the product page), with a link to flyitalyadsb.com:
166
+
167
+ ```text
168
+ Flight data: FlyItalyADSB (flyitalyadsb.com), CC BY-SA 4.0
169
+ ```
170
+
171
+ The same line is `flyitalyadsb.ATTRIBUTION`. Share-alike covers the data and adapted versions of it (a dataset, feed or API built from it), not your product's code, artwork or design. Details: [using the data in a product](https://flyitalyadsb.com/en/data/products/using-the-data/?utm_source=pypi&utm_campaign=python-client) and the [terms of service](https://flyitalyadsb.com/en/terms/?utm_source=pypi&utm_campaign=python-client).
172
+
173
+ The code of this package is [MIT](https://github.com/flyitalyadsb/adsb-api/blob/main/python/LICENSE); the data it returns is not MIT (see [NOTICE](https://github.com/flyitalyadsb/adsb-api/blob/main/python/NOTICE)).
174
+
175
+ ## MCP server for AI assistants
176
+
177
+ The same data, with the same key, is available to AI assistants through an MCP server at `https://flyitalyadsb.com/mcp` (Streamable HTTP, listed in the official MCP registry as `com.flyitalyadsb/mcp`). On claude.ai: Connectors, Add custom connector, URL `https://flyitalyadsb.com/mcp`. In Claude Code:
178
+
179
+ ```bash
180
+ claude mcp add --transport http flyitalyadsb https://flyitalyadsb.com/mcp \
181
+ --header "X-Api-Key: $FLYITALYADSB_API_KEY"
182
+ ```
183
+
184
+ Guide: [MCP and AI agents](https://flyitalyadsb.com/en/data/mcp/?utm_source=pypi&utm_campaign=python-client).
185
+
186
+ ## Links
187
+
188
+ - [API page: plans and a free key](https://flyitalyadsb.com/en/data/api/?utm_source=pypi&utm_campaign=python-client)
189
+ - [API documentation](https://flyitalyadsb.com/en/data/api/docs/?utm_source=pypi&utm_campaign=python-client): [endpoints](https://flyitalyadsb.com/en/data/api/docs/endpoints/?utm_source=pypi&utm_campaign=python-client), [limits and errors](https://flyitalyadsb.com/en/data/api/docs/limits-and-errors/?utm_source=pypi&utm_campaign=python-client), [history](https://flyitalyadsb.com/en/data/api/docs/history/?utm_source=pypi&utm_campaign=python-client), [alerts and webhooks](https://flyitalyadsb.com/en/data/api/docs/alerts/?utm_source=pypi&utm_campaign=python-client), [commercial use](https://flyitalyadsb.com/en/data/api/docs/commercial-use/?utm_source=pypi&utm_campaign=python-client)
190
+ - [OpenAPI 3.1 spec](https://flyitalyadsb.com/openapi.json)
191
+ - [Examples and source on GitHub](https://github.com/flyitalyadsb/adsb-api) (curl, Python, Node.js, ESP32)
192
+ - [Service status](https://flyitalyadsb.com/en/status/?utm_source=pypi&utm_campaign=python-client) · [Contact](https://flyitalyadsb.com/en/contact/?utm_source=pypi&utm_campaign=python-client)
193
+
194
+ Found a bug in the client? [Open an issue](https://github.com/flyitalyadsb/adsb-api/issues).
195
+
196
+ ---
197
+
198
+ Flight data: FlyItalyADSB (flyitalyadsb.com), CC BY-SA 4.0. Service provided by Nesso Labs S.r.l.
@@ -0,0 +1,162 @@
1
+ # flyitalyadsb: official Python client for the FlyItalyADSB ADS-B API
2
+
3
+ **flyitalyadsb** is the official Python client for the [FlyItalyADSB](https://flyitalyadsb.com/en/data/api/?utm_source=pypi&utm_campaign=python-client) ADS-B API: live and historical aircraft positions as JSON for any point on Earth, from a community network of about 3,200 ADS-B and MLAT receivers. Commercial use is allowed on every plan, Free included. The Free key is self-serve and answers up to 500 km around a point; the Pro plan (€49/month) returns the whole world in one request. The data is unfiltered: military, PIA and LADD aircraft are flagged, not removed, and the network's own MLAT locates aircraft that don't broadcast a position. Beyond live positions there are per-aircraft history, overflights of a place, notable-traffic events and an MCP server for AI assistants. Standard library only (no dependencies), fully typed, Python 3.9+.
4
+
5
+ ```bash
6
+ pip install flyitalyadsb
7
+ ```
8
+
9
+ ## Quickstart
10
+
11
+ Get a free key with your email on the [API page](https://flyitalyadsb.com/en/data/api/?utm_source=pypi&utm_campaign=python-client#api-key) (no approval step), then:
12
+
13
+ ```python
14
+ from flyitalyadsb import Client
15
+
16
+ client = Client() # reads the key from FLYITALYADSB_API_KEY, or Client(api_key="...")
17
+
18
+ # Every aircraft within 25 km of London Heathrow, right now
19
+ for a in client.near(51.47, -0.45, 25):
20
+ print(a.callsign, a.registration, a.icao_type, a.altitude, "MIL" if a.military else "")
21
+
22
+ print(client.limits) # your plan and usage this month, from the X-FIA-* headers
23
+ ```
24
+
25
+ Keep the key out of your code and out of git: an environment variable, or your secret store.
26
+
27
+ ## Methods
28
+
29
+ Every method is one request on your key; the account calls through `request()` (`/me/location`, `/webhooks`) are not counted. Radii are in kilometres.
30
+
31
+ | Method | Endpoint | Returns |
32
+ | --- | --- | --- |
33
+ | `near(lat, lon, radius_km)` | `/lat/{lat}/lon/{lon}/dist/{km}` | `AircraftList`: every aircraft within the radius, anywhere on Earth |
34
+ | `world()` | `/lat/0/lon/0/dist/20040` | `AircraftList`: the whole world in one request (Pro and Business plans) |
35
+ | `by_icao(icao)` | `/icao/{hex}` | `Aircraft`, or `None` if it isn't seen now |
36
+ | `by_callsign(callsign)` | `/callsign/{callsign}` | `Aircraft` or `None` |
37
+ | `by_registration(registration)` | `/reg/{reg}` | `Aircraft` or `None` |
38
+ | `military()`, `pia()`, `ladd()` | `/mil`, `/pia`, `/ladd` | `AircraftList`: military, PIA and LADD aircraft seen now, network-wide |
39
+ | `squawk(code)` | `/sqk/{squawk}` | `AircraftList`: e.g. `7700`, `7600`, `7500`, network-wide |
40
+ | `aircraft_type(designator)` | `/type/{type}` | `AircraftList`: an ICAO type, e.g. `"A320"`, `"B738"`, `"EC35"` |
41
+ | `history(icao)` | `/history/{icao}` | `HistoryDates`: the UTC days with a track |
42
+ | `history(icao, day)` | `/history/{icao}/{date}` | `Trace` or `None`: one day's track, `positions()` for the points |
43
+ | `profile(icao)` | `/profile/{icao}` | `Profile` or `None`: identity, live status, history summary, links |
44
+ | `overflights(lat, lon, radius_km, start, end)` | `/overflights` | `Overflights`: the aircraft that flew over a place between two times |
45
+ | `events(lat, lon, radius_km, since=, until=, kinds=)` | `/events` | `Events`: emergencies, military and other notable traffic, up to 7 days back |
46
+ | `request(method, path, params=, body=)` | any other, e.g. `/me/location`, `/webhooks` | the parsed JSON |
47
+ | `request_key(email, found_via="pypi")` (a function) | `POST /keys` | asks for a free key: the address gets a one-time link. Never called for you |
48
+
49
+ `Aircraft` has typed fields with readable names (`callsign`, `registration`, `icao_type`, `lat`, `lon`, `altitude` in feet or `"ground"`, `ground_speed` in knots, `vertical_rate` in ft/min, `squawk`, `source` such as `adsb_icao` or `mlat`, `db_flags`) and the flags `military`, `interesting`, `pia`, `ladd`, `on_ground` and `from_mlat`. Every field the API sent stays available with its own name in `raw` and through `get()`, e.g. `a.get("nav_altitude_mcp")`. Lists are iterable and have `len()`. Every result keeps the full JSON in `raw`. The fields and units: [fields and units](https://flyitalyadsb.com/en/data/api/docs/fields/?utm_source=pypi&utm_campaign=python-client).
50
+
51
+ ```python
52
+ from datetime import datetime, timedelta, timezone
53
+
54
+ now = datetime.now(timezone.utc)
55
+
56
+ # What flew within 3 km of a place in the last 2 hours, with the lowest altitude in the circle
57
+ for o in client.overflights(45.4642, 9.19, 3, now - timedelta(hours=2), now):
58
+ print(o.closest_time, o.registration, o.icao_type, o.callsigns, o.min_alt_ft, o.closest_km)
59
+
60
+ # Emergencies and military traffic within 100 km in the last 24 hours
61
+ for e in client.events(45.54, 10.22, 100, kinds=["emergency", "military"]):
62
+ print(e.time, e.kind, e.reason, e.callsign, e.registration, e.map_url)
63
+
64
+ # One aircraft's days with a track, and its last day's track
65
+ dates = client.history("4ca7b5")
66
+ if dates.dates:
67
+ track = client.history("4ca7b5", dates.dates[-1])
68
+ print(len(track.positions()) if track else 0, "points")
69
+ ```
70
+
71
+ ## Plans and limits
72
+
73
+ Choose mostly by area: each request asks for the aircraft in a circle, and the largest circle depends on the plan. Commercial use is allowed on every plan, Free included.
74
+
75
+ | Plan | Price per month (before tax) | Requests/min (per key) | Requests/month | Radius per request | Overflights |
76
+ | --- | --- | --- | --- | --- | --- |
77
+ | Free | €0 | 30 | 300,000 | up to 500 km | 10 km, 6 h window |
78
+ | Starter | €9 | 60 | 1,000,000 | up to 1,000 km | 25 km, 24 h |
79
+ | Pro | €49 | 300 | 10,000,000 | whole world | 50 km, 24 h |
80
+ | Business | €249 | 1,000 | 50,000,000 | whole world | 50 km, 24 h |
81
+
82
+ - The Free plan also has a cap of 100 requests a minute per IP.
83
+ - A paid plan raises the limits of the key you already have.
84
+ - Requests refused for a limit are not counted, and nothing is ever billed beyond the plan.
85
+ - The monthly counter resets on the 1st. No plan includes an SLA: the service is best effort.
86
+ - Current prices and limits are always on the [plans page](https://flyitalyadsb.com/en/data/api/?utm_source=pypi&utm_campaign=python-client#piani).
87
+
88
+ `client.limits` (and `.limits` on every result) reports the key's state from the `X-FIA-Plan`, `X-FIA-Limit-Per-Min`, `X-FIA-Quota-Month` and `X-FIA-Used-Month` headers: `plan`, `limit_per_min`, `quota_month`, `used_month` and `remaining_month`.
89
+
90
+ ## Errors
91
+
92
+ | Exception | When | Useful attributes |
93
+ | --- | --- | --- |
94
+ | `PlanLimitError` | 403 or 429: a limit of the plan | `reason` (`"radius"`, `"overflights"`, `"paid_plan"`, `"rate_limit"`, `"monthly_quota"`), `max_radius_km`, `retry_after`, `resets`, `plans_url` |
95
+ | `AuthError` | 401: missing or invalid key | `help_url` |
96
+ | `NotFoundError` | 404 (the lookups return `None` instead) | |
97
+ | `ApiError` | any other error answer, e.g. 400 | `status`, `message`, `code`, `body`, `limits` |
98
+ | `TransportError` | no usable answer: network, timeout, not JSON | |
99
+
100
+ All of them are `FlyItalyADSBError`.
101
+
102
+ ```python
103
+ from flyitalyadsb import Client, PlanLimitError
104
+
105
+ client = Client(user_agent="my-app/1.0") # name your app in the User-Agent
106
+ try:
107
+ everything = client.world()
108
+ except PlanLimitError as e:
109
+ if e.reason == "radius": # Free and Starter: 500 and 1,000 km per request
110
+ print(f"Up to {e.max_radius_km:g} km on this plan; the whole world needs Pro: {e.plans_url}")
111
+ elif e.reason == "monthly_quota":
112
+ print("Monthly quota used up until", e.resets, e.plans_url)
113
+ else:
114
+ print(e)
115
+ ```
116
+
117
+ The client never hammers the API. On a 429 or 503 that carries `Retry-After` of at most `max_retry_wait` seconds (default 30), it waits once and tries again; otherwise it raises. Radius and monthly-quota errors are never retried. The timeout is 30 seconds by default (`Client(timeout=...)`).
118
+
119
+ ## What's in the data
120
+
121
+ - One record per aircraft in readsb's aircraft.json format: ICAO address, position, altitude, speed, track, vertical rate, squawk, category, and the military, PIA and LADD flags. Registration and ICAO type are present for about 99% of aircraft, callsign for about 98%.
122
+ - Unfiltered: military, PIA and LADD aircraft are flagged, not hidden. Positions from ADS-B and from the network's own MLAT, which covers many military aircraft.
123
+ - The picture is rebuilt every 2 seconds. Coverage follows the receivers, worldwide: check an area with the [coverage tool](https://flyitalyadsb.com/en/data/coverage/?utm_source=pypi&utm_campaign=python-client) before you build on it.
124
+ - History: per-aircraft daily tracks for every day since 2026-08-17, plus 2022 to 2024 with gaps. Overflights of a place since 2026-08-17.
125
+ - Not included: routes (departure and arrival airports), schedules and photos.
126
+
127
+ ## Licence and credit
128
+
129
+ The flight data is licensed [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/). The only thing asked is a credit with the licence where your users see the data (in the app, on the device or in its manual, on the product page), with a link to flyitalyadsb.com:
130
+
131
+ ```text
132
+ Flight data: FlyItalyADSB (flyitalyadsb.com), CC BY-SA 4.0
133
+ ```
134
+
135
+ The same line is `flyitalyadsb.ATTRIBUTION`. Share-alike covers the data and adapted versions of it (a dataset, feed or API built from it), not your product's code, artwork or design. Details: [using the data in a product](https://flyitalyadsb.com/en/data/products/using-the-data/?utm_source=pypi&utm_campaign=python-client) and the [terms of service](https://flyitalyadsb.com/en/terms/?utm_source=pypi&utm_campaign=python-client).
136
+
137
+ The code of this package is [MIT](https://github.com/flyitalyadsb/adsb-api/blob/main/python/LICENSE); the data it returns is not MIT (see [NOTICE](https://github.com/flyitalyadsb/adsb-api/blob/main/python/NOTICE)).
138
+
139
+ ## MCP server for AI assistants
140
+
141
+ The same data, with the same key, is available to AI assistants through an MCP server at `https://flyitalyadsb.com/mcp` (Streamable HTTP, listed in the official MCP registry as `com.flyitalyadsb/mcp`). On claude.ai: Connectors, Add custom connector, URL `https://flyitalyadsb.com/mcp`. In Claude Code:
142
+
143
+ ```bash
144
+ claude mcp add --transport http flyitalyadsb https://flyitalyadsb.com/mcp \
145
+ --header "X-Api-Key: $FLYITALYADSB_API_KEY"
146
+ ```
147
+
148
+ Guide: [MCP and AI agents](https://flyitalyadsb.com/en/data/mcp/?utm_source=pypi&utm_campaign=python-client).
149
+
150
+ ## Links
151
+
152
+ - [API page: plans and a free key](https://flyitalyadsb.com/en/data/api/?utm_source=pypi&utm_campaign=python-client)
153
+ - [API documentation](https://flyitalyadsb.com/en/data/api/docs/?utm_source=pypi&utm_campaign=python-client): [endpoints](https://flyitalyadsb.com/en/data/api/docs/endpoints/?utm_source=pypi&utm_campaign=python-client), [limits and errors](https://flyitalyadsb.com/en/data/api/docs/limits-and-errors/?utm_source=pypi&utm_campaign=python-client), [history](https://flyitalyadsb.com/en/data/api/docs/history/?utm_source=pypi&utm_campaign=python-client), [alerts and webhooks](https://flyitalyadsb.com/en/data/api/docs/alerts/?utm_source=pypi&utm_campaign=python-client), [commercial use](https://flyitalyadsb.com/en/data/api/docs/commercial-use/?utm_source=pypi&utm_campaign=python-client)
154
+ - [OpenAPI 3.1 spec](https://flyitalyadsb.com/openapi.json)
155
+ - [Examples and source on GitHub](https://github.com/flyitalyadsb/adsb-api) (curl, Python, Node.js, ESP32)
156
+ - [Service status](https://flyitalyadsb.com/en/status/?utm_source=pypi&utm_campaign=python-client) · [Contact](https://flyitalyadsb.com/en/contact/?utm_source=pypi&utm_campaign=python-client)
157
+
158
+ Found a bug in the client? [Open an issue](https://github.com/flyitalyadsb/adsb-api/issues).
159
+
160
+ ---
161
+
162
+ Flight data: FlyItalyADSB (flyitalyadsb.com), CC BY-SA 4.0. Service provided by Nesso Labs S.r.l.
@@ -0,0 +1,77 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "flyitalyadsb"
7
+ dynamic = ["version"]
8
+ description = "Official Python client for the FlyItalyADSB ADS-B API: live aircraft positions worldwide, history, overflights and events. Commercial use on every plan, Free included."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ license-files = ["LICENSE", "NOTICE"]
13
+ authors = [{ name = "FlyItalyADSB", email = "info@flyitalyadsb.com" }]
14
+ keywords = [
15
+ "ads-b",
16
+ "adsb",
17
+ "flight tracking",
18
+ "aviation",
19
+ "aircraft",
20
+ "mlat",
21
+ "api client",
22
+ "flight data",
23
+ "aircraft tracking",
24
+ "mode-s",
25
+ "military aircraft",
26
+ "squawk",
27
+ "mcp",
28
+ ]
29
+ classifiers = [
30
+ "Development Status :: 4 - Beta",
31
+ "Intended Audience :: Developers",
32
+ "Intended Audience :: Science/Research",
33
+ "Operating System :: OS Independent",
34
+ "Programming Language :: Python :: 3",
35
+ "Programming Language :: Python :: 3 :: Only",
36
+ "Programming Language :: Python :: 3.9",
37
+ "Programming Language :: Python :: 3.10",
38
+ "Programming Language :: Python :: 3.11",
39
+ "Programming Language :: Python :: 3.12",
40
+ "Programming Language :: Python :: 3.13",
41
+ "Programming Language :: Python :: 3.14",
42
+ "Programming Language :: Python :: 3.15",
43
+ "Topic :: Internet :: WWW/HTTP",
44
+ "Topic :: Scientific/Engineering :: GIS",
45
+ "Topic :: Software Development :: Libraries :: Python Modules",
46
+ "Typing :: Typed",
47
+ ]
48
+ dependencies = []
49
+
50
+ [project.urls]
51
+ Homepage = "https://flyitalyadsb.com/en/data/api/"
52
+ Documentation = "https://flyitalyadsb.com/en/data/api/docs/"
53
+ Source = "https://github.com/flyitalyadsb/adsb-api/tree/main/python"
54
+ Issues = "https://github.com/flyitalyadsb/adsb-api/issues"
55
+ "Plans and pricing" = "https://flyitalyadsb.com/en/data/api/#piani"
56
+ "MCP server" = "https://flyitalyadsb.com/en/data/mcp/"
57
+ OpenAPI = "https://flyitalyadsb.com/openapi.json"
58
+
59
+ [tool.hatch.version]
60
+ path = "src/flyitalyadsb/_version.py"
61
+
62
+ # Core metadata 2.4 (license expression and files) is all this package needs.
63
+ [tool.hatch.build.targets.wheel]
64
+ packages = ["src/flyitalyadsb"]
65
+ core-metadata-version = "2.4"
66
+
67
+ [tool.hatch.build.targets.sdist]
68
+ include = ["src/", "tests/", "README.md", "LICENSE", "NOTICE", "pyproject.toml"]
69
+ core-metadata-version = "2.4"
70
+
71
+ [tool.pytest.ini_options]
72
+ testpaths = ["tests"]
73
+ addopts = "-ra"
74
+
75
+ [tool.mypy]
76
+ strict = true
77
+ files = ["src"]
@@ -0,0 +1,84 @@
1
+ """Official Python client for the FlyItalyADSB ADS-B API.
2
+
3
+ Live aircraft positions as JSON for any point on Earth, from a community network of
4
+ ADS-B and MLAT receivers, plus history, overflights and notable-traffic events.
5
+ Commercial use is allowed on every plan, Free included. Standard library only.
6
+
7
+ >>> from flyitalyadsb import Client
8
+ >>> client = Client() # reads FLYITALYADSB_API_KEY
9
+ >>> for a in client.near(51.47, -0.45, 25):
10
+ ... print(a.callsign, a.registration, a.icao_type, a.altitude)
11
+
12
+ Docs: https://flyitalyadsb.com/en/data/api/docs/
13
+ Flight data: FlyItalyADSB (flyitalyadsb.com), CC BY-SA 4.0
14
+ """
15
+
16
+ from ._version import __version__
17
+ from .client import (
18
+ API_KEY_ENV,
19
+ BASE_URL,
20
+ SIGNUP_URL,
21
+ USER_AGENT,
22
+ WORLD_RADIUS_KM,
23
+ Client,
24
+ request_key,
25
+ )
26
+ from .errors import (
27
+ LIMITS_DOCS_URL,
28
+ PLANS_URL,
29
+ ApiError,
30
+ AuthError,
31
+ FlyItalyADSBError,
32
+ NotFoundError,
33
+ PlanLimitError,
34
+ TransportError,
35
+ )
36
+ from .models import (
37
+ Aircraft,
38
+ AircraftList,
39
+ Altitude,
40
+ Event,
41
+ Events,
42
+ HistoryDates,
43
+ Limits,
44
+ Overflight,
45
+ Overflights,
46
+ Profile,
47
+ Trace,
48
+ TracePoint,
49
+ )
50
+
51
+ #: The credit the data's licence asks for, where your users see the data.
52
+ ATTRIBUTION = "Flight data: FlyItalyADSB (flyitalyadsb.com), CC BY-SA 4.0"
53
+
54
+ __all__ = [
55
+ "API_KEY_ENV",
56
+ "ATTRIBUTION",
57
+ "BASE_URL",
58
+ "LIMITS_DOCS_URL",
59
+ "PLANS_URL",
60
+ "SIGNUP_URL",
61
+ "USER_AGENT",
62
+ "WORLD_RADIUS_KM",
63
+ "Aircraft",
64
+ "AircraftList",
65
+ "Altitude",
66
+ "ApiError",
67
+ "AuthError",
68
+ "Client",
69
+ "Event",
70
+ "Events",
71
+ "FlyItalyADSBError",
72
+ "HistoryDates",
73
+ "Limits",
74
+ "NotFoundError",
75
+ "Overflight",
76
+ "Overflights",
77
+ "PlanLimitError",
78
+ "Profile",
79
+ "Trace",
80
+ "TracePoint",
81
+ "TransportError",
82
+ "__version__",
83
+ "request_key",
84
+ ]
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"