Use United direct choose-flights URLs to compare one-way and round-trip prices for any route, passenger count, dates, cabin, and optional fare constraints. Return visible fares, flight details, fare-label evidence, filter evidence, page state, return-fare evidence, and itinerary-total evidence.
Use Cases
- Compare one-way and round-trip flight prices for a route.
- Check adult, child, and other multi-passenger searches.
- Test refundable, nonstop, Premium Plus, or Basic Economy-excluded fares.
- Distinguish visible results from empty results, bot challenges, unavailable dates, or United errors.
- Select an outbound and inspect return fares and itinerary totals.
Automation Flow
- Build the one-way URL:
https://www.united.com/en/us/fsr/choose-flights?f={origin}&t={destination}&d={departure-date}&tt=0&sc=7&px={passengers}&taxng=1&clm={cabin}&st={sort}&tqp=R. - Build the round-trip URL:
https://www.united.com/en/us/fsr/choose-flights?f={origin}&t={destination}&d={departure-date}&r={return-date}&tt=1&sc=7%2C7&px={passengers}&taxng=1&clm={cabin}&st={sort}&tqp=R&newHP=True; if it errors, retry withsc=7and omitnewHP=True. - Encode United's passenger vector carefully: the observed vector for two adults and one child is
2,0,0,0,0,1,0,0; map each passenger type to the site's vector position rather than assuming the child is the second value. - For refundable fares with Basic Economy excluded, append
ft=2&bef=0.mm=0alone did not expose refundable labels. Treat Premium Plus and nonstop as requested constraints, but confirm them from visible card text becauseclm=7can display Economy and Polaris options. - In one BQL call, navigate directly, solve Akamai if presented, wait for a flight container or rendered error/empty/unavailable-date state, and run this evaluator. Scroll through the results once and rerun if cards are lazy-rendered; deduplicate cards before reporting first-page and later-page results.
(() => {
const clean=s=>String(s||'').replace(/\s+/g,' ').trim();
const visible=e=>{const r=e?.getBoundingClientRect(),s=e&&getComputedStyle(e);return !!e&&r.width>0&&r.height>0&&s.display!=='none'&&s.visibility!=='hidden'};
const body=clean(document.body?.innerText),priceRe=/(?:US\s*)?\$\s*[\d,]+(?:\.\d{2})?|[\d,]+(?:\.\d{2})?\s*(?:USD|US\$)/gi;
const amount=s=>{const m=String(s||'').replace(/,/g,'').match(/(?:\$|USD|US\$)\s*(\d+(?:\.\d{2})?)|(\d+(?:\.\d{2})?)\s*(?:USD|US\$)/i);return m?Number(m[1]||m[2]):null};
const botChallenge=/captcha|verify you are human|bot challenge|unusual traffic|access denied/i.test(body)||!!document.querySelector('iframe[src*="captcha"],[id*="captcha" i],[class*="captcha" i]');
const error=/unable to complete your request|we['’]re sorry|try again later|request.*(?:error|complete)|system error|technical difficulties/i.test(body);
const unavailable=/not available|outside.*(?:booking|schedule)|select a different date|date.*unavailable|currently unavailable/i.test(body)&&!error;
const empty=/no flights|no results|nothing found|empty/i.test(body)&&!error&&!unavailable;
const cards=[...document.querySelectorAll('div[class*="flightContainer"]')].filter(c=>visible(c)&&/Origin|Destination/i.test(c.innerText||''));
const flights=cards.map((card,index)=>{const text=clean(card.innerText),times=text.match(/\b(?:1[0-2]|[1-9]):[0-5]\d\s*(?:AM|PM)\b/gi)||[],prices=[...new Set((text.match(priceRe)||[]).map(clean))],nums=prices.map(amount).filter(Number.isFinite),labels=[...new Set([...card.querySelectorAll('button,[role="button"]')].map(e=>clean((e.innerText||'')+' '+(e.getAttribute('aria-label')||'')+' '+(e.getAttribute('aria-labelledby')||'')).replace(/\s+select to view fare options$/i,'')).filter(x=>/economy|premium plus|polaris|refundable|basic/i.test(x)))],stops=text.match(/\b(?:\d+ STOP|NONSTOP)\b/i)?.[0]||null;return{index,origin:text.match(/\b([A-Z]{3}) Origin\b/i)?.[1]||null,destination:text.match(/Destination[\s\S]*?\(([A-Z]{3})\)/i)?.[1]||null,depart:times[0]||null,arrive:times[1]||null,duration:text.match(/\b\d+H(?:,\s*\d+M)?\b/i)?.[0]||null,stops,flightNumbers:[...new Set(text.match(/\bUA\s*\d{2,4}\b/gi)||[])],fareLabels:labels,farePrices:prices,lowestDisplayedFare:nums.length?Math.min(...nums):null,isNonstop:/^NONSTOP$/i.test(stops||''),isPremiumEconomy:labels.some(x=>/premium plus|premium economy/i.test(x))||/premium economy|premium plus/i.test(text),isRefundable:/refundable|fully refundable|refundability/i.test(text)||labels.some(x=>/refundable/i.test(x)),hasBasicEconomy:/basic economy/i.test(text)||labels.some(x=>/basic/i.test(x)),soldOut:/sold out|not available|unavailable/i.test(text),text:text.slice(0,2000)}});
const allText=[...document.querySelectorAll('body *')].filter(visible).map(e=>clean(e.innerText)).filter(t=>t&&t.length<900);
const evidence=(re,n)=>[...new Set(allText.filter(t=>re.test(t)&&([...t.matchAll(priceRe)].length||/refundable|basic economy/i.test(t))).slice(0,n))];
const fares=flights.flatMap(f=>f.farePrices).map(amount).filter(Number.isFinite);
return{url:location.href,pageType:/choose-travelers|traveler/i.test(location.pathname)?'traveler-or-cart':'flight-results',searchState:botChallenge?'bot-challenge':error?'site-error':flights.length?'results':unavailable?'date-unavailable':empty?'empty':'unknown',botChallenge,totalCards:flights.length,lowestDisplayedFare:fares.length?Math.min(...fares):null,flights:flights.slice(0,50),filterEvidence:{refundable:/refundable|fully refundable/i.test(body),basicEconomyExcluded:/basic economy.*(?:excluded|omit|remove)|exclude.*basic economy/i.test(body)||/[?&]bef=0(?:&|$)/i.test(location.search),premiumEconomy:/premium economy|premium plus/i.test(body),nonstop:/nonstop|direct/i.test(body),queryParams:Object.fromEntries(new URL(location.href).searchParams)},returnFareEvidence:evidence(/return|round trip|select .*fare|economy|business|first/i,30),totalEvidence:evidence(/total due|trip total|itinerary total|price breakdown|total price|grand total/i,20),body:body.slice(0,1600)};
})()- Treat refundable, Basic Economy exclusion, requested cabin, and nonstop constraints as confirmed only when matching visible card text or filter evidence exists. Fare labels may be rendered in button text rather than
aria-label; inspect both. - To inspect return pricing, select a visible outbound fare button inside its flight container, preferably using its fare text or
button[aria-label^="Select "], wait, and rerun the evaluator. If navigation reacheschoose-travelers, inspect the page body for return evidence and total evidence; United may show only the outbound under anONEWAYlabel while still showingTotal due. Report return fares unavailable when absent, but retain any displayed total. - If the direct URL fails, use the homepage fallback; clear airport inputs through the native setter and dispatch
inputbefore typing, select autocomplete matches, and set the homepage cabin control when available. The observed homepage Premium economy option usedselect#cabinTypevalue1, but its equivalence to directclmvalues is unverified.
Params
| Param | What it does | Example value |
|---|---|---|
origin | Departure airport code mapped to f | EWR |
destination | Arrival airport code mapped to t | FRA |
departure-date | Departure date mapped to d in YYYY-MM-DD format | 2027-06-15 |
return-date | Return date mapped to r | 2027-06-29 |
tt | Trip type: 0 one-way, 1 round-trip | 1 |
passengers | Passenger vector mapped to px; position is passenger-type-specific | 2,0,0,0,0,1,0,0 |
cabin | Direct cabin/search option mapped to clm | 7 |
sc | Search configuration | 7,7 |
taxng | Tax display/search option | 1 |
st | Result sort mode | bestmatches |
tqp | Observed result modifier | R |
newHP | Optional newer round-trip search mode | True |
mm | Optional observed search modifier | 0 |
ft | Observed refundable-fare filter state | 2 |
bef | Observed Basic Economy exclusion state | 0 |
verify-return | Select an outbound and inspect return fares and totals | true |
nonstop | Requested nonstop constraint; verify in card text | true |
premium-economy | Requested Premium Economy constraint; verify visible cabin evidence | true |
refundable | Apply ft=2&bef=0 and verify visible refundable text | true |
include-basic-fares | Homepage fallback control | false |
origin-city | Homepage fallback autocomplete text | Newark |
destination-city | Homepage fallback autocomplete text | Frankfurt |
homepage-cabin-value | Observed homepage Premium economy select value | 1 |
Possible Friction Points
| Trigger | Action |
|---|---|
| Akamai challenge blocks or intermittently prevents results | Restart the BQL session with a US residential proxy, solve Akamai, then revisit the direct URL. |
| Direct choose-flights URL shows a United request-completion error | Check the passenger vector first; use the passenger-type mapping confirmed for the requested mix, retry in a fresh BQL session, then use the homepage fallback. |
| Requested departure date is outside United's currently bookable window or the homepage marks it unavailable | Report date-unavailable, do not report fares or page-two cards, and retain the unavailable-date evidence. |
px places a child in the wrong passenger position | Use the site's passenger-type vector; for two adults and one child, use 2,0,0,0,0,1,0,0, not 2,1,0,0,0,0,0,0. |
mm=0 shows no refundable labels | Apply the observed ft=2&bef=0 filter state and rerun extraction. |
clm=7 shows Economy or Polaris alongside Premium Plus | Do not call the search Premium-Plus-only; filter or classify cards using visible fare labels. |
Fare labels are absent from aria-label | Read visible button text and aria-labelledby content; report that text as fare-label evidence. |
| Homepage calendar marks the requested date unavailable | Report the date as unavailable and retain any separate direct-URL error state; do not invent fares. |
| Homepage airport input appends new text | Clear it with the native input setter and dispatch input before typing. |
| Homepage airport autocomplete returns no matching location | Replace the code with the full city name and select the matching suggestion. |
| United broadens an airport search to nearby airports | Report each returned airport and filter flights by the requested route. |
| Additional cards are below the initial viewport | Scroll through results, rerun the evaluator, and deduplicate by route and text. |
Selecting an outbound reaches choose-travelers with ONEWAY and no return fare evidence | Report return fares unavailable, retain any visible Total due or itinerary-total evidence, and do not classify the original search as empty. |
Later cart state shows Session expired or Your cart is empty | Report the original result evidence; mark return fares and totals unavailable only when no earlier total was captured. |
Round-trip URL with sc=7%2C7&newHP=True behaves like the base flow | Retry the base URL with sc=7, omit newHP=True, and use the returned page state. |
| Result page contains no visible price-like values | Wait for rendering and rerun once; if still empty, report fares as unavailable. |
| Date-picker fallback opens on the wrong month | Move the calendar with month controls until the requested date is visible, then select its accessible grid cell. |
| Homepage exposes Premium economy but direct results lack matching cabin text | Report cabin mapping as unverified rather than treating the homepage option or clm value as confirmed. |