Search API Reference¶
Flight Search¶
The main search functionality for finding specific flights.
SearchFlights¶
fli.search.flights.SearchFlights()
¶
Flight search via Google Flights' FlightsFrontendService API.
Public surface:
- :meth:
search— issue a GetShoppingResults call and return the parsed flights. - :meth:
get_booking_options— follow up with GetBookingResults to surface bookable fares for a selected itinerary. See the method docstring for the live-token limitation.
Concurrency
SearchFlights is not thread-safe. The instance caches the
shopping-session id from the most recent :meth:search call so
:meth:get_booking_options can derive the booking token; two
concurrent search calls on the same instance will race on that
cache and may cross-pollinate sessions between unrelated bookings.
For multi-threaded or async server use, either (a) instantiate a
fresh SearchFlights per request, or (b) pass the
session_id returned by your own session bookkeeping into
:meth:get_booking_options explicitly (the kwarg overrides the
cached value).
Initialize the search client.
Source code in fli/search/flights.py
BASE_URL = 'https://www.google.com/_/FlightsFrontendUi/data/travel.frontend.flights.FlightsFrontendService/GetShoppingResults'
class-attribute
instance-attribute
¶
BOOKING_URL = 'https://www.google.com/_/FlightsFrontendUi/data/travel.frontend.flights.FlightsFrontendService/GetBookingResults'
class-attribute
instance-attribute
¶
DEFAULT_HEADERS = {'content-type': 'application/x-www-form-urlencoded;charset=UTF-8'}
class-attribute
instance-attribute
¶
client = get_client()
instance-attribute
¶
get_booking_options(flight: FlightResult | tuple[FlightResult, ...], filters: FlightSearchFilters, currency: str | None = None, language: str | None = None, country: str | None = None, booking_token: str | None = None, session_id: str | None = None) -> list[BookingOption]
¶
Fetch bookable fare options for a selected itinerary.
After a :meth:search call, the session id from Google's response
is cached on the client and used here automatically — no explicit
token plumbing is required by callers. The booking-call payload
carries the same selected_flight legs the caller used in their
round-trip search and a protobuf token constructed from the
cached session id + the chosen itinerary's identifiers.
| PARAMETER | DESCRIPTION |
|---|---|
flight
|
A :class:
TYPE:
|
filters
|
The same filters used in the preceding :meth:
TYPE:
|
currency
|
Optional ISO 4217 currency code passed to Google as
TYPE:
|
language
|
Optional BCP-47 language code (
TYPE:
|
country
|
Optional ISO 3166-1 alpha-2 country code (
TYPE:
|
booking_token
|
Explicit override for
TYPE:
|
session_id
|
Explicit override for the session id used to build
the token. Defaults to the session captured by the most
recent :meth:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[BookingOption]
|
A list of :class: |
list[BookingOption]
|
returns no vendors. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
No session id available — either pass it
explicitly or call :meth: |
Exception
|
HTTP request failure. |
Source code in fli/search/flights.py
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | |
search(filters: FlightSearchFilters, top_n: int = 5, currency: str | None = None, language: str | None = None, country: str | None = None) -> list[FlightResult | tuple[FlightResult, ...]] | None
¶
Search for flights using the given :class:FlightSearchFilters.
| PARAMETER | DESCRIPTION |
|---|---|
filters
|
Full search descriptor (airports, dates, preferences).
TYPE:
|
top_n
|
Number of outbound options to expand when chasing a round-trip or multi-city itinerary.
TYPE:
|
currency
|
Optional ISO 4217 currency code (
TYPE:
|
language
|
Optional BCP-47 language code (
TYPE:
|
country
|
Optional ISO 3166-1 alpha-2 country code (
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[FlightResult | tuple[FlightResult, ...]] | None
|
For one-way trips, a list of :class: |
list[FlightResult | tuple[FlightResult, ...]] | None
|
round-trip / multi-city, a list of tuples of |
list[FlightResult | tuple[FlightResult, ...]] | None
|
class: |
list[FlightResult | tuple[FlightResult, ...]] | None
|
when no results. |
| RAISES | DESCRIPTION |
|---|---|
Exception
|
HTTP failure or unparseable response. |
Source code in fli/search/flights.py
FlightSearchFilters¶
A simplified interface for flight search parameters.
fli.models.google_flights.FlightSearchFilters
¶
Bases: BaseModel
Complete set of filters for flight search.
This model matches required Google Flights' API structure.
airlines: list[Airline] | None = None
class-attribute
instance-attribute
¶
airlines_exclude: list[Airline] | None = None
class-attribute
instance-attribute
¶
alliances: list[Alliance] | None = None
class-attribute
instance-attribute
¶
alliances_exclude: list[Alliance] | None = None
class-attribute
instance-attribute
¶
bags: BagsFilter | None = None
class-attribute
instance-attribute
¶
emissions: EmissionsFilter = EmissionsFilter.ALL
class-attribute
instance-attribute
¶
exclude_basic_economy: bool = False
class-attribute
instance-attribute
¶
flight_segments: list[FlightSegment]
instance-attribute
¶
layover_restrictions: LayoverRestrictions | None = None
class-attribute
instance-attribute
¶
max_duration: PositiveInt | None = None
class-attribute
instance-attribute
¶
passenger_info: PassengerInfo
instance-attribute
¶
price_limit: PriceLimit | None = None
class-attribute
instance-attribute
¶
seat_type: SeatType = SeatType.ECONOMY
class-attribute
instance-attribute
¶
show_all_results: bool = True
class-attribute
instance-attribute
¶
sort_by: SortBy = SortBy.BEST
class-attribute
instance-attribute
¶
stops: MaxStops = MaxStops.ANY
class-attribute
instance-attribute
¶
trip_type: TripType = TripType.ONE_WAY
class-attribute
instance-attribute
¶
encode() -> str
¶
URL encode the formatted filters for API request.
Source code in fli/models/google_flights/flights.py
format() -> list
¶
Format filters into Google Flights API structure.
This method converts the FlightSearchFilters model into the specific nested list/dict structure required by Google Flights' API.
The output format matches Google Flights' internal API structure, with careful handling of nested arrays and proper serialization of enums and model objects.
| RETURNS | DESCRIPTION |
|---|---|
list
|
A formatted list structure ready for the Google Flights API request
TYPE:
|
Source code in fli/models/google_flights/flights.py
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | |
Date Search¶
Search functionality for finding the cheapest dates to fly.
SearchDates¶
fli.search.dates.SearchDates()
¶
Date-based flight search implementation.
This class provides methods to search for flight prices across a date range, useful for finding the cheapest dates to fly.
Initialize the search client for date-based searches.
Source code in fli/search/dates.py
BASE_URL = 'https://www.google.com/_/FlightsFrontendUi/data/travel.frontend.flights.FlightsFrontendService/GetCalendarGraph'
class-attribute
instance-attribute
¶
DEFAULT_HEADERS = {'content-type': 'application/x-www-form-urlencoded;charset=UTF-8'}
class-attribute
instance-attribute
¶
MAX_DAYS_PER_SEARCH = 61
class-attribute
instance-attribute
¶
client = get_client()
instance-attribute
¶
__parse_currency(item: list[list] | list | None) -> str | None
staticmethod
¶
Parse the returned currency code from the API response.
Source code in fli/search/dates.py
__parse_date(item: list[list] | list | None, trip_type: TripType) -> tuple[datetime] | tuple[datetime, datetime]
staticmethod
¶
Parse date data from the API response.
| PARAMETER | DESCRIPTION |
|---|---|
item
|
Raw date data from the API response
TYPE:
|
trip_type
|
Trip type (one-way or round-trip)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[datetime] | tuple[datetime, datetime]
|
Tuple of datetime objects |
Source code in fli/search/dates.py
__parse_price(item: list[list] | list | None) -> float | None
staticmethod
¶
Parse price data from the API response.
| PARAMETER | DESCRIPTION |
|---|---|
item
|
Raw price data from the API response
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float | None
|
Float price value if valid, None if invalid or missing |
Source code in fli/search/dates.py
search(filters: DateSearchFilters, currency: str | None = None, language: str | None = None, country: str | None = None) -> list[DatePrice] | None
¶
Search for flight prices across a date range and search parameters.
| PARAMETER | DESCRIPTION |
|---|---|
filters
|
Search parameters including date range, airports, and preferences
TYPE:
|
currency
|
Optional ISO 4217 currency code (e.g.
TYPE:
|
language
|
Optional BCP-47 language code passed via the
TYPE:
|
country
|
Optional ISO 3166-1 alpha-2 country code passed via the
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[DatePrice] | None
|
List of DatePrice objects containing date and price pairs, or None if no results |
| RAISES | DESCRIPTION |
|---|---|
Exception
|
If the search fails or returns invalid data |
Notes
- For date ranges larger than 61 days, splits into multiple searches.
- We can't search more than 305 days in the future.
Source code in fli/search/dates.py
DatePrice¶
fli.search.dates.DatePrice
¶
Examples¶
Basic Flight Search¶
from fli.search import SearchFlights
from fli.models import Airport, SeatType, FlightSearchFilters, FlightSegment, PassengerInfo
# Create filters
filters = FlightSearchFilters(
passenger_info=PassengerInfo(adults=1),
flight_segments=[
FlightSegment(
departure_airport=[[Airport.JFK, 0]],
arrival_airport=[[Airport.LAX, 0]],
travel_date="2026-06-01",
)
],
seat_type=SeatType.ECONOMY
)
# Search flights
search = SearchFlights()
results = search.search(filters)
Date Range Search¶
from fli.search import SearchDates
from fli.models import DateSearchFilters, Airport, FlightSegment, PassengerInfo
# Create filters
filters = DateSearchFilters(
passenger_info=PassengerInfo(adults=1),
flight_segments=[
FlightSegment(
departure_airport=[[Airport.JFK, 0]],
arrival_airport=[[Airport.LAX, 0]],
travel_date="2026-06-01",
)
],
from_date="2026-06-01",
to_date="2026-06-30"
)
# Search dates
search = SearchDates()
results = search.search(filters)
Running These Examples¶
You can find complete, runnable versions of these examples in the examples/python/ directory:
# Run with uv (recommended)
uv run python examples/python/basic_one_way_search.py
uv run python examples/python/date_range_search.py
# Or install dependencies and run directly
pip install pydantic curl_cffi httpx
python examples/python/basic_one_way_search.py
For more advanced examples, see:
examples/python/complex_flight_search.py- Advanced filteringexamples/python/result_processing.py- Data analysisexamples/python/error_handling_with_retries.py- Robust error handling
HTTP Client¶
The underlying HTTP client used for API requests.
Client¶
fli.search.client.Client(calls_per_second: int = DEFAULT_CALLS_PER_SECOND)
¶
HTTP client with built-in rate limiting, retry and user agent impersonation functionality.
Sessions are kept per-thread because curl_cffi.requests.Session is
not thread-safe — concurrent post/get calls from different
threads each get their own libcurl handle. The shared
:class:TokenBucketRateLimiter enforces the global 10 req/sec budget
across all of them.
Initialise the shared rate limiter and per-thread session storage.
Source code in fli/search/client.py
DEFAULT_HEADERS = {'content-type': 'application/x-www-form-urlencoded;charset=UTF-8'}
class-attribute
instance-attribute
¶
__del__()
¶
Best-effort cleanup of the main-thread session (others die with their thread).
Source code in fli/search/client.py
get(url: str, **kwargs: Any) -> Response
¶
Make a rate-limited GET request with automatic retries.
Source code in fli/search/client.py
post(url: str, **kwargs: Any) -> Response
¶
Make a rate-limited POST request with automatic retries.