# Flight Airport Comparator CLI ✈️ A Python CLI tool that helps you find the best departure airport for your destination by comparing direct flights from all airports in a country. **✅ NOW WITH WORKING FLIGHT DATA!** Uses fast-flights v3.0rc1 with SOCS cookie integration to successfully bypass Google's consent page. ## What It Does Answers the question: **"I want to fly to [DESTINATION]. Which airport in [COUNTRY] should I depart from — and when in the next 6 months does the best route open up?"** ### Key Features - 🌍 **Multi-Airport Comparison**: Automatically scans all airports in a country - 📅 **Seasonal Scanning**: Discover new routes and price trends across 6 months - ⚡ **Direct Flights Only**: Filters out connections automatically - 🆕 **New Route Detection**: Highlights routes that appear in later months - 🎨 **Beautiful Tables**: Rich terminal output with color and formatting - 🚀 **Fast & Concurrent**: Parallel API requests for quick results - ✅ **SOCS Cookie Integration**: Bypasses Google consent page for real flight data! - 💾 **Smart Caching**: SQLite cache reduces API calls and prevents rate limiting ## Installation ```bash # Clone or download this repository cd flight-comparator # Install fast-flights v3.0rc1 (REQUIRED for working flight data) pip install --upgrade git+https://github.com/AWeirdDev/flights.git # Install other dependencies pip install -r requirements.txt # Build airport database (runs automatically on first use) python airports.py ``` ### Requirements - Python 3.10+ - **fast-flights v3.0rc1** (install from GitHub, not PyPI) - Dependencies: click, rich, python-dateutil, primp ## Quick Test Verify it works with real flight data: ```bash python test_v3_with_cookies.py ``` Expected output: ``` ✅ SUCCESS! Found 1 flight option(s): 1. Ryanair Price: €89 BER → BRI 06:10 - 08:20 (130 min) ``` ## Usage ### Basic Examples **Single date query:** ```bash python main.py --to JFK --country DE --date 2026-06-15 ``` **Seasonal scan (6 months):** ```bash python main.py --to JFK --country DE ``` **Custom airport list:** ```bash python main.py --to JFK --from FRA,MUC,BER --date 2026-06-15 ``` **Dry run (preview without API calls):** ```bash python main.py --to JFK --country DE --dry-run ``` ### All Options ``` Options: --to TEXT Destination airport IATA code (e.g., JFK) [required] --country TEXT Origin country ISO code (e.g., DE, US) --date TEXT Departure date YYYY-MM-DD. Omit for seasonal scan. --window INTEGER Months to scan in seasonal mode (default: 6) --seat [economy|premium|business|first] Cabin class (default: economy) --adults INTEGER Number of passengers (default: 1) --sort [price|duration] Sort order (default: price) --from TEXT Comma-separated IATA codes (overrides --country) --top INTEGER Max results per airport (default: 3) --output [table|json|csv] Output format (default: table) --workers INTEGER Concurrency level (default: 5) --dry-run List airports and dates without API calls --help Show this message and exit. ``` ### Advanced Examples **Business class, sorted by duration:** ```bash python main.py --to SIN --country DE --date 2026-07-20 --seat business --sort duration ``` **Seasonal scan with 12-month window:** ```bash python main.py --to LAX --country GB --window 12 ``` **Output as JSON:** ```bash python main.py --to CDG --country NL --date 2026-05-10 --output json ``` **Force fresh queries (disable cache):** ```bash python main.py --to JFK --country DE --no-cache ``` **Custom cache threshold (48 hours):** ```bash python main.py --to JFK --country DE --cache-threshold 48 ``` ## How It Works 1. **Airport Resolution**: Loads airports for your country from the OpenFlights dataset 2. **Date Resolution**: Single date or generates monthly dates (15th of each month) 3. **Flight Search**: Queries Google Flights via fast-flights for each airport × date 4. **Filtering**: Keeps only direct flights (0 stops) 5. **Analysis**: Detects new connections in seasonal mode 6. **Formatting**: Presents results in beautiful tables, JSON, or CSV ## Seasonal Scan Mode When you omit `--date`, the tool automatically: - Queries one date per month (default: 15th) across the next 6 months - Detects routes that appear in later months but not earlier ones - Tags new connections with ✨ NEW indicator - Helps you discover seasonal schedule changes This is especially useful for: - Finding when summer routes start - Discovering new airline schedules - Comparing price trends over time ## Country Codes Common country codes: - 🇩🇪 DE (Germany) - 🇺🇸 US (United States) - 🇬🇧 GB (United Kingdom) - 🇫🇷 FR (France) - 🇪🇸 ES (Spain) - 🇮🇹 IT (Italy) - 🇳🇱 NL (Netherlands) - 🇦🇺 AU (Australia) - 🇯🇵 JP (Japan) [Full list of supported countries available in data/airports_by_country.json] ## Architecture ``` flight-comparator/ ├── main.py # CLI entrypoint (Click) ├── date_resolver.py # Date logic & new connection detection ├── airports.py # Airport data management ├── searcher.py # Flight search with concurrency ├── formatter.py # Output formatting (Rich tables, JSON, CSV) ├── data/ │ └── airports_by_country.json # Generated airport database ├── tests/ # Smoke tests for each module └── requirements.txt ``` ## Caching System The tool uses SQLite to cache flight search results, reducing API calls and preventing rate limiting. ### How It Works - **Automatic caching**: All search results are saved to `data/flight_cache.db` - **Cache hits**: If a query was made recently, results are retrieved instantly from cache - **Default threshold**: 24 hours (configurable with `--cache-threshold`) - **Cache indicator**: Shows `💾 Cache hit:` when using cached data ### Cache Management **View cache statistics:** ```bash python cache_admin.py stats ``` **Clean old entries (30+ days):** ```bash python cache_admin.py clean --days 30 ``` **Clear entire cache:** ```bash python cache_admin.py clear-all ``` ### CLI Options - `--cache-threshold N`: Set cache validity in hours (default: 24) - `--no-cache`: Force fresh API queries, ignore cache ### Benefits - ⚡ **Instant results** for repeated queries (0.0s vs 2-3s per query) - 🛡️ **Rate limit protection**: Avoid hitting Google's API limits - 💰 **Reduced API load**: Fewer requests = lower risk of being blocked - 📊 **Historical data**: Cache preserves price history ## Configuration Key constants in `date_resolver.py`: ```python SEARCH_WINDOW_MONTHS = 6 # Default seasonal scan window SAMPLE_DAY_OF_MONTH = 15 # Which day to query each month ``` You can override the window at runtime with `--window N`. ## Limitations - ⚠️ Relies on fast-flights scraping Google Flights (subject to rate limits and anti-bot measures) - ⚠️ EU users may encounter consent flow issues (use fallback mode, which is default) - ⚠️ Prices are as shown on Google Flights, not final booking prices - ⚠️ Seasonal scan queries only the 15th of each month as a sample - ⚠️ Large scans (many airports × months) can take 2-3 minutes ## Performance Single date scan: - ~20 airports: < 30s (with --workers 5) Seasonal scan (6 months): - ~20 airports: 2-3 minutes - Total requests: 120 (20 × 6) ## Testing Run smoke tests for each module: ```bash cd tests python test_date_resolver.py python test_airports.py python test_searcher.py python test_formatter.py ``` ## Troubleshooting **"fast-flights not installed"** ```bash pip install fast-flights ``` **"Country code 'XX' not found"** - Check the country code is correct (2-letter ISO code) - Verify it exists in `data/airports_by_country.json` **Slow performance** - Reduce `--window` for seasonal scans - Increase `--workers` (but watch out for rate limiting) - Use `--from` with specific airports instead of entire country **No results found** - Try a different date (some routes are seasonal) - Check the destination airport code is correct - Verify there actually are direct flights on that route ## License This tool is for personal use and research. Respect Google Flights' terms of service and rate limits. ## Credits - Uses [fast-flights](https://github.com/shmuelzon/fast-flights) for Google Flights scraping - Airport data from [OpenFlights](https://openflights.org/) - Built with [Click](https://click.palletsprojects.com/) and [Rich](https://rich.readthedocs.io/)