Flight booking options
Who sells the itinerary and for how much (SerpApi booking_options).
/v1/serp/google_flights_bookingAirline direct and OTAs, each with price, fare name and rules, bag fees, the seller's local-currency price and Google's click-through as both a POST form (booking_request) and a GET link (booking_url). Google gathers seller prices while the request is open: expect 3-12 s.
Request
https://api.scrapercompany.com/v1/serp/google_flights_bookingAuthenticate with your API key in the x-api-key header (see Authentication).
Body
JSON object. Unknown fields are rejected with 422.
- booking_tokenstringrequiredpattern ^gf1\.[A-Za-z0-9_\-]{16,16384}$
booking_tokenof a complete itinerary: a one-way result of/v1/serp/google_flights, or a return/last-leg result of/v1/serp/google_flights_return.
Example request
curl -X POST "https://api.scrapercompany.com/v1/serp/google_flights_booking" \
-H "x-api-key: $SCRAPERCOMPANY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"booking_token": "gf1.eNp9T8sKwjAQ_Jc9p5BUqqU3tc0hBm0bE8WQk_hASy9tVRD_3aRVVBSzsJlhZjabK5wgIgi2EOmyKQrUNr-7tEEEaYKwK4Ne-q-m3QFGJ2C9xjgOfLh8sNaC3-zgY7_vEeyRAJ4DuvSH0o3oEjG3nAzCEMyfZXrfIjEIqvabNUQwPuR0kdCpTC6UqzwVWM24DFI1JiOuGM3kuRYqZ_OjEpliK_vo2sakiC3aFxZuSot2DjUV3O6AWl_r"
}'Response
200 — Sellers of the chosen itinerary with prices, fare rules, bag fees and click-through links. Metered responses carry x-credits-charged and x-credits-remaining headers (see credit headers).
{
"currency": "USD",
"trip_type": "round_trip",
"legs": [
{
"segments": [
{
"departure_airport": "YUL",
"arrival_airport": "CDG",
"departure_time": "2026-11-04T18:10:00",
"arrival_time": "2026-11-05T07:20:00",
"airline": "Air Canada",
"airline_code": "AC",
"flight_number": "AC 874",
"duration_minutes": 430,
"aircraft": "Airbus A330",
"cabin_class": "economy",
"departure_airport_name": "Montréal-Pierre Elliott Trudeau International Airport",
"arrival_airport_name": "Aéroport de Paris-Charles de Gaulle",
"ticket_also_sold_by": [
"LH 6809",
"SN 9636"
],
"legroom": "31 in",
"legroom_category": "average",
"overnight": true,
"red_eye": false,
"often_delayed_by_over_30_min": false,
"carbon_emissions_kg": 325,
"extensions": [
"Average legroom (31 in)",
"Wi-Fi for a fee"
],
"airline_logo": "https://www.gstatic.com/flights/airline_logos/70px/AC.png"
}
],
"departure_airport": "YUL",
"arrival_airport": "CDG",
"duration_minutes": 430,
"stops": 0,
"layover_airports": [],
"is_direct": true,
"layovers": [],
"airlines": [
"Air Canada"
],
"departure_time": "2026-11-04T18:10:00",
"arrival_time": "2026-11-05T07:20:00"
},
{
"segments": [
{
"departure_airport": "CDG",
"arrival_airport": "ZRH",
"departure_time": "2026-11-11T07:15:00",
"arrival_time": "2026-11-11T08:35:00",
"airline": "SWISS",
"airline_code": "LX",
"flight_number": "LX 647",
"duration_minutes": 80,
"aircraft": "Airbus A320",
"cabin_class": "economy",
"departure_airport_name": "Aéroport de Paris-Charles de Gaulle",
"arrival_airport_name": "Zurich Airport",
"ticket_also_sold_by": [],
"legroom": "29 in",
"legroom_category": "below_average",
"overnight": false,
"red_eye": false,
"often_delayed_by_over_30_min": false,
"carbon_emissions_kg": 62,
"extensions": [
"Below average legroom (29 in)",
"Carbon emissions estimate: 62 kg"
],
"airline_logo": "https://www.gstatic.com/flights/airline_logos/70px/LX.png"
},
{
"departure_airport": "ZRH",
"arrival_airport": "YUL",
"departure_time": "2026-11-11T12:40:00",
"arrival_time": "2026-11-11T15:10:00",
"airline": "SWISS",
"airline_code": "LX",
"flight_number": "LX 86",
"duration_minutes": 510,
"aircraft": "Airbus A330",
"cabin_class": "economy",
"departure_airport_name": "Zurich Airport",
"arrival_airport_name": "Montréal-Pierre Elliott Trudeau International Airport",
"ticket_also_sold_by": [
"AC 6821"
],
"legroom": "31 in",
"legroom_category": "average",
"overnight": false,
"red_eye": false,
"often_delayed_by_over_30_min": true,
"carbon_emissions_kg": 351,
"extensions": [
"Average legroom (31 in)",
"Wi-Fi for a fee"
],
"airline_logo": "https://www.gstatic.com/flights/airline_logos/70px/LX.png"
}
],
"departure_airport": "CDG",
"arrival_airport": "YUL",
"duration_minutes": 835,
"stops": 1,
"layover_airports": [
"ZRH"
],
"is_direct": false,
"layovers": [
{
"duration_minutes": 245,
"airport": "ZRH",
"airport_name": "Zurich Airport",
"city": "Zürich",
"departure_airport": "ZRH",
"change_of_airport": false,
"overnight": false
}
],
"airlines": [
"SWISS"
],
"departure_time": "2026-11-11T07:15:00",
"arrival_time": "2026-11-11T15:10:00"
}
],
"booking_options": [
{
"book_with": "SWISS",
"seller_code": "LX",
"is_airline": true,
"price": 527,
"currency": "USD",
"display_price": "$527",
"local_prices": [
{
"currency": "CAD",
"price": 749
}
],
"marketed_as": [
"LH 6809",
"LX 647"
],
"booking_request": {
"url": "https://www.google.com/travel/clk/f",
"post_data": "u=ADowPOL...&v=1"
},
"booking_url": "https://www.google.com/travel/clk/f?u=ADowPOL...&v=1",
"seller_domain": "www.swiss.com/...",
"separate_tickets": false,
"sellers": [
"SWISS"
],
"extensions": [],
"baggage_prices": [
"1st checked bag: $127",
"2nd checked bag: $183"
]
},
{
"book_with": "Lufthansa",
"seller_code": "LH",
"is_airline": true,
"price": 527,
"currency": "USD",
"display_price": "$527",
"local_prices": [
{
"currency": "CAD",
"price": 749
}
],
"marketed_as": [
"LH 6809",
"LX 647"
],
"booking_request": {
"url": "https://www.google.com/travel/clk/f",
"post_data": "u=ADowPOL...&v=1"
},
"booking_url": "https://www.google.com/travel/clk/f?u=ADowPOL...&v=1",
"seller_domain": "www.lufthansa.com/...",
"separate_tickets": false,
"sellers": [
"Lufthansa"
],
"extensions": [],
"baggage_prices": [
"1st checked bag: $127",
"2nd checked bag: $183"
]
}
],
"option_count": 9,
"cheapest_price": 527,
"price_insights": {
"lowest_price": 527,
"price_level": "typical",
"typical_price_range": [
495,
880
],
"price_history": [
[
1790568000,
529
],
[
1790654400,
528
]
]
},
"google_flights_url": "https://www.google.com/travel/flights/booking?tfs=CBwQAho_EgoyMDI2LTExLTA0Ih8KA1lVTBIKMjAyNi0xMS0wNBoDQ0RHKgJBQzIDODc0ag...",
"wire_bytes": 79626,
"elapsed_s": 6.247
}Response fields
Fields marked required are always present; others appear when they apply.
- currencystringrequired
Currency of the original search.
- trip_typestringrequired
one_way,round_tripormulti_city.One of
one_wayround_tripmulti_city - legsarray of objectrequired
Every leg of the chosen itinerary, in order.
Show 11 child fieldsHide child fields
- legs[].segmentsarray of objectrequired
Flights in order.
Show 22 child fieldsHide child fields
- legs[].segments[].departure_airportstringrequired
IATA code.
- legs[].segments[].arrival_airportstringrequired
IATA code.
- legs[].segments[].departure_timestring | nullrequired
Airport-local wall-clock time as Google shows it, ISO 8601 without a UTC offset, e.g.
2026-11-04T18:10:00. Null when unknown. - legs[].segments[].arrival_timestring | nullrequired
Airport-local wall-clock time as Google shows it, ISO 8601 without a UTC offset, e.g.
2026-11-04T18:10:00. Null when unknown. - legs[].segments[].airlinestringrequired
Marketing airline name (empty string when Google gives none).
- legs[].segments[].airline_codestring | nullrequired
IATA code of the marketing airline.
- legs[].segments[].flight_numberstring | nullrequired
Marketing carrier and number, e.g.
AC 874. - legs[].segments[].duration_minutesinteger | nullrequired
Flight time, minutes.
- legs[].segments[].aircraftstring | nullrequired
e.g.
Airbus A330. - legs[].segments[].cabin_classstring | nullrequired
One of
economypremium_economybusinessfirst - legs[].segments[].departure_airport_namestring | nullrequired
- legs[].segments[].arrival_airport_namestring | nullrequired
- legs[].segments[].operated_bystring | nullrequired
The airline actually flying it when Google names one other than the marketing carrier, e.g.
Endeavor Air DBA Delta Connection. - legs[].segments[].ticket_also_sold_byarray of stringrequired
Codeshare flight numbers the same flight is also sold under, e.g.
LH 6809. - legs[].segments[].legroomstring | nullrequired
Seat pitch as Google shows it, e.g.
31 in. - legs[].segments[].legroom_categorystring | nullrequired
One of
averagebelow_averageabove_average - legs[].segments[].overnightbooleanrequired
Lands on a later calendar day than it departs (local times).
- legs[].segments[].red_eyebooleanrequired
Heuristic: departs 20:00-02:59 and lands 04:00-10:59 after the night (local times).
overnightis exact; this is not. - legs[].segments[].often_delayed_by_over_30_minbooleanrequired
Google's flag that this flight is often delayed by more than 30 minutes.
- legs[].segments[].carbon_emissions_kginteger | nullrequired
CO2e estimate for this flight, kilograms (rounded).
- legs[].segments[].extensionsarray of stringrequired
Google's amenity lines, e.g.
Average legroom (31 in),Free Wi-Fi,Wi-Fi for a fee,In-seat power & USB outlets,Live TV,On-demand video,Stream media to your device,Carbon emissions estimate: 325 kg. - legs[].segments[].airline_logostring | nullrequired
Logo URL of the marketing airline.
- legs[].departure_airportstringrequired
IATA code.
- legs[].arrival_airportstringrequired
IATA code.
- legs[].departure_timestring
Airport-local wall-clock time as Google shows it, ISO 8601 without a UTC offset, e.g.
2026-11-04T18:10:00. Present only when known. - legs[].arrival_timestring
Airport-local wall-clock time as Google shows it, ISO 8601 without a UTC offset, e.g.
2026-11-04T18:10:00. Present only when known. - legs[].duration_minutesinteger | nullrequired
Door-to-door travel time including layovers, minutes.
- legs[].stopsintegerrequired
- legs[].layover_airportsarray of stringrequired
IATA codes of the connection airports.
- legs[].is_directbooleanrequired
stopsis 0. - legs[].layoversarray of objectrequired
Show 7 child fieldsHide child fields
- legs[].layovers[].duration_minutesinteger | nullrequired
Connection time, minutes.
- legs[].layovers[].airportstringrequired
IATA code of the airport the traveller lands at.
- legs[].layovers[].airport_namestring | nullrequired
- legs[].layovers[].citystring | nullrequired
- legs[].layovers[].departure_airportstringrequired
Airport the next flight leaves from; equals
airportunless the connection changes airports. - legs[].layovers[].change_of_airportbooleanrequired
The next flight leaves from a different airport.
- legs[].layovers[].overnightbooleanrequired
The next flight leaves on a later calendar day than the previous one lands.
- legs[].airlinesarray of stringrequired
Airline names Google lists for this leg.
- booking_optionsarray of objectrequired
Airline-direct and online travel agency sellers.
Show 17 child fieldsHide child fields
- booking_options[].book_withstringrequired
Seller name; several sellers are joined with
andwhen the option is separate tickets. - booking_options[].seller_codestring | nullrequired
Google's code for the (first) seller: the IATA code for an airline, e.g.
LX. - booking_options[].is_airlinebooleanrequired
Every seller is an airline (airline direct).
- booking_options[].pricenumber | nullrequired
This seller's price for the whole trip, in
currency, as Google shows it. - booking_options[].currencystringrequired
Currency of the original search.
- booking_options[].display_pricestring | nullrequired
pricewith its currency symbol, e.g.$527. - booking_options[].local_pricesarray of objectrequired
The seller's own price when it charges in another currency, e.g. CAD 749.
Show 2 child fieldsHide child fields
- booking_options[].local_prices[].currencystringrequired
- booking_options[].local_prices[].pricenumberrequired
- booking_options[].marketed_asarray of stringrequired
Flight numbers this seller sells the itinerary under, e.g.
LX 647. - booking_options[].booking_requestobject | nullrequired
Google's click-through as a form (SerpApi's shape): POST
post_dataasapplication/x-www-form-urlencodedtourl. Null when the seller has no link (e.g. call to book).Show 2 child fieldsHide child fields
- booking_options[].booking_request.urlstringrequired
Google's click-through URL.
- booking_options[].booking_request.post_datastringrequired
URL-encoded form body.
- booking_options[].booking_urlstring | nullrequired
The same click-through as a GET link; Google answers it with a redirect to the seller's page. Null when
booking_requestis. - booking_options[].seller_domainstring | nullrequired
The seller's site as Google shows it, e.g.
www.swiss.com/.... - booking_options[].booking_phonestring | nullrequired
Phone number of a call-to-book seller (which has no link).
- booking_options[].separate_ticketsbooleanrequired
The option is several tickets bought from different sellers (see
sellers). - booking_options[].sellersarray of stringrequired
Every seller of this option.
- booking_options[].option_titlestring | nullrequired
Fare family when Google names one, e.g.
Delta Main Basic. - booking_options[].extensionsarray of stringrequired
Fare rules Google lists, e.g.
No refunds,Free seat selection,Ticket changes for a fee. Mostly shown for airline-direct sellers. - booking_options[].baggage_pricesarray of stringrequired
Bag fees as Google words them, e.g.
1st checked bag: $45,1 free carry-on.
- option_countintegerrequired
Number of entries in
booking_options. - cheapest_pricenumber | nullrequired
Lowest
priceinbooking_options; null when none is priced. - price_insightsobject | null
Null when Google gives none. Omitted when
booking_optionsis empty; that answer is not billed.Show 4 child fieldsHide child fields
- price_insights.lowest_pricenumber | nullrequired
Lowest price Google shows for this search, in
currency. - price_insights.price_levelstring | nullrequired
Google's verdict on today's price:
low(below its typical range),typical(inside it) orhigh(above it).One of
lowtypicalhigh - price_insights.typical_price_rangearray of number | nullrequiredmin items 2, max items 2
[low, high]: Google's typical price range for this trip. - price_insights.price_historyarray of array of numberrequired
[[unix_seconds, price], ...]: Google's price history for this trip, about 60 days. Empty when Google gives none.
- google_flights_urlstringrequired
Google Flights booking page for this itinerary.
- wire_bytesintegerrequired
Size of Google's response, bytes.
- elapsed_snumberrequired
Time Google took to answer, seconds (typically 3-12 s: Google checks seller prices while the request is open).
Errors
Errors return a JSON body with a detail field. Failed requests are not charged. See Errors for the full list and retry advice.
| Status | Meaning | Retry? |
|---|---|---|
401Unauthorized | Missing or invalid API key. {"detail":"missing or invalid API key"} | No, fix the request |
402Payment Required | Not enough credits for this request. Only returned once credit enforcement is switched on; during the beta metering runs in shadow mode and never blocks. {"detail":"insufficient credits: this request costs 5, 0 available. Credits renew 2026-11-01."} | No, fix the request |
422Unprocessable Content | Request validation failed. {"detail":[{"loc":["body","name"],"msg":"Field required","type":"missing"}]} | No, fix the request |
429Too Many Requests | Too many requests: the key's requests-per-minute limit was exceeded, or (once credit enforcement is on) the plan's concurrent-request limit. No rate-limit or Retry-After headers are sent; back off and retry. {"detail":"rate limit 60/min exceeded"} | Yes, with backoff |
502Bad Gateway | The upstream source failed, blocked the request or returned an unusable answer. Safe to retry later; failed requests are not charged. {"detail":"RuntimeError"} | Yes, with backoff |
Try it
- Export your key:
export SCRAPERCOMPANY_API_KEY=sk_...(no key yet? request access). - Copy the cURL example above and run it in a terminal.
- Or open the interactive playground on api.scrapercompany.com, paste your key and pick this endpoint.