Skip to main content

Google Flights price scraper. Search flights programmatically via the same RPC endpoints the web app uses.

Project description

swoop

Google Flights price scraper. Search flights programmatically using the same RPC endpoints the Google Flights web app uses.

from swoop import search

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

Install

pip install swoop-flights

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

CLI

Search Google Flights directly from the terminal:

# 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'

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

# Look up a specific flight
swoop flight DL2300 -f JFK -t LAX -d 2026-06-15

# See fare tiers for search result #1
swoop book 1 JFK LAX 2026-06-15

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

Output formats: table (default, colored), json, csv, brief. Use --help on any subcommand 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")

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
)

Time window filtering

results = search(
    "JFK", "LHR", "2026-06-15",
    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})")

You can also pass a booking token string with explicit parameters:

options = get_booking_results(
    itinerary.booking_token,
    origin="JFK",
    destination="LAX",
    date="2026-06-15",
    selected_legs=[
        [
            flight.departure_airport,
            f"{flight.departure_date[0]}-{flight.departure_date[1]:02d}-{flight.departure_date[2]:02d}",
            flight.arrival_airport,
            None,
            flight.airline,
            flight.flight_number,
        ]
        for flight in itinerary.flights
    ],
)

Retry and timeout

# Retry up to 3 times on HTTP 429 (rate limit) with exponential backoff
results = search("JFK", "LAX", "2026-06-15", retries=3, timeout=90)

# Same for booking results
options = get_booking_results(itinerary, retries=2, timeout=60)

Flight details

Each Itinerary contains detailed segment data:

results = search("JFK", "LAX", "2026-06-15")
for itinerary in results.best:
    for flight in itinerary.flights:
        print(f"{flight.airline} {flight.flight_number}")
        print(f"  {flight.departure_airport}{flight.arrival_airport}")
        print(f"  Aircraft: {flight.aircraft}")
        print(f"  Legroom: {flight.legroom}")
        if flight.co2_grams:
            print(f"  CO₂: {flight.co2_grams}g")

    if itinerary.carbon_emissions:
        ce = itinerary.carbon_emissions
        print(f"  Route emissions: {ce.difference_percent}% vs typical")

    if results.price_range:
        print(f"  Price range: ${results.price_range.low}–${results.price_range.high}")

Error handling

from swoop import search, SwoopHTTPError, SwoopRateLimitError, SwoopParseError

try:
    results = search("JFK", "LAX", "2026-06-15")
except SwoopRateLimitError:
    print("Rate limited — wait a few minutes")
except SwoopHTTPError as e:
    print(f"HTTP {e.status_code}")
except SwoopParseError as e:
    print(f"Parse error: {e}")

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
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

Pricing notes

Use itinerary.price to get the USD price as an integer.

By default, search() excludes basic economy fares so prices reflect Main Cabin. Pass include_basic_economy=True to include them:

results = search("JFK", "LAX", "2026-06-15", include_basic_economy=True)

How it works

Swoop uses Google Flights' internal GetShoppingResults and GetBookingResults RPC endpoints — the same ones the web app calls when you search for flights. Requests are serialized as nested JSON payloads and sent via HTTP POST with browser impersonation (via primp).

Responses are decoded from nested list structures into typed Python dataclasses.

Dependencies

  • primp — HTTP client with browser TLS impersonation
  • protobuf — Protocol buffer serialization
  • click — CLI framework (optional, [cli] extra)
  • rich — Terminal formatting (optional, [cli] extra)

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.1.tar.gz (33.6 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.1-py3-none-any.whl (39.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: swoop_flights-0.2.1.tar.gz
  • Upload date:
  • Size: 33.6 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.1.tar.gz
Algorithm Hash digest
SHA256 8f8d44b6702c35f04bf34867c9ca445f3ea0383f61f0088ffef5b5a4f0db8994
MD5 2c0ac528bd7eb434262bb9982971d028
BLAKE2b-256 3264f00e41fac06f881206b1d3712d0c28240caca7d4183e3ca1f4e0eb399fd2

See more details on using hashes here.

File details

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

File metadata

  • Download URL: swoop_flights-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 39.8 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4f93142fd4964fb8e9619cb108412f5a4ad23fea009b2ae964090d00737fc691
MD5 afc5fac32e45ac957bdc70195b4389ab
BLAKE2b-256 8578fcb1b39cafbd385fece612dc59dbc8c9f0f48dbfc35b9f9416846f59435c

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