Car hire
Search car hire at an airport for a date range and get back normalized offers, cheapest total first — total and per-day price, the agency you collect from…
Search car hire at an airport for a date range and get back normalized offers, cheapest total first — total and per-day price, the agency you collect from AND the separate company that sold the booking, vehicle class, seats/bags/doors, transmission, mileage and cancellation policy, and whether pickup is in-terminal or a shuttle. Direct API, no browser.
Also known as: car, rental car, rental, car rental, hire car, vehicle, rent a car, hire a car, car hire
Call it
bowmark.cars.search(query: CarQuery, limit?: number, options?: CallOptions): Promise<CarSearchResult>Functions
| Function | What it does |
|---|---|
search | Searches car hire for an airport and date range — { pickup: "SFO", pickupDate: "2026-09-01", dropoffDate: "2026-09-05" } — and returns up to limit normalized offers (default and max… |
Types
type CarQuery = {
pickup: string // IATA airport code ("SFO") — the vertical is airport-first
dropoff?: string // defaults to pickup; set it for a one-way hire
pickupDate: string // ISO date "2026-09-01"
dropoffDate: string
pickupHour?: number // 0-23, defaults to the site's own 10:00
dropoffHour?: number
driverAge?: number // under-25 changes which fleet is quotable at all
}
// One normalized offer. Nulls mean "this site does not report it for this
// offer", never "we failed to read it" — so a filter can tell an absent
// perk from a declined one.
type Car = {
source: string // which site this came from
id: string // that site's id for the offer
price: number | null // TOTAL for the whole hire
dayPrice: number | null // per-day, as the site computes it
currency: string
agency: string // who you collect the car from ("Fox")
seller: string // who sold the booking ("Wisecars") — often different
carName: string // "Mitsubishi Mirage", an "or similar" example
carClass: string // "Economy", "Compact SUV"
passengers: number | null
bags: number | null
doors: number | null
transmission: "automatic" | "manual" | null
airConditioning: boolean | null
unlimitedMileage: boolean | null
freeCancellation: boolean | null
pickupType: string | null // "IN_TERMINAL" / "SHUTTLE" — counter walk vs bus
pickupAddress: string | null
url: string // deep link to this offer
}
type CarSearchResult = {
cars: Car[] // cheapest TOTAL first; unpriced offers last
warnings: string[] // always present; empty when nothing was dropped. A
// site named here quoted NOTHING, which is a different
// fact from an airport with no availability
}
type CallOptions = {
timeoutMs?: number // per-provider budget in ms, default 30000, clamped to 1000-55000.
// A provider slower than this is DROPPED from the results and
// NAMED in warnings — never silently absent
}Examples
// Cheapest week away: price the same hire at three airports and compare the
// real totals, not the advertised per-day rate.
const airports = ["SFO", "OAK", "SJC"];
const quotes = await Promise.all(airports.map(async (pickup) => {
const { cars, warnings } = await bowmark.cars.search({
pickup, pickupDate: "2026-09-01", dropoffDate: "2026-09-08",
}, 25);
for (const w of warnings) log(`${pickup}: ${w}`);
const best = cars[0] || null;
log(`${pickup}: ${best ? best.currency + best.price + " total (" + best.carClass + ")" : "nothing quoted"}`);
return best ? { pickup, total: best.price, perDay: best.dayPrice, car: best.carName, agency: best.agency, url: best.url } : { pickup, total: null };
}));
return quotes.filter(q => q.total).sort((a, b) => a.total - b.total);// A tight connection: only offers you can walk to, that you can cancel, with
// room for four and their bags. Nulls are "unstated", so require true.
const { cars, warnings } = await bowmark.cars.search({
pickup: "MCO", pickupDate: "2026-10-02", dropoffDate: "2026-10-06", pickupHour: 22,
}, 50);
for (const w of warnings) log(w);
const walkable = cars.filter(c =>
c.pickupType === "IN_TERMINAL" && c.freeCancellation === true &&
(c.passengers ?? 0) >= 4 && (c.bags ?? 0) >= 3);
log(`${walkable.length} of ${cars.length} offers are in-terminal, refundable and big enough`);
return walkable.slice(0, 5).map(c => ({
car: c.carName, class: c.carClass, total: c.price, perDay: c.dayPrice,
// who you collect from vs who you bought from — routinely different companies
collectFrom: c.agency, soldBy: c.seller,
unlimitedMiles: c.unlimitedMileage, url: c.url,
}));Providers behind it
| Provider | |
|---|---|
momondo | Momondo |