Skip to main content

Search Google Flights programmatically. Real prices, typed results, no API key.

Project description

swoop

PyPI Python License CI

Search Google Flights programmatically. Real prices, typed results, no API key.

from swoop import search

results = search("JFK", "LAX", "2026-06-15")
for flight in results.best:
    airline = ", ".join(flight.airline_names)
    print(f"${flight.price}{airline}")

[!NOTE] Swoop is not affiliated with Google. It calls undocumented RPC endpoints that can change without notice.

Swoop calls Google Flights' internal GetShoppingResults and GetBookingResults RPC endpoints — the same ones the web app uses when you search for flights. Requests use TLS fingerprint impersonation via primp to match a real browser session. Responses are deeply nested lists (matching an internal protobuf schema) decoded into typed Python dataclasses.

Perch uses Swoop in production to monitor booked flights for price drops, saving users an average of $247 per trip.


Install

pip install swoop-flights

# With CLI (adds `swoop` command)
pip install swoop-flights[cli]

CLI

swoop search JFK LAX 2026-06-15

# Search flights
swoop search JFK LAX 2026-06-15

# Nonstop, sorted by price
swoop search JFK LAX 2026-06-15 --nonstop --sort cheapest

# Roundtrip, business class
swoop search JFK LAX 2026-06-15 -r 2026-06-22 --cabin business

# JSON output for piping
swoop search JFK LAX 2026-06-15 -o json -q | jq '.results[0].price_usd'

# See fare tiers for search result #1
swoop book 1 JFK LAX 2026-06-15
More CLI examples
# Look up a specific flight
swoop flight DL2300 -f JFK -t LAX -d 2026-06-15

# CSV for spreadsheets
swoop search JFK LAX 2026-06-15 -o csv -q > flights.csv

# Filter by airline and time window
swoop search JFK LAX 2026-06-15 -a DL -a UA --depart-after 8 --depart-before 14

Run swoop search --help for all options.

Python API

One-way search

from swoop import search

results = search("SFO", "JFK", "2026-06-15")

# results.best  — top-ranked flights
# results.other — remaining flights
for flight in results.best:
    print(f"${flight.price}")
    print(f"  {flight.departure_airport}{flight.arrival_airport}")
    print(f"  {flight.airline_names}, {flight.stop_count} stops")
    print(f"  {flight.travel_time} min total")
More examples

Roundtrip search

results = search("SFO", "JFK", "2026-06-15", return_date="2026-06-22")
# Price in results is the roundtrip total

Cabin class and filters

from swoop import search, SORT_CHEAPEST

results = search(
    "LAX", "NRT", "2026-06-15",
    cabin="business",       # economy, premium-economy, business, first
    max_stops=0,            # nonstop only
    sort=SORT_CHEAPEST,     # cheapest first
    airlines=["NH", "JL"],  # filter to specific carriers
    earliest_departure=8,   # depart after 8am
    latest_departure=14,    # depart before 2pm
)

Booking details (fare options)

from swoop import search, get_booking_results

results = search("JFK", "LAX", "2026-06-15")
itinerary = results.best[0]

# Get fare tiers — just pass the itinerary
options = get_booking_results(itinerary)

for opt in options:
    print(f"${opt.price}{opt.brand_label} ({opt.fare_family})")

[!TIP] Google rate-limits aggressively. Use retries=3 in production — both search() and get_booking_results() support retries and timeout parameters with exponential backoff.

How it works

Swoop reverse-engineers the FlightsFrontendService RPC interface that powers Google Flights. Search parameters are encoded as nested JSON arrays matching Google's internal protobuf schema, then sent as HTTP POST requests. The HTTP client uses TLS fingerprint impersonation (via primp) so requests are indistinguishable from a real Chrome session.

Responses arrive as deeply nested list structures — no field names, just positional indices. Swoop's decoder walks these structures and maps them to typed Python dataclasses (Itinerary, Flight, Layover, CarbonEmissions, etc.) with named attributes.

graph LR
    A["search()"] --> B["RPC request"] --> C["Google Flights"] --> D["nested lists"] --> E["typed dataclasses"]
API reference

search(origin, destination, date, **kwargs)

Search Google Flights and return a SearchResult.

Parameter Type Default Description
origin str required Origin IATA code
destination str required Destination IATA code
date str required Departure date (YYYY-MM-DD)
return_date str | None None Return date for roundtrip
cabin str "economy" economy, premium-economy, business, first
adults int 1 Number of adults
max_stops int | None None None=any, 0=nonstop, 1=1 stop, 2=2 stops
sort int SORT_DEPARTURE_TIME Sort order constant
airlines list[str] | None None Filter by airline codes
include_basic_economy bool False Include basic economy fares (excluded by default so prices reflect Main Cabin)
timeout int 90 HTTP timeout in seconds
retries int 0 Retries on HTTP 429 with exponential backoff

Returns SearchResult | None. None means no results found.

get_booking_results(itinerary_or_token, **kwargs)

Get fare options for a specific itinerary. Pass an Itinerary object directly, or a booking token string with explicit origin, destination, date, and selected_legs. Returns list[BookingOption] with price, brand_label, brand_code, fare_family, etc. BookingOption supports both attribute access (opt.price) and dict-style access (opt["price"], opt.get("price")).

Result types

  • SearchResultbest: list[Itinerary], other: list[Itinerary], price_range: PriceRange | None
  • Itinerary — Full itinerary with price, flights, layovers, travel_time, booking_token, carbon_emissions
  • Flight — Segment details: airline, flight_number, aircraft, legroom, co2_grams, amenities
  • Layover — Stop info: minutes, airports, is_overnight
  • CarbonEmissionsthis_flight_grams, typical_for_route_grams, difference_percent

Constants

Constant Value Description
SORT_TOP 1 Google's default ranking
SORT_CHEAPEST 2 Cheapest first
SORT_DEPARTURE_TIME 3 By departure time
SORT_ARRIVAL_TIME 4 By arrival time
SORT_DURATION 5 Shortest first

Error handling

All exceptions inherit from SwoopError. Catch SwoopRateLimitError for HTTP 429, SwoopHTTPError for other HTTP failures, and SwoopParseError for response decoding issues.

Contributing

Issues and pull requests welcome at github.com/saraswatayu/swoop.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

swoop_flights-0.2.2.tar.gz (33.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

swoop_flights-0.2.2-py3-none-any.whl (39.9 kB view details)

Uploaded Python 3

File details

Details for the file swoop_flights-0.2.2.tar.gz.

File metadata

  • Download URL: swoop_flights-0.2.2.tar.gz
  • Upload date:
  • Size: 33.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for swoop_flights-0.2.2.tar.gz
Algorithm Hash digest
SHA256 62502a4ca1ba981b0a9639fe1ce193704cc376a5bb10e85bf34c69801e93809c
MD5 dab32426e25291666c6895094725cf1f
BLAKE2b-256 e4947f6506c16a3e4ff9f796c709b9be45fc7277d0e6fc6cac5cce33ec0b35b8

See more details on using hashes here.

File details

Details for the file swoop_flights-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: swoop_flights-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 39.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for swoop_flights-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 bf796e00ceb0c0ea551cfbccae8608da98c8f623c7fe3fa4a3a8a50485fd83bc
MD5 884ba05dd4f6e6919f4a438d2ad6daf3
BLAKE2b-256 84e050f3893c3b9319de2956553a7aa8cacfccf05f7861c60522b14f51695b63

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page