The SearchDates class helps you find the cheapest dates to fly by searching across date ranges. Itβs perfect for flexible travel planning when you want to find the best prices rather than search specific dates.
Basic usage
One-way date search
Find the cheapest one-way flights across a date range:
from datetime import datetime, timedelta
from fli.models import (
Airport,
DateSearchFilters,
FlightSegment,
PassengerInfo,
)
from fli.search import SearchDates
# Create future dates
base_date = datetime.now() + timedelta( days = 30 )
travel_date = base_date.strftime( "%Y-%m- %d " )
from_date = base_date.strftime( "%Y-%m- %d " )
to_date = (base_date + timedelta( days = 30 )).strftime( "%Y-%m- %d " )
# Create filters
filters = DateSearchFilters(
passenger_info = PassengerInfo( adults = 1 ),
flight_segments = [
FlightSegment(
departure_airport = [[Airport. JFK , 0 ]],
arrival_airport = [[Airport. LAX , 0 ]],
travel_date = travel_date,
)
],
from_date = from_date,
to_date = to_date,
)
# Search dates
search = SearchDates()
results = search.search(filters)
# Process results
for date_price in results:
print ( f "Date: { date_price.date } , Price: $ { date_price.price } " )
This example comes from examples/date_range_search.py in the source code.
Round-trip date search
Find the cheapest round-trip dates with a specific duration:
from datetime import datetime, timedelta
from fli.models import (
Airport,
DateSearchFilters,
FlightSegment,
PassengerInfo,
TripType,
)
from fli.search import SearchDates
base_date = datetime.now() + timedelta( days = 30 )
travel_date = base_date.strftime( "%Y-%m- %d " )
from_date = base_date.strftime( "%Y-%m- %d " )
to_date = (base_date + timedelta( days = 60 )).strftime( "%Y-%m- %d " )
# Round trip with 7-day duration
filters = DateSearchFilters(
trip_type = TripType. ROUND_TRIP ,
passenger_info = PassengerInfo( adults = 1 ),
flight_segments = [
FlightSegment(
departure_airport = [[Airport. JFK , 0 ]],
arrival_airport = [[Airport. LAX , 0 ]],
travel_date = travel_date,
),
FlightSegment(
departure_airport = [[Airport. LAX , 0 ]],
arrival_airport = [[Airport. JFK , 0 ]],
travel_date = (datetime.strptime(travel_date, "%Y-%m- %d " ) + timedelta( days = 7 )).strftime( "%Y-%m- %d " ),
),
],
from_date = from_date,
to_date = to_date,
duration = 7 , # 7-day trips
)
search = SearchDates()
results = search.search(filters)
for result in results:
outbound, return_date = result.date
print ( f "Outbound: { outbound } , Return: { return_date } , Price: $ { result.price } " )
Advanced filtering
Filter by day of week
Find weekend flights only:
from datetime import datetime, timedelta
from fli.models import (
Airport,
DateSearchFilters,
FlightSegment,
PassengerInfo,
SeatType,
TripType,
)
from fli.search import SearchDates
# Create filters for weekends only
base_date = datetime.now() + timedelta( days = 30 )
travel_date = base_date.strftime( "%Y-%m- %d " )
from_date = base_date.strftime( "%Y-%m- %d " )
to_date = (base_date + timedelta( days = 30 )).strftime( "%Y-%m- %d " )
filters = DateSearchFilters(
trip_type = TripType. ONE_WAY ,
passenger_info = PassengerInfo( adults = 1 ),
flight_segments = [
FlightSegment(
departure_airport = [[Airport. JFK , 0 ]],
arrival_airport = [[Airport. LAX , 0 ]],
travel_date = travel_date,
)
],
from_date = from_date,
to_date = to_date,
seat_type = SeatType. PREMIUM_ECONOMY ,
)
search = SearchDates()
results = search.search(filters)
# Filter for weekends only
weekend_results = [
r for r in results
if r.date[ 0 ].weekday() >= 5 # Saturday = 5, Sunday = 6
]
print ( f "Found { len (weekend_results) } weekend flights:" )
for result in weekend_results:
day_name = result.date[ 0 ].strftime( "%A" )
date_str = result.date[ 0 ].strftime( "%Y-%m- %d " )
print ( f " { day_name } , { date_str } : $ { result.price } " )
This example comes from examples/date_search_with_preferences.py in the source code.
Time restrictions
Search with departure time preferences:
from fli.models import TimeRestrictions
filters = DateSearchFilters(
passenger_info = PassengerInfo( adults = 1 ),
flight_segments = [
FlightSegment(
departure_airport = [[Airport. JFK , 0 ]],
arrival_airport = [[Airport. LAX , 0 ]],
travel_date = travel_date,
time_restrictions = TimeRestrictions(
earliest_departure = 9 , # 9 AM
latest_departure = 18 , # 6 PM
),
)
],
from_date = from_date,
to_date = to_date,
)
Cabin class preferences
Search for premium cabin dates:
from fli.models import SeatType
filters = DateSearchFilters(
passenger_info = PassengerInfo( adults = 1 ),
flight_segments = [ ... ],
from_date = from_date,
to_date = to_date,
seat_type = SeatType. BUSINESS ,
)
Weekend trip optimization
Find the cheapest weekend trips with validation:
from datetime import datetime, timedelta
from fli.models import (
Airport,
DateSearchFilters,
FlightSegment,
PassengerInfo,
SeatType,
TimeRestrictions,
TripType,
)
from fli.search import SearchDates
def validate_dates ( from_date : str , to_date : str , min_stay : int , max_stay : int ) -> None :
"""Validate date ranges for round trip searches."""
start = datetime.strptime(from_date, "%Y-%m- %d " ).date()
end = datetime.strptime(to_date, "%Y-%m- %d " ).date()
today = datetime.now().date()
if start <= today:
raise ValueError ( "Start date must be in the future" )
if end <= start:
raise ValueError ( "End date must be after start date" )
if end - start > timedelta( days = 180 ):
raise ValueError ( "Date range cannot exceed 180 days" )
if min_stay < 1 :
raise ValueError ( "Minimum stay must be at least 1 day" )
if max_stay > 30 :
raise ValueError ( "Maximum stay cannot exceed 30 days" )
if min_stay > max_stay:
raise ValueError ( "Minimum stay cannot be greater than maximum stay" )
print ( f "β Date validation passed: { from_date } to { to_date } " )
print ( f "β Stay duration: { min_stay } - { max_stay } days" )
from_date = (datetime.now() + timedelta( days = 30 )).strftime( "%Y-%m- %d " )
to_date = (datetime.now() + timedelta( days = 60 )).strftime( "%Y-%m- %d " )
min_stay = 2
max_stay = 4
try :
validate_dates(from_date, to_date, min_stay, max_stay)
except ValueError as exc:
print ( f "β Validation failed: { exc } " )
exit ( 1 )
stay_lengths = range (min_stay, max_stay + 1 )
search = SearchDates()
weekend_trips = []
print ( " \n π Searching for round trip dates..." )
for duration in stay_lengths:
outbound_date = from_date
return_date = (
datetime.strptime(outbound_date, "%Y-%m- %d " ) + timedelta( days = duration)
).strftime( "%Y-%m- %d " )
flight_segments = [
FlightSegment(
departure_airport = [[Airport. JFK , 0 ]],
arrival_airport = [[Airport. LAX , 0 ]],
travel_date = outbound_date,
time_restrictions = TimeRestrictions(
earliest_departure = 9 ,
latest_departure = 18 ,
),
),
FlightSegment(
departure_airport = [[Airport. LAX , 0 ]],
arrival_airport = [[Airport. JFK , 0 ]],
travel_date = return_date,
),
]
filters = DateSearchFilters(
trip_type = TripType. ROUND_TRIP ,
passenger_info = PassengerInfo( adults = 1 ),
flight_segments = flight_segments,
from_date = from_date,
to_date = to_date,
duration = duration,
seat_type = SeatType. ECONOMY ,
)
results = search.search(filters)
if not results:
continue
for trip in results:
outbound, inbound = trip.date
if outbound.weekday() >= 5 : # Saturday = 5, Sunday = 6
weekend_trips.append({
"outbound" : outbound.strftime( "%Y-%m- %d " ),
"return" : inbound.strftime( "%Y-%m- %d " ),
"stay_length" : duration,
"price" : trip.price,
})
weekend_trips.sort( key = lambda trip : trip[ "price" ])
print ( f " \n β
Found { len (weekend_trips) } weekend flight combinations:" )
for index, trip in enumerate (weekend_trips[: 5 ], 1 ):
print ( f " \n { index } . Weekend Trip:" )
print ( f " Outbound: { trip[ 'outbound' ] } " )
print ( f " Return: { trip[ 'return' ] } " )
print ( f " Stay: { trip[ 'stay_length' ] } days" )
print ( f " Price: $ { trip[ 'price' ] } " )
This example comes from examples/advanced_date_search_validation.py in the source code.
API reference
SearchDates class
Defined in fli/search/dates.py:25.
Constructor
Creates a new instance with an initialized HTTP client. The client includes:
Automatic rate limiting (10 requests/second)
Retry logic with exponential backoff (up to 3 attempts)
Browser impersonation for API access
search() method
def search (
self ,
filters : DateSearchFilters
) -> list[DatePrice] | None
Parameters:
filters (DateSearchFilters): Search parameters including date range, airports, and preferences
Returns:
list[DatePrice] containing date and price pairs, or None if no results
Raises:
Exception: If the search fails or returns invalid data
Implementation notes:
Automatically splits date ranges over 61 days into multiple searches
Can search up to 305 days in the future
For round-trip searches, returns tuples of (outbound_date, return_date) in each DatePrice.date
See implementation at fli/search/dates.py:42-99.
DateSearchFilters
Complete search configuration for date-based searches.
Required fields:
passenger_info (PassengerInfo): Passenger counts
flight_segments (list[FlightSegment]): One or more flight segments
from_date (str): Start of date range in YYYY-MM-DD format
to_date (str): End of date range in YYYY-MM-DD format
Optional fields:
trip_type (TripType): ONE_WAY or ROUND_TRIP (default: ONE_WAY)
duration (int): Trip duration in days for round-trip searches
seat_type (SeatType): Cabin class preference
stops (MaxStops): Stop preferences
airlines (list[Airline]): Filter by specific airlines
DatePrice
Contains date and price information.
Fields:
date (tuple[datetime] | tuple[datetime, datetime]): Date(s) for the flight
One-way: Single datetime in tuple (departure_date,)
Round-trip: Two datetimes in tuple (outbound_date, return_date)
price (float): Flight price for the date(s)
Defined in fli/search/dates.py:18-22.
Date range limitations
Important limitations:
Maximum single search: 61 days (automatically chunked if larger)
Maximum future date: 305 days from today
Date ranges over 61 days will trigger multiple API calls
The library handles chunking automatically:
# This works - automatically splits into multiple searches
from_date = (datetime.now() + timedelta( days = 30 )).strftime( "%Y-%m- %d " )
to_date = (datetime.now() + timedelta( days = 150 )).strftime( "%Y-%m- %d " ) # 120 days
filters = DateSearchFilters(
passenger_info = PassengerInfo( adults = 1 ),
flight_segments = [ ... ],
from_date = from_date,
to_date = to_date,
)
# Automatically split into 2 searches (61 + 59 days)
results = search.search(filters)
See chunking implementation at fli/search/dates.py:63-98.
Price tracking
Track prices over time to find the best deals:
import time
from datetime import datetime, timedelta
from fli.models import Airport, DateSearchFilters, FlightSegment, PassengerInfo
from fli.search import SearchDates
def track_prices ( days = 7 ):
"""Track flight prices over a specified number of days."""
base_date = datetime.now() + timedelta( days = 30 )
travel_date = base_date.strftime( "%Y-%m- %d " )
from_date = base_date.strftime( "%Y-%m- %d " )
to_date = (base_date + timedelta( days = 7 )).strftime( "%Y-%m- %d " )
filters = DateSearchFilters(
passenger_info = PassengerInfo( adults = 1 ),
flight_segments = [
FlightSegment(
departure_airport = [[Airport. JFK , 0 ]],
arrival_airport = [[Airport. LAX , 0 ]],
travel_date = travel_date,
)
],
from_date = from_date,
to_date = to_date,
)
search = SearchDates()
price_history = {}
for day in range (days):
print ( f "Day { day + 1 } : Searching for prices..." )
results = search.search(filters)
# Store prices
for result in results:
date_str = result.date[ 0 ].strftime( "%Y-%m- %d " )
if date_str not in price_history:
price_history[date_str] = []
price_history[date_str].append(result.price)
# Wait for next check (in real implementation, wait 24 hours)
if day < days - 1 :
print ( "Waiting for next check..." )
time.sleep( 86400 ) # 24 hours
return price_history
# Analyze price history
price_history = track_prices( 7 )
print ( " \n === Price History Summary ===" )
for date, prices in price_history.items():
min_price = min (prices)
max_price = max (prices)
avg_price = sum (prices) / len (prices)
print ( f " { date } : Min: $ { min_price :.2f} , Max: $ { max_price :.2f} , Avg: $ { avg_price :.2f} " )
This example comes from examples/price_tracking.py in the source code.
Best practices
SearchDates is ideal when you have flexible travel dates and want to find the cheapest options. For specific dates, use SearchFlights instead.
Always check if results is None before processing: results = search.search(filters)
if not results:
print ( "No dates found" )
return
Round-trip date structure
For round-trip searches, DatePrice.date contains a tuple of two datetimes: for result in results:
outbound, return_date = result.date # Unpack tuple
print ( f "Outbound: { outbound } , Return: { return_date } " )
Consider chunking overhead
Date ranges over 61 days trigger multiple API calls. For very large ranges, consider breaking into smaller searches.
Filter results post-search
Use Pythonβs filtering capabilities to narrow results by day of week, price range, etc.: # Weekend departures only
weekend_results = [r for r in results if r.date[ 0 ].weekday() >= 5 ]
# Under $500
cheap_results = [r for r in results if r.price < 500 ]
Examples
Explore complete working examples:
Date range search Find cheapest dates to fly
Date search with preferences Advanced date filtering with day-of-week preferences
Advanced date search validation Comprehensive validation for round-trip date searches
Price tracking Monitor price changes over time
Next steps
SearchFlights Search for flights on specific dates
All examples Browse 11 complete code examples