Ticket search
Runnable examples for searching flight ticket prices: cheapest and fastest options, full itinerary details, and multi-passenger comparisons. See the Flight Tickets reference for field definitions. Uses IATA codes (not ICAO). Results are cached for 1 hour — prices are indicative and may change at booking time.
| # | Question | Data used |
|---|---|---|
| 1 | Find cheapest and fastest options for JFK → LAX | GET /tickets/search |
| 2 | Show full itinerary with layover details for LHR → JFK | GET /tickets/search |
| 3 | Search for 2 passengers LHR → CDG — compare all options | GET /tickets/search |
Requirements
x-api-key on every request (direct subscription). Learn more →Install
The scripts below use requests for API calls and rich for terminal output. Install once:
pip install requests rich1. Cheapest and fastest: JFK → LAX
Question: What are the cheapest and fastest ticket options on the JFK–LAX route?
The API returns results sorted cheapest-first. Find the fastest option by scanning total_duration_min.
import os
import requests
from rich.console import Console
from rich.panel import Panel
console = Console()
HEADERS = {
"X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
"X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"
def fetch_tickets(
origin: str,
destination: str,
date: str | None = None,
passengers: int = 1,
) -> dict | None:
params: dict[str, str | int] = {
"origin": origin,
"destination": destination,
"passengers": passengers,
}
if date:
params["date"] = date
r = requests.get(
f"{BASE}/tickets/search",
headers=HEADERS,
params=params,
timeout=(10, 15),
)
if r.status_code == 404:
return None
r.raise_for_status()
return r.json()
def fmt_mins(minutes: int | None) -> str:
if minutes is None:
return "—"
return f"{minutes // 60}h {minutes % 60:02d}m"
def stops_label(stops: int) -> str:
return "Nonstop" if stops == 0 else f"{stops} stop(s)"
def flight_summary(flight: dict) -> str:
legs = flight.get("legs", [])
first_leg = legs[0] if legs else {}
return (
f"${flight.get('price_usd', 0):.2f} · "
f"{stops_label(flight.get('stops', 0))} · "
f"{fmt_mins(flight.get('total_duration_min'))} · "
f"{first_leg.get('flight_number', '—')} ({first_leg.get('airline', '—')})"
)
def main() -> None:
data = fetch_tickets("JFK", "LAX")
if not data:
console.print("[red]No ticket data returned.[/red]")
return
flights = data.get("flights", [])
if not flights:
console.print("[yellow]No flights available for JFK → LAX.[/yellow]")
return
cheapest = flights[0]
fastest = min(flights, key=lambda f: f.get("total_duration_min") or 99999)
console.print(
Panel(
f"[bold green]Cheapest[/bold green]\n{flight_summary(cheapest)}",
title="JFK → LAX",
style="green",
)
)
if fastest is not cheapest:
console.print(
Panel(
f"[bold cyan]Fastest[/bold cyan]\n{flight_summary(fastest)}",
title="JFK → LAX",
style="cyan",
)
)
else:
console.print("[dim]Cheapest option is also the fastest.[/dim]")
if __name__ == "__main__":
main()Output: Two panels — the cheapest option and the fastest option — each showing price, stop count, total duration, and the first leg's flight number and airline. When cheapest equals fastest, only one panel is shown.
2. Full itinerary with layover details: LHR → JFK
Question: What does a connecting itinerary look like, including each leg and layover wait times?
Find the first connecting option in the results and display each leg as a row, then list layover stops with wait times.
import os
import requests
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
console = Console()
HEADERS = {
"X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
"X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"
def fetch_tickets(origin: str, destination: str) -> dict | None:
r = requests.get(
f"{BASE}/tickets/search",
headers=HEADERS,
params={"origin": origin, "destination": destination, "passengers": 1},
timeout=(10, 15),
)
if r.status_code == 404:
return None
r.raise_for_status()
return r.json()
def fmt_mins(minutes: int | None) -> str:
if minutes is None:
return "—"
return f"{minutes // 60}h {minutes % 60:02d}m"
def print_itinerary(flight: dict, label: str) -> None:
console.print(
Panel(
f"[bold]{label}[/bold] · ${flight.get('price_usd', 0):.2f} · "
f"{fmt_mins(flight.get('total_duration_min'))}",
style="blue",
)
)
legs_table = Table(show_header=True, show_lines=True)
legs_table.add_column("Airline", style="cyan")
legs_table.add_column("Flight")
legs_table.add_column("From")
legs_table.add_column("To")
legs_table.add_column("Departs")
legs_table.add_column("Arrives")
legs_table.add_column("Duration")
for leg in flight.get("legs", []):
legs_table.add_row(
leg.get("airline", "—"),
leg.get("flight_number", "—"),
f"{leg.get('departure_airport', '—')} ({leg.get('departure_airport_name', '—')[:20]})",
f"{leg.get('arrival_airport', '—')} ({leg.get('arrival_airport_name', '—')[:20]})",
leg.get("departure_time", "—"),
leg.get("arrival_time", "—"),
fmt_mins(leg.get("duration_min")),
)
console.print(legs_table)
layovers = flight.get("layovers", [])
if layovers:
console.print("[bold]Layovers[/bold]")
for lw in layovers:
console.print(
f" {lw.get('airport', '—')} {lw.get('airport_name', '—')} "
f"[yellow]{fmt_mins(lw.get('duration_min'))} wait[/yellow]"
)
def main() -> None:
data = fetch_tickets("LHR", "JFK")
if not data:
console.print("[red]No ticket data returned.[/red]")
return
flights = data.get("flights", [])
if not flights:
console.print("[yellow]No flights available for LHR → JFK.[/yellow]")
return
connecting = next((f for f in flights if f.get("stops", 0) > 0), None)
if connecting:
print_itinerary(connecting, "Connecting Itinerary — LHR → JFK")
else:
console.print("[dim]No connecting flights in results — showing cheapest nonstop.[/dim]")
print_itinerary(flights[0], "Nonstop — LHR → JFK")
if __name__ == "__main__":
main()Output: An itinerary card showing each leg (airline, flight number, airports, departure/arrival times, duration) followed by a layover list with wait times per stop. Falls back to the cheapest nonstop if no connecting options are available.
3. All options for 2 passengers: LHR → CDG
Question: What are all available ticket options for 2 passengers on LHR–CDG?
Display every returned option as a comparison table. Show original currency when it differs from USD.
import os
import requests
from rich.console import Console
from rich.table import Table
console = Console()
HEADERS = {
"X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
"X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"
def fetch_tickets(
origin: str, destination: str, passengers: int
) -> dict | None:
r = requests.get(
f"{BASE}/tickets/search",
headers=HEADERS,
params={
"origin": origin,
"destination": destination,
"passengers": passengers,
},
timeout=(10, 15),
)
if r.status_code == 404:
return None
r.raise_for_status()
return r.json()
def fmt_mins(minutes: int | None) -> str:
if minutes is None:
return "—"
return f"{minutes // 60}h {minutes % 60:02d}m"
def stops_label(stops: int) -> str:
return "Nonstop" if stops == 0 else f"{stops} stop(s)"
def main() -> None:
passengers = 2
data = fetch_tickets("LHR", "CDG", passengers=passengers)
if not data:
console.print("[red]No ticket data returned.[/red]")
return
flights = data.get("flights", [])
if not flights:
console.print("[yellow]No flights available for LHR → CDG.[/yellow]")
return
table = Table(
title=f"LHR → CDG — {len(flights)} option(s) for {passengers} passengers",
show_lines=True,
)
table.add_column("#", justify="right", style="dim")
table.add_column("Price (USD)", justify="right", style="bold green")
table.add_column("Price/pax", justify="right")
table.add_column("Duration", justify="center")
table.add_column("Stops", justify="center")
table.add_column("First Flight")
for i, flight in enumerate(flights, start=1):
price = flight.get("price_usd", 0.0)
per_pax = price / passengers if passengers else price
orig_price = flight.get("original_price")
orig_currency = flight.get("original_currency", "USD")
price_cell = f"${price:.2f}"
if orig_currency and orig_currency != "USD" and orig_price:
price_cell += f"\n[dim]({orig_price:.0f} {orig_currency})[/dim]"
legs = flight.get("legs", [])
first = legs[0] if legs else {}
first_flight = (
f"{first.get('flight_number', '—')} {first.get('airline', '—')}"
)
table.add_row(
str(i),
price_cell,
f"${per_pax:.2f}",
fmt_mins(flight.get("total_duration_min")),
stops_label(flight.get("stops", 0)),
first_flight,
)
console.print(table)
console.print(
"[dim]Prices are market snapshots — confirm at booking. "
"Results cached for 1 hour.[/dim]"
)
if __name__ == "__main__":
main()Output: A table listing every available option with total price, per-passenger price, duration, stop count, and first leg flight number. Original currency is shown beneath the USD price when it differs.