The Problem

Clients that need programmatic access to Google Flights data must either scrape HTML (fragile) or rely on undocumented internal APIs (unstable). Maintaining a reliable, typed Python wrapper that hides the parsing details and offers a clean query object is the missing piece for many travel‑tech services.

What This Does

fast-flights provides a strongly‑typed wrapper around Google Flights. The public API lives in fast_flights/__init__.py, exposing FlightQuery, Passengers, create_query, and get_flights. Query objects are assembled in fast_flights/querying.py (pb, to_bytes, url, params) and passed to fast_flights/fetcher.py where get_flights orchestrates the request‑response cycle. Optional integrations (Bright Data, SearchApi) are in fast_flights/integrations/, each subclassing the base integration in fast_flights/integrations/base.py.

How It Is Wired

Execution begins when a consumer calls get_flights(query, integration=…) (defined in fast_flights/fetcher.py).

  1. get_flightsfetch_flights_html (same file) builds the request URL via url (querying.py) and serialises the query with to_bytes.
  2. fetch_flights_htmlfetch_html (integrations/base.py) performs the outbound HTTP GET. fetch_html pulls credentials with get_env and respects the chosen integration class.
  3. fetch_html returns raw HTML/JS payload → parse (fast_flights/parser.py) which calls parse_js.
  4. parse_js constructs model objects (Airport, SimpleDatetime, etc.) from the protobuf‑derived data (fast_flights/pb/flights_pb2.py).
  5. The result list is transformed by to_result_model in fast_flights/integrations/searchapi.py (when using SearchApi) or by the generic mapper in fetcher.py for the default path.

Key hubs:

  • fast_flights/querying.py (imported by 4 modules, 14 functions) builds the request.
  • fast_flights/integrations/base.py (2 callers, makes the only network call).
  • fast_flights/fetcher.py (5 functions, orchestrates the flow).

No circular imports were detected; the call graph has 67 internal edges, with create_query, FlightQuery, to_bytes, and Airport each invoked from four distinct locations, giving them the widest blast radius.

How To Use It

# Clone and install the package locally
git clone https://github.com/moses-y/flights
cd flights
pip install -e .          # installs fast_flights and its deps
from fast_flights import FlightQuery, Passengers, create_query, get_flights

query = create_query(
    flights=[FlightQuery(date="2024-12-01", from_airport="NYC", to_airport="LON")],
    seat="economy",
    passengers=Passengers(adults=1),
    language="en-US",
)

result = get_flights(query)          # default (no integration)
# result is a list of typed flight objects

If using Bright Data or SearchApi, instantiate the integration class (BrightData(zone="...") or SearchApi()) and pass it to get_flights. Those classes read required secrets via fast_flights/integrations/base.get_env, so set the appropriate environment variables before runtime.

Real‑World Use

A travel‑booking backend can call create_query for each itinerary, invoke get_flights, and store the returned Flight objects (with price, airline, carbon emissions) in its own database. The strong typing eliminates ad‑hoc dict handling and the single‑function entry point (get_flights) makes it easy to wrap in an async task queue.

Code Health & Issues

  • High – Pin GitHub Action versions.github/workflows/*.yml uses pypa/gh-action-pypi-publish@release/v1. Pin to a commit SHA.
  • High – Missing lockfilepyproject.toml present without poetry.lock/requirements.lock. Commit a lockfile to freeze transitive deps.
  • High – CI never runs tests – Workflows contain no test step despite four test files. Add a pytest step.
  • Medium – Enable Dependabot – No auto‑update config; add .github/dependabot.yml.
  • Medium – No vulnerability scan – Add dependency-review-action or osv-scanner to PR checks.
  • Medium – Checkout persists token – In python-publish.yml set persist-credentials: false.
  • Low – No job timeout – Add timeout-minutes to docs.yml jobs.
  • High – Oversized generated enumenums/_generated_enum.py (3,313 lines) should be split into logical groups.
  • Medium – Duplicated test code – Repeated 6‑line block in tests/general.py and tests/searchapi.py; extract a helper module.

Dependency note: protobuf >=5.27.0 is two major versions behind the latest 7.x release; consider updating to avoid compatibility surprises.

The Bottom Line

fast-flights delivers a clean, typed interface for Google Flights data with a modest codebase and clear separation of concerns. The core request‑response path is well‑encapsulated, but the repo lacks a locked dependency set, proper CI test execution, and has a few maintainability pain points (large generated enum, duplicated test helpers). It is suitable for teams comfortable with Python packaging and willing to address the CI and dependency hygiene gaps before production use.