Bowmark AIdocs

Kayak

Kayak (kayak.com) — metasearch flight results, cheapest-first, read directly from the result cards.

Domain: kayak.com

Also known as: Kayak, kayak

Prefer the capability

bowmark.flights covers this provider and routes around it when it is having a bad day. Reach for this page when you need kayak.com specifically.

Call it directly

bowmark.providers.kayak.search(query: KayakQuery): Promise<KayakFlight[]>
bowmark.providers.kayak.getBookingOptions(flight: KayakFlight): Promise<KayakBookingOption[]>
bowmark.providers.kayak.searchHotels(query: KayakHotelQuery): Promise<KayakHotel[]>
bowmark.providers.kayak.searchCars(query: KayakCarQuery): Promise<KayakCar[]>

Functions

FunctionWhat it does
searchRuns the search on kayak.com and reads the rendered result cards, sorted price-ascending.
getBookingOptionsFor ONE row returned by search(), every seller Kayak found for that exact itinerary — each with its own price, fare family ("Basic Economy" vs "Main Flex"), cabin, bag policy and a direct…
searchHotelsRuns the stays search on kayak.com and returns priced properties for a destination and date range, cheapest TOTAL first.
searchCarsRuns the car-hire search on kayak.com and returns priced vehicles for a pickup location and date range, cheapest-first.

Types

interface KayakQuery {
  from: string;            // IATA or city, e.g. "SFO"
  to: string;
  depart: string;          // YYYY-MM-DD
  return?: string;         // omit for one-way
  cabin?: "economy" | "premium" | "business" | "first";
  stops?: "any" | "nonstop" | "1";
}

// Kayak's OWN row shape — not the `flights` capability contract.
interface KayakFlight {
  id: string;
  price: number | null;
  currency: string;
  tripType: "round trip" | "one way";
  airlines: string[];
  stops: number;
  depart: string;          // ISO-ish local departure
  arrive: string;
  durationMinutes: number | null;
  url?: string;            // this brand's results URL for the query
}

// One seller's offer for a specific itinerary. Nulls mean "Kayak does not
// report it for this offer", never "we failed to read it".
interface KayakBookingOption {
  provider: string | null;        // who you buy from, e.g. "Super.com", "JetBlue"
  providerCode: string;           // their raw code, e.g. "SUPERAIR", "B6"
  fareType: string | null;        // "Basic Economy", "Main Cabin", "Main Flex", "Mint"
  cabin: string | null;           // "Economy", "Prem Economy", "Business", "First"
  price: number | null;
  currency: string;
  deepLink: string | null;        // absolute link into this seller's booking flow
  carryOn: string | null;         // "Included", "Not Included (+$55)", "Unknown"
  checkedBag: string | null;
  carryOnIncluded: boolean | null;    // null = the site says "Unknown"
  checkedBagIncluded: boolean | null;
  freeCancellation: boolean | null;
  seatsRemaining: number | null;
}

interface KayakHotelQuery {
  location: string;   // IATA airport code, e.g. "SFO", or a resolvable city
  checkIn: string;    // YYYY-MM-DD
  checkOut: string;   // YYYY-MM-DD
  adults?: number;    // default 2
  rooms?: number;     // default 1
}

// Kayak's OWN row shape for stays.
interface KayakHotel {
  id: string;
  name: string;
  price: number | null;        // per NIGHT, cheapest seller (normalized, see below)
  totalPrice: number | null;   // the WHOLE stay — what rows are sorted on
  currency: string;
  seller: string;              // who sells that rate ("Priceline")
  sellerCount: number | null;  // how many sellers quoted this property
  stars: number | null;        // property stars, 1-5
  score: number | null;        // guest score out of 10
  reviewCount: number | null;
  propertyType: string;        // "Hotel", "Motel", "Apartment"
  neighborhood: string | null;
  city: string | null;
  distance: string | null;     // "11.7 mi", as the site renders it
  distanceFrom: string | null; // what that distance is measured from
  url: string;                 // deep link to the property
}

interface KayakCarQuery {
  pickup: string;          // IATA airport code, e.g. "SFO"
  dropoff?: string;        // defaults to pickup
  pickupDate: string;      // YYYY-MM-DD
  dropoffDate: string;     // YYYY-MM-DD
  pickupHour?: number;     // 0-23, default 10
  dropoffHour?: number;    // 0-23, default 10
  driverAge?: number;      // default 30; under-25 changes what is quotable
}

// Kayak's OWN row shape for car hire.
interface KayakCar {
  id: string;
  price: number | null;    // total for the whole rental
  dayPrice: number | null; // per day
  currency: string;
  agency: string;          // who you collect the car from
  seller: string;          // who sells the booking — often a different company
  carName: string;         // "Mitsubishi Mirage" (or similar)
  carClass: string;        // "Economy", "Compact SUV"
  // null on these two means the site quoted no usable figure for this offer: it
  // sends 0 for "unstated" and 24 for the range "2/4 doors", and neither is a count.
  passengers: number | null;
  doors: number | null;
  bags: number | null;     // 0 IS a real answer here, so it is published as one
  transmission: "automatic" | "manual" | null;
  airConditioning: boolean | null;
  unlimitedMileage: boolean | null;
  freeCancellation: boolean | null;
  pickupType: string | null;    // "IN_TERMINAL" | "SHUTTLE" | …
  pickupAddress: string | null;
  url: string;             // deep link to this offer
}

Examples

const rows = await bowmark.providers.kayak.search({ from: "SFO", to: "JFK", depart: "2026-09-01", stops: "nonstop" });
return rows.slice(0, 3);
// The cheapest row is one seller's price for one fare. Ask who else sells the
// same flight, and what the cheap fare actually includes.
const rows = await bowmark.providers.kayak.search({ from: "SFO", to: "JFK", depart: "2026-09-15" });
const cheapest = rows.filter(r => r.price != null).sort((a, b) => a.price - b.price)[0];
const sellers = await bowmark.providers.kayak.getBookingOptions(cheapest);
// Same itinerary, different fares: the headline price often has no checked bag.
const withBag = sellers.filter(s => s.checkedBagIncluded === true);
log(`${sellers.length} sellers, ${withBag.length} include a checked bag`);
return {
  headline: { price: cheapest.price, seller: sellers[0].provider, fare: sellers[0].fareType },
  cheapestWithBag: withBag.sort((a, b) => a.price - b.price)[0] ?? null,
  book: sellers[0].deepLink,
};
flightsFlights — the capability this provider backs.
hotelsHotels — the capability this provider backs.
aaAlso backs the same capability.
cheapflightsAlso backs the same capability.
google_flightsAlso backs the same capability.
momondoAlso backs the same capability.