Skip to content

Price a round trip: outbound, return and booking options

Search Google Flights, pick an outbound, get its return flights, then see who sells the itinerary and for how much.

Overview

A round trip on Google Flights is chosen one leg at a time, the way SerpApi models it. Each call hands you a token for the next one:

StepCallYou getCredits
1. Outbound
Outbound options, each priced for the whole trip, with a departure_token
3
2. Return
Return options for the outbound you chose, each with a booking_token
3
3. Booking
Airline and OTA sellers for the itinerary, with prices, fare rules, bag fees and links
3

A one-way search skips step 2: its options already carry a booking_token. Empty results at any step are free.

Search the outbound

departure and arrival take IATA airport codes (YUL) or city codes (NYC, LON, PAR), which search every airport in the city. Adding return_date makes it a round trip.

curl -X POST "https://api.scrapercompany.com/v1/serp/google_flights" \
  -H "x-api-key: $SCRAPERCOMPANY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "departure": "YUL",
    "arrival": "CDG",
    "departure_date": "2026-11-30",
    "return_date": "2026-12-07",
    "adults": 1,
    "currency": "USD"
  }'
One outbound option (shortened)
{
  "group": "best",
  "price": 527,
  "display_price": "$527",
  "price_exact": 526.19,
  "total_duration_minutes": 430,
  "total_stops": 0,
  "departure_token": "gf1.eNqFUMkKwjAU_Jd3TiGpVqU3TVuhBO1iIhpyEhe09NJWBfHfTRexxS2B...",
  "price_token": "CjRIb2...",
  "legs": [
    {
      "departure_airport": "YUL",
      "arrival_airport": "CDG",
      "departure_time": "2026-11-30T18:10:00",
      "arrival_time": "2026-12-01T07:20:00",
      "stops": 0,
      "segments": [
        {
          "flight_number": "AC 874",
          "airline": "Air Canada",
          "aircraft": "Airbus A330",
          "cabin_class": "economy",
          "legroom": "31 in"
        }
      ]
    }
  ]
}

price is Google's displayed whole amount for the whole trip (so the return is already included), price_exact the exact figure, and group says whether Google ranked it among its best flights. Times are airport-local, without a UTC offset. The response also has price_insights (Google's typical range, price level and history) and a google_flights_url for each itinerary.

Narrow the search with stops, include_airlines / exclude_airlines, max_price, max_duration, outbound_times / return_times, carry_on_bags / checked_bags (Google adds the bag fees to the price), cabin_class and sort_by; every field is in the reference.

Choose the return

Pass the chosen outbound's departure_token; nothing else is needed, because the token carries the search.

chosen = min(outbound["itineraries"], key=lambda it: it["price"] or float("inf"))
returns = post("/v1/serp/google_flights_return", {"departure_token": chosen["departure_token"]})
print(returns["itinerary_count"], "return options")
for it in returns["itineraries"][:5]:
    leg = it["legs"][0]
    print(it["display_price"], leg["departure_time"], leg["arrival_time"], leg["stops"], "stops")

The response has the same shape as the search, with leg_index: 1. Prices are still for the whole trip, now with this return. These options are the last leg, so each carries a booking_token and a booking_url instead of a departure_token.

Get booking options

trip = min(returns["itineraries"], key=lambda it: it["price"] or float("inf"))
booking = post("/v1/serp/google_flights_booking", {"booking_token": trip["booking_token"]})
for option in booking["booking_options"]:
    print(option["book_with"], option["display_price"], option.get("option_title"), option["baggage_prices"])
One booking option (shortened)
{
  "book_with": "SWISS",
  "seller_code": "LX",
  "is_airline": true,
  "price": 527,
  "display_price": "$527",
  "local_prices": [
    {
      "currency": "CAD",
      "price": 749
    }
  ],
  "marketed_as": [
    "LH 6809",
    "LX 647",
    "LX 86"
  ],
  "baggage_prices": [
    "1st checked bag: $127",
    "2nd checked bag: $183",
    "1 free carry-on"
  ],
  "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",
  "separate_tickets": false
}

Each option names the seller (is_airline for airline-direct), its price in your currency and in the seller's own (local_prices), the fare family and rules where Google lists them (option_title, extensions), bag fees, and Google's click-through both as a form to POST (booking_request) and as a link (booking_url). separate_tickets marks an option sold as several tickets.

Booking options take a few seconds

Google checks the sellers while the request is open: expect 3-12 seconds. Set your client timeout accordingly (the examples use 120 s).

City and airport codes

When you have a place name rather than a code, resolve it with POST/v1/serp/google_flights_location_search (1 credit). Cities come back with their airports and a Google city id (/m/05qtj for Paris), which departure_id / arrival_id accept alongside comma-separated airport lists such as JFK,EWR.

Request
{
  "q": "paris"
}

Multi-city trips

Instead of return_date, send multi_city: 1-4 further legs after the first, each {departure, arrival, date} with optional times. Dates must not go backwards. Choose legs the same way: one /v1/serp/google_flights_return call per further leg, then booking options for the last leg's booking_token. Google's multi-city search is slower, up to about 10 seconds for a later leg.

Three legs
{
  "departure": "YUL",
  "arrival": "CDG",
  "departure_date": "2026-11-30",
  "multi_city": [
    {
      "departure": "CDG",
      "arrival": "FCO",
      "date": "2026-12-04"
    },
    {
      "departure": "FCO",
      "arrival": "YUL",
      "date": "2026-12-09"
    }
  ]
}

Tokens, staleness and cost

  • Tokens are self-contained and don't expire on a timer, but they stop working when Google stops selling the chosen flights or fare. A stale departure_token or booking_token returns 422 ("search again"); booking options that come back empty are free.
  • Coming from an older integration? booking_token now means the token the booking endpoint takes, and appears only on complete itineraries. Google's raw price token is price_token, on every itinerary: use it if you need a stable itinerary key. See the changelog.
  • One-way searches are priced as one-way. One-way prices you stored before this change were round-trip fares, so don't compare the two directly.
  • A full round trip costs 9 credits (3 + 3 + 3); add 1 for each location lookup. For flexible dates, POST/v1/serp/google_flights_calendar (5 credits) prices a whole date grid first.