opensky-cli 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.
- opensky_cli-0.1.0/.env.example +8 -0
- opensky_cli-0.1.0/.gitignore +16 -0
- opensky_cli-0.1.0/LICENSE +21 -0
- opensky_cli-0.1.0/PKG-INFO +231 -0
- opensky_cli-0.1.0/README.md +204 -0
- opensky_cli-0.1.0/create_video.py +747 -0
- opensky_cli-0.1.0/demo.gif +0 -0
- opensky_cli-0.1.0/opensky-demo.mp4 +0 -0
- opensky_cli-0.1.0/pyproject.toml +46 -0
- opensky_cli-0.1.0/src/opensky/__init__.py +3 -0
- opensky_cli-0.1.0/src/opensky/__main__.py +3 -0
- opensky_cli-0.1.0/src/opensky/_vendor/__init__.py +0 -0
- opensky_cli-0.1.0/src/opensky/_vendor/google_flights.py +489 -0
- opensky_cli-0.1.0/src/opensky/airports.py +183 -0
- opensky_cli-0.1.0/src/opensky/cache.py +49 -0
- opensky_cli-0.1.0/src/opensky/cli.py +690 -0
- opensky_cli-0.1.0/src/opensky/config.py +151 -0
- opensky_cli-0.1.0/src/opensky/data/conflict_zones.json +203 -0
- opensky_cli-0.1.0/src/opensky/data/demo_flights.json +3355 -0
- opensky_cli-0.1.0/src/opensky/display.py +358 -0
- opensky_cli-0.1.0/src/opensky/models.py +90 -0
- opensky_cli-0.1.0/src/opensky/providers/__init__.py +81 -0
- opensky_cli-0.1.0/src/opensky/providers/amadeus.py +150 -0
- opensky_cli-0.1.0/src/opensky/providers/duffel.py +122 -0
- opensky_cli-0.1.0/src/opensky/providers/google.py +111 -0
- opensky_cli-0.1.0/src/opensky/safety.py +138 -0
- opensky_cli-0.1.0/src/opensky/search.py +280 -0
- opensky_cli-0.1.0/tests/__init__.py +0 -0
- opensky_cli-0.1.0/tests/fixture_flights_blr_ham.json +3355 -0
- opensky_cli-0.1.0/tests/test_airports.py +73 -0
- opensky_cli-0.1.0/tests/test_cache.py +34 -0
- opensky_cli-0.1.0/tests/test_cli.py +160 -0
- opensky_cli-0.1.0/tests/test_config.py +96 -0
- opensky_cli-0.1.0/tests/test_dedup.py +76 -0
- opensky_cli-0.1.0/tests/test_display.py +192 -0
- opensky_cli-0.1.0/tests/test_integration.py +245 -0
- opensky_cli-0.1.0/tests/test_models.py +87 -0
- opensky_cli-0.1.0/tests/test_providers.py +300 -0
- opensky_cli-0.1.0/tests/test_safety.py +70 -0
- opensky_cli-0.1.0/tests/test_vendor.py +143 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Optional: Duffel API (free unlimited searches)
|
|
2
|
+
# Sign up at https://duffel.com
|
|
3
|
+
# OPENSKY_DUFFEL_TOKEN=duffel_test_xxxxx
|
|
4
|
+
|
|
5
|
+
# Optional: Amadeus API (free tier: 2,000 calls/month)
|
|
6
|
+
# Sign up at https://developers.amadeus.com
|
|
7
|
+
# OPENSKY_AMADEUS_KEY=your_api_key
|
|
8
|
+
# OPENSKY_AMADEUS_SECRET=your_api_secret
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Federico De Ponte
|
|
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,231 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: opensky-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The first agentic flight search engine. Searches hundreds of routes in minutes, not hours.
|
|
5
|
+
Project-URL: Homepage, https://github.com/federicodeponte/opensky
|
|
6
|
+
Project-URL: Repository, https://github.com/federicodeponte/opensky
|
|
7
|
+
Author: Federico De Ponte
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: cli,flight-search,flights,google-flights,price-comparison,travel
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Internet
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Requires-Dist: airportsdata>=20240101
|
|
19
|
+
Requires-Dist: curl-cffi>=0.7
|
|
20
|
+
Requires-Dist: diskcache>=5.6
|
|
21
|
+
Requires-Dist: httpx>=0.27
|
|
22
|
+
Requires-Dist: pydantic>=2.10
|
|
23
|
+
Requires-Dist: ratelimit>=2.2
|
|
24
|
+
Requires-Dist: rich>=13.0
|
|
25
|
+
Requires-Dist: typer>=0.15
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# opensky
|
|
29
|
+
|
|
30
|
+
The first agentic flight search engine. Define your origins, destinations, and dates, and opensky searches every combination for you, in minutes instead of hours.
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
$ opensky scan --config scan.toml
|
|
34
|
+
|
|
35
|
+
Scanning 6 origins x 6 destinations x 10 dates = 360 combos via google
|
|
36
|
+
|
|
37
|
+
Best per Destination
|
|
38
|
+
Destination Price Date Duration Route
|
|
39
|
+
Amsterdam €289 Tue Mar 17 11h 20m Bangkok → Amsterdam
|
|
40
|
+
Berlin €312 Thu Mar 12 12h 45m Kuala Lumpur → Berlin
|
|
41
|
+
Frankfurt €298 Wed Mar 11 11h 50m Bangkok → Frankfurt
|
|
42
|
+
Hamburg €357 Tue Mar 10 13h 10m Bangalore → Dubai → Hamburg
|
|
43
|
+
Munich €315 Fri Mar 13 12h 30m Delhi → Munich
|
|
44
|
+
Copenhagen €345 Mon Mar 16 13h 10m Singapore → Copenhagen
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Doing this manually on Google Flights would take 360 individual searches. opensky does it in one command.
|
|
48
|
+
|
|
49
|
+
## How it works
|
|
50
|
+
|
|
51
|
+
1. You define a search space: origins, destinations, date range
|
|
52
|
+
2. opensky searches every combination across up to three providers (Google Flights, Duffel, Amadeus)
|
|
53
|
+
3. Results are deduplicated, scored, and presented as a price matrix with the cheapest options highlighted
|
|
54
|
+
|
|
55
|
+
It also works for single route searches:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
opensky search bangalore hamburg tomorrow
|
|
59
|
+
opensky search BLR HAM next monday
|
|
60
|
+
opensky search BLR HAM mar 15
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Install
|
|
64
|
+
|
|
65
|
+
Requires Python 3.11+.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install opensky
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Or from source:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
git clone https://github.com/federicodeponte/opensky.git
|
|
75
|
+
cd opensky
|
|
76
|
+
python -m venv .venv && source .venv/bin/activate
|
|
77
|
+
pip install -e .
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Copy `.env.example` to `.env` and fill in any API keys you have (optional, Google Flights works without any keys).
|
|
81
|
+
|
|
82
|
+
## Quick demo
|
|
83
|
+
|
|
84
|
+
See what opensky does without any API keys or network calls:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
opensky demo
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+

|
|
91
|
+
|
|
92
|
+
## Usage
|
|
93
|
+
|
|
94
|
+
### Multi-route scan (the power feature)
|
|
95
|
+
|
|
96
|
+
Search every combination of origins, destinations, and dates at once.
|
|
97
|
+
|
|
98
|
+
#### Interactive setup
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
opensky config init
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
opensky config init
|
|
106
|
+
|
|
107
|
+
Where are you flying from? (comma-separated cities or codes): bangalore, delhi, bangkok
|
|
108
|
+
→ BLR (Bangalore), DEL (Delhi), BKK (Bangkok)
|
|
109
|
+
Where to? (comma-separated cities or codes): hamburg, frankfurt, amsterdam
|
|
110
|
+
→ HAM (Hamburg), FRA (Frankfurt), AMS (Amsterdam)
|
|
111
|
+
Start date (YYYY-MM-DD): mar 15
|
|
112
|
+
End date (YYYY-MM-DD): mar 25
|
|
113
|
+
Currency [EUR]:
|
|
114
|
+
|
|
115
|
+
Created scan.toml. Next: opensky scan --config scan.toml
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Then run:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
opensky scan --config scan.toml
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### Quick template
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
opensky config init --quick # dumps template, no prompts
|
|
128
|
+
# edit scan.toml with your routes and dates
|
|
129
|
+
opensky scan --config scan.toml
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
6 origins x 6 destinations x 10 dates = 360 searches, one command. You get:
|
|
133
|
+
- **Best per destination**: cheapest flight to each city, with date and route
|
|
134
|
+
- **Price matrix**: prices across all dates, cheapest highlighted
|
|
135
|
+
- **Stats**: total flights found, price range
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
opensky scan --config scan.toml --all-flights # show every flight, not just summary
|
|
139
|
+
opensky scan --config scan.toml --workers 5 # parallel workers (default: 3)
|
|
140
|
+
opensky scan --config scan.toml --json -o results.json
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Scans are cached. If interrupted, re-run the same command to resume where it left off.
|
|
144
|
+
|
|
145
|
+
#### Scan config
|
|
146
|
+
|
|
147
|
+
```toml
|
|
148
|
+
[search]
|
|
149
|
+
origins = ["BLR", "DEL", "BOM", "KUL", "BKK", "SIN"]
|
|
150
|
+
destinations = ["HAM", "FRA", "MUC", "BER", "AMS", "CPH"]
|
|
151
|
+
cabin = "economy"
|
|
152
|
+
currency = "EUR"
|
|
153
|
+
stops = "any"
|
|
154
|
+
|
|
155
|
+
[search.date_range]
|
|
156
|
+
start = "2026-03-10"
|
|
157
|
+
end = "2026-03-20"
|
|
158
|
+
|
|
159
|
+
[scoring]
|
|
160
|
+
price_weight = 1.0
|
|
161
|
+
duration_weight = 0.5
|
|
162
|
+
|
|
163
|
+
# Optional: add ground transit time for scoring
|
|
164
|
+
[connections]
|
|
165
|
+
final_destination = "Hamburg"
|
|
166
|
+
|
|
167
|
+
[connections.transit_hours]
|
|
168
|
+
HAM = 0
|
|
169
|
+
BER = 2
|
|
170
|
+
FRA = 4
|
|
171
|
+
|
|
172
|
+
[safety]
|
|
173
|
+
risk_threshold = "high_risk"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Single route search
|
|
177
|
+
|
|
178
|
+
Use city names, IATA codes, or friendly dates:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
opensky search bangalore hamburg tomorrow
|
|
182
|
+
opensky search BLR HAM next monday
|
|
183
|
+
opensky search BLR HAM mar 15 --class business
|
|
184
|
+
opensky search BLR HAM 2026-03-10 --source duffel
|
|
185
|
+
opensky search BLR HAM 2026-03-10 --json
|
|
186
|
+
opensky search BLR HAM 2026-03-10 --fresh
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Options:
|
|
190
|
+
- `--class` / `--cabin`: Travel class (economy, premium, business, first)
|
|
191
|
+
- `--stops`: Max stops (nonstop, 1, 2, or any)
|
|
192
|
+
- `--max-price`: Maximum price (0 = no limit)
|
|
193
|
+
- `--fresh` / `--no-cache`: Skip cached results
|
|
194
|
+
- `--source` / `--provider`: Flight data source (google, duffel, amadeus)
|
|
195
|
+
- `--include-risky`: Include flights through conflict zones
|
|
196
|
+
- `--json` / `--csv`: Machine-readable output
|
|
197
|
+
- `--output` / `-o`: Save results to file
|
|
198
|
+
- `--currency` / `-c`: Currency code (EUR, USD, GBP, etc.)
|
|
199
|
+
|
|
200
|
+
## Providers
|
|
201
|
+
|
|
202
|
+
opensky aggregates results from up to three flight data sources. When multiple providers are configured, results are deduplicated (same flight from two sources keeps the cheapest price).
|
|
203
|
+
|
|
204
|
+
| Provider | Env vars | Notes |
|
|
205
|
+
|----------|----------|-------|
|
|
206
|
+
| Google Flights | none (default) | Scrapes Google Flights. Needs residential IP. |
|
|
207
|
+
| [Duffel](https://duffel.com) | `OPENSKY_DUFFEL_TOKEN` | Free unlimited searches. |
|
|
208
|
+
| [Amadeus](https://developers.amadeus.com) | `OPENSKY_AMADEUS_KEY` + `OPENSKY_AMADEUS_SECRET` | Free tier: 2,000 calls/month. |
|
|
209
|
+
|
|
210
|
+
## Conflict zones
|
|
211
|
+
|
|
212
|
+
opensky ships with a conflict zone database. By default, flights through high-risk airspace are filtered out. Use `--include-risky` to see all options.
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
opensky zones # list active conflict zones
|
|
216
|
+
opensky zones --update # fetch latest data
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Limitations
|
|
220
|
+
|
|
221
|
+
- **Residential IP required**: Google Flights blocks datacenter IPs. Use `--proxy` on servers. Duffel and Amadeus work from any IP.
|
|
222
|
+
- **Rate limits**: All providers rate-limited to 10 req/sec. Default scan settings (3 workers, 1s delay) are conservative.
|
|
223
|
+
- **Price accuracy**: Prices may differ from airline websites. Always verify before booking.
|
|
224
|
+
|
|
225
|
+
## Credits
|
|
226
|
+
|
|
227
|
+
Flight data API based on [fli](https://github.com/punitarani/fli) by Punit Arani (MIT license). Airport metadata from [airportsdata](https://github.com/mborsetti/airportsdata).
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
MIT
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# opensky
|
|
2
|
+
|
|
3
|
+
The first agentic flight search engine. Define your origins, destinations, and dates, and opensky searches every combination for you, in minutes instead of hours.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
$ opensky scan --config scan.toml
|
|
7
|
+
|
|
8
|
+
Scanning 6 origins x 6 destinations x 10 dates = 360 combos via google
|
|
9
|
+
|
|
10
|
+
Best per Destination
|
|
11
|
+
Destination Price Date Duration Route
|
|
12
|
+
Amsterdam €289 Tue Mar 17 11h 20m Bangkok → Amsterdam
|
|
13
|
+
Berlin €312 Thu Mar 12 12h 45m Kuala Lumpur → Berlin
|
|
14
|
+
Frankfurt €298 Wed Mar 11 11h 50m Bangkok → Frankfurt
|
|
15
|
+
Hamburg €357 Tue Mar 10 13h 10m Bangalore → Dubai → Hamburg
|
|
16
|
+
Munich €315 Fri Mar 13 12h 30m Delhi → Munich
|
|
17
|
+
Copenhagen €345 Mon Mar 16 13h 10m Singapore → Copenhagen
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Doing this manually on Google Flights would take 360 individual searches. opensky does it in one command.
|
|
21
|
+
|
|
22
|
+
## How it works
|
|
23
|
+
|
|
24
|
+
1. You define a search space: origins, destinations, date range
|
|
25
|
+
2. opensky searches every combination across up to three providers (Google Flights, Duffel, Amadeus)
|
|
26
|
+
3. Results are deduplicated, scored, and presented as a price matrix with the cheapest options highlighted
|
|
27
|
+
|
|
28
|
+
It also works for single route searches:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
opensky search bangalore hamburg tomorrow
|
|
32
|
+
opensky search BLR HAM next monday
|
|
33
|
+
opensky search BLR HAM mar 15
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
Requires Python 3.11+.
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install opensky
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Or from source:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
git clone https://github.com/federicodeponte/opensky.git
|
|
48
|
+
cd opensky
|
|
49
|
+
python -m venv .venv && source .venv/bin/activate
|
|
50
|
+
pip install -e .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Copy `.env.example` to `.env` and fill in any API keys you have (optional, Google Flights works without any keys).
|
|
54
|
+
|
|
55
|
+
## Quick demo
|
|
56
|
+
|
|
57
|
+
See what opensky does without any API keys or network calls:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
opensky demo
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+

|
|
64
|
+
|
|
65
|
+
## Usage
|
|
66
|
+
|
|
67
|
+
### Multi-route scan (the power feature)
|
|
68
|
+
|
|
69
|
+
Search every combination of origins, destinations, and dates at once.
|
|
70
|
+
|
|
71
|
+
#### Interactive setup
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
opensky config init
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
opensky config init
|
|
79
|
+
|
|
80
|
+
Where are you flying from? (comma-separated cities or codes): bangalore, delhi, bangkok
|
|
81
|
+
→ BLR (Bangalore), DEL (Delhi), BKK (Bangkok)
|
|
82
|
+
Where to? (comma-separated cities or codes): hamburg, frankfurt, amsterdam
|
|
83
|
+
→ HAM (Hamburg), FRA (Frankfurt), AMS (Amsterdam)
|
|
84
|
+
Start date (YYYY-MM-DD): mar 15
|
|
85
|
+
End date (YYYY-MM-DD): mar 25
|
|
86
|
+
Currency [EUR]:
|
|
87
|
+
|
|
88
|
+
Created scan.toml. Next: opensky scan --config scan.toml
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Then run:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
opensky scan --config scan.toml
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
#### Quick template
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
opensky config init --quick # dumps template, no prompts
|
|
101
|
+
# edit scan.toml with your routes and dates
|
|
102
|
+
opensky scan --config scan.toml
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
6 origins x 6 destinations x 10 dates = 360 searches, one command. You get:
|
|
106
|
+
- **Best per destination**: cheapest flight to each city, with date and route
|
|
107
|
+
- **Price matrix**: prices across all dates, cheapest highlighted
|
|
108
|
+
- **Stats**: total flights found, price range
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
opensky scan --config scan.toml --all-flights # show every flight, not just summary
|
|
112
|
+
opensky scan --config scan.toml --workers 5 # parallel workers (default: 3)
|
|
113
|
+
opensky scan --config scan.toml --json -o results.json
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Scans are cached. If interrupted, re-run the same command to resume where it left off.
|
|
117
|
+
|
|
118
|
+
#### Scan config
|
|
119
|
+
|
|
120
|
+
```toml
|
|
121
|
+
[search]
|
|
122
|
+
origins = ["BLR", "DEL", "BOM", "KUL", "BKK", "SIN"]
|
|
123
|
+
destinations = ["HAM", "FRA", "MUC", "BER", "AMS", "CPH"]
|
|
124
|
+
cabin = "economy"
|
|
125
|
+
currency = "EUR"
|
|
126
|
+
stops = "any"
|
|
127
|
+
|
|
128
|
+
[search.date_range]
|
|
129
|
+
start = "2026-03-10"
|
|
130
|
+
end = "2026-03-20"
|
|
131
|
+
|
|
132
|
+
[scoring]
|
|
133
|
+
price_weight = 1.0
|
|
134
|
+
duration_weight = 0.5
|
|
135
|
+
|
|
136
|
+
# Optional: add ground transit time for scoring
|
|
137
|
+
[connections]
|
|
138
|
+
final_destination = "Hamburg"
|
|
139
|
+
|
|
140
|
+
[connections.transit_hours]
|
|
141
|
+
HAM = 0
|
|
142
|
+
BER = 2
|
|
143
|
+
FRA = 4
|
|
144
|
+
|
|
145
|
+
[safety]
|
|
146
|
+
risk_threshold = "high_risk"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Single route search
|
|
150
|
+
|
|
151
|
+
Use city names, IATA codes, or friendly dates:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
opensky search bangalore hamburg tomorrow
|
|
155
|
+
opensky search BLR HAM next monday
|
|
156
|
+
opensky search BLR HAM mar 15 --class business
|
|
157
|
+
opensky search BLR HAM 2026-03-10 --source duffel
|
|
158
|
+
opensky search BLR HAM 2026-03-10 --json
|
|
159
|
+
opensky search BLR HAM 2026-03-10 --fresh
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Options:
|
|
163
|
+
- `--class` / `--cabin`: Travel class (economy, premium, business, first)
|
|
164
|
+
- `--stops`: Max stops (nonstop, 1, 2, or any)
|
|
165
|
+
- `--max-price`: Maximum price (0 = no limit)
|
|
166
|
+
- `--fresh` / `--no-cache`: Skip cached results
|
|
167
|
+
- `--source` / `--provider`: Flight data source (google, duffel, amadeus)
|
|
168
|
+
- `--include-risky`: Include flights through conflict zones
|
|
169
|
+
- `--json` / `--csv`: Machine-readable output
|
|
170
|
+
- `--output` / `-o`: Save results to file
|
|
171
|
+
- `--currency` / `-c`: Currency code (EUR, USD, GBP, etc.)
|
|
172
|
+
|
|
173
|
+
## Providers
|
|
174
|
+
|
|
175
|
+
opensky aggregates results from up to three flight data sources. When multiple providers are configured, results are deduplicated (same flight from two sources keeps the cheapest price).
|
|
176
|
+
|
|
177
|
+
| Provider | Env vars | Notes |
|
|
178
|
+
|----------|----------|-------|
|
|
179
|
+
| Google Flights | none (default) | Scrapes Google Flights. Needs residential IP. |
|
|
180
|
+
| [Duffel](https://duffel.com) | `OPENSKY_DUFFEL_TOKEN` | Free unlimited searches. |
|
|
181
|
+
| [Amadeus](https://developers.amadeus.com) | `OPENSKY_AMADEUS_KEY` + `OPENSKY_AMADEUS_SECRET` | Free tier: 2,000 calls/month. |
|
|
182
|
+
|
|
183
|
+
## Conflict zones
|
|
184
|
+
|
|
185
|
+
opensky ships with a conflict zone database. By default, flights through high-risk airspace are filtered out. Use `--include-risky` to see all options.
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
opensky zones # list active conflict zones
|
|
189
|
+
opensky zones --update # fetch latest data
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Limitations
|
|
193
|
+
|
|
194
|
+
- **Residential IP required**: Google Flights blocks datacenter IPs. Use `--proxy` on servers. Duffel and Amadeus work from any IP.
|
|
195
|
+
- **Rate limits**: All providers rate-limited to 10 req/sec. Default scan settings (3 workers, 1s delay) are conservative.
|
|
196
|
+
- **Price accuracy**: Prices may differ from airline websites. Always verify before booking.
|
|
197
|
+
|
|
198
|
+
## Credits
|
|
199
|
+
|
|
200
|
+
Flight data API based on [fli](https://github.com/punitarani/fli) by Punit Arani (MIT license). Airport metadata from [airportsdata](https://github.com/mborsetti/airportsdata).
|
|
201
|
+
|
|
202
|
+
## License
|
|
203
|
+
|
|
204
|
+
MIT
|