Search Air Canada Multi-City Flights and Fare Options

Site aircanada.comTask search-air-canada-multi-city-flightsVersion v2Updated Sep 25, 2026Category travel

Search Air Canada's multi-city booking flow for itinerary options, connections, layovers, and fare families across multiple segments. This skill was captured from a live agent session on aircanada.com and is published here as a reusable recipe for agents.

NoteSelectors and URL schemes drift as sites change. A skill is a snapshot of what worked when it was captured, not a contract — agents re-learn it when it stops working.

Find Air Canada multi-city flight options and report available itineraries, connections, layover durations, and requested fare families for a sequence of airport/date segments, including open-jaw itineraries.

Use Cases

Use when a request contains two or more flight legs and requires comparing fare families or identifying a particular connection, airport, or layover duration. Inputs should provide segment origins, destinations, dates, and any optional fare, routing, or connection preferences.

Automation Flow

  1. Navigate directly to https://www.aircanada.com/home/{country}/{language}/aco/flights, defaulting to ca/en. Other market editions price the same itinerary in their own currency and fare rules, so report which edition produced the fares.

  2. Select the multi-city trip type using button#bkmgFlights-trip-selector_tripTypeBtn, then choose the visible option #bkmgFlights-trip-selector_tripTypeSelector_M.

  3. Set the passenger count before searching. The form defaults to one adult (button#bkmg-desktop_selectTravelers reads 1 Adult, accessible name Passengers - currently selected - 1 Adult), so a group left untouched is priced as a single adult and the fare comparison is wrong for that party. Open that button, then click the observed steppers until each count input holds the requested value:

    • adults #bkmg-desktop_selectTravelers_addTraveler_ADT / _removeTraveler_ADT, count in #bkmg-desktop_selectTravelers_travelerCount_ADT
    • youths _YTH, children _CHD, infant on lap _INF, infant in seat _INS, following the same addTraveler / removeTraveler / travelerCount pattern

    Confirm with #bkmg-desktop_selectTravelers_confirmTravelers and re-read the button text to verify the party before submitting. One adult is the default when the caller says nothing. At narrow viewports the same control renders as #bkmg-mobile-tablet_selectTravelers.

  4. If the OneTrust preference dialog appears, open it with button#onetrust-pc-btn-handler and save/confirm with button.save-preference-btn-handler before filling the form.

  5. For each segment i, fill and commit the first visible airport suggestion for:

    • #bkmgMultiDesktop_origin_trip_{i} with {origin-i}
    • #bkmgMultiDesktop_destination_trip_{i} with {destination-i} After typing an airport code, wait for suggestions and select #bkmgMultiDesktop_{field}_trip_{i}SearchResult0 where rendered. Verify the selected input value before continuing.
  6. Fill each date input #bkmgMultiDesktop_travelDates_{i} in DD/MM format. If typing does not commit the date, open #bkmgMultiDesktop_travelDates_{i}-showCalendar and select the visible calendar cell whose aria-label matches the full date, such as td[aria-label='November 8, 2026']. Verify the date value afterward.

  7. Submit the multi-city search with the visible booking/search control after all segments and dates are populated. In one automation transaction, wait for the results page and run the evaluator below; do not revisit the homepage or repeat airport searches.

  8. From the results, retain itineraries matching optional constraints such as {required-connection-airport} and {minimum-layover-duration}, and report only requested fare families such as Flex, Comfort, or Latitude. Treat requested fares on each segment independently when the site presents mixed-fare options.

Optional input shape

{
  "segments": [
    {"origin": "{origin-1}", "destination": "{destination-1}", "date": "{date-1}"},
    {"origin": "{origin-2}", "destination": "{destination-2}", "date": "{date-2}"}
  ],
  "requiredConnectionAirport": "{airport-code}",
  "minimumLayoverMinutes": "{minutes}",
  "fareFamilies": ["{fare-family-1}", "{fare-family-2}"]
}

Result-page evaluator

Run this evaluate() on the loaded results page. It returns visible flight and fare-card text without leaving the target origin or making network calls.

(()=>{
  const visible=e=>{const r=e.getBoundingClientRect();return r.width>0&&r.height>0};
  const selectors=[
    '[data-testid*="flight"]','[data-testid*="itinerary"]','[data-testid*="fare"]',
    '[class*="flight-card"]','[class*="flightCard"]','[class*="itinerary"]',
    '[class*="fare-card"]','[class*="fareCard"]','article'
  ];
  const nodes=[...new Set(selectors.flatMap(s=>[...document.querySelectorAll(s)]))]
    .filter(visible)
    .map(e=>({text:(e.innerText||'').replace(/\s+/g,' ').trim()}))
    .filter(x=>x.text&&(/\b(?:Basic|Standard|Flex|Comfort|Latitude|Premium|Business|Economy|Signature)\b|flight|layover|stop|connection/i.test(x.text)||/(?:CAD|USD|\$)\s?[\d,]+/.test(x.text)));
  const results=[],seen=new Set();
  for(const x of nodes){
    const key=x.text.slice(0,1200);
    if(!seen.has(key)){seen.add(key);results.push({text:x.text})}
  }
  return {pageTitle:document.title,results};
})()

Possible Friction Points

  • The booking widget renders two variants by viewport: the bkmg-desktop_* / bkmgMultiDesktop_* ids this recipe uses exist only at desktop width, while a narrow viewport swaps in bkmg-mobile-tablet_* and the trip-type selector is absent entirely. Set a desktop viewport before querying these ids.
  • The passenger panel counts five traveller types (ADT, YTH, CHD, INF on lap, INS in seat) as separate steppers, each starting at zero except one adult. Children and infants are not adults, so mapping a whole party onto the adult stepper misprices it.
  • Air Canada's multi-city form uses distinct fields suffixed by segment number: origin_trip_1, destination_trip_1, origin_trip_2, and so on.
  • Airport autocomplete must be committed by selecting a suggestion; merely typing an airport code is insufficient.
  • Date fields accept DD/MM, but typed dates may fail to commit. The calendar fallback uses full localized aria-label values, for example td[aria-label='November 8, 2026'].
  • OneTrust consent can block the booking form. The preference-panel flow is #onetrust-pc-btn-handler followed by .save-preference-btn-handler.
  • The observed run did not expose a stable results URL or documented query-parameter shortcut; use the booking form rather than guessing a search URL.
  • The evaluator's text filter names fare families only as examples. Air Canada renames and varies them by market, so a card for a family outside that list is kept only by its generic keyword or its price. When the caller asks for a specific family, match the requested name against the returned card text rather than assuming the filter preserved it.
  • Connection and fare-card CSS classes may change. Prefer data-testid selectors when present and use the evaluator's visible-text fallback; do not interpret duplicate nested cards as separate flights without deduplicating their text.
  • The {country}/{language} segment of the entry URL selects the Air Canada site edition, which sets the currency and the fares shown. Keep the caller's market, and name it alongside any price.
  • A long layover and a required connection airport are result constraints, not form fields; verify them from each segment's displayed airport and duration.

Call it

GET https://production-sfo.browserless.io/skills?token=TOKEN-HERE&domain=aircanada.com&task=search-air-canada-multi-city-flights