FlightAware's Foresight sits at the premium end of their AeroAPI pricing, and teams evaluating it often come to us asking whether our ML flight time endpoint is the same thing for less money.

It isn't, and it's worth explaining precisely why rather than letting someone find out after they've integrated. The two products answer different questions. One of them is much harder to build, which is what the price reflects.

Two questions that sound identical

"How long does this route usually take?" — a question about a city pair and an aircraft type, answerable in advance, and stable. The answer for Heathrow to Madrid in an A320 is much the same today as it was last month.

"When will this particular aircraft, currently at FL370 over Bordeaux, actually get to the gate?" — a question about one flight in progress, whose answer changes minute by minute as it encounters wind, holding, a runway change, or a gate that's still occupied.

The first is a block-time model. The second is a live predictive ETA. Both are legitimately described as "ML-powered arrival estimates," which is why the confusion is so common.

What a block-time model does

Ours takes an origin, a destination, and optionally an aircraft type, and returns a gate-to-gate estimate:

import requests

BASE = "https://skylink-api.p.rapidapi.com"
H = {"X-RapidAPI-Key": KEY, "X-RapidAPI-Host": "skylink-api.p.rapidapi.com"}

r = requests.get(f"{BASE}/ml/flight-time", headers=H,
                 params={"from": "KSFO", "to": "KJFK", "aircraft": "B738"})
print(r.json())
{
  "origin": "KSFO",
  "destination": "KJFK",
  "aircraft_type": "B738",
  "distance_nm": 2241.75,
  "estimated_minutes": 294,
  "estimated_hours_display": "4h 54m",
  "min_minutes": 259,
  "max_minutes": 329,
  "model_version": "2.0.0-wind"
}

Gate to gate including taxi, trained on historical operational data, with min and max bounds around the point estimate.

Note the width of that band. 259 to 329 minutes on a nearly five-hour flight is roughly ±12%, and the model is being honest with you: that's the real spread of outcomes on this route in this aircraft. Some of that is wind, some is taxi and runway configuration, some is ATC flow. A block-time model can tell you the distribution. It cannot tell you where in the distribution today's flight will land, because it doesn't know anything about today.

That's stated plainly in our own documentation, and it's the key limitation: wind and live en-route weather are not inputs. The result is a statistical average for the route and aircraft category, not a forecast for a specific departure.

What a live predictive ETA does

Foresight and products like it are solving a genuinely harder problem. A live ETA engine takes the flight's current position, altitude and speed, combines it with forecast winds along the remaining route, current and predicted conditions at the destination, historical behaviour of that route at that time of day, arrival flow and holding patterns in the terminal area, and taxi-in times for the likely runway and gate — and produces an estimate that updates continuously and converges as the flight approaches.

That requires things a block-time model doesn't need: a live position feed with good coverage, weather integration, a large historical corpus of actual outcomes to train against, and continuous retraining as conditions and schedules shift. It's a substantial ongoing engineering investment, and the pricing reflects that rather than being marketing.

If your business depends on knowing when this flight arrives, that is what you're paying for, and it's a reasonable thing to pay for.

The terminal building at Taipei Songshan Airport

Which one your product needs

The test is whether the answer needs to change while the flight is in the air.

A block-time model is enough when:

  • You're building schedules or timetables.
  • You're sizing connection buffers — how much time to leave between an inbound and an outbound on a given route pair.
  • You're quoting durations to a customer at booking time, where nothing about today's operation is known yet.
  • You're doing capacity or network analysis, where you want typical values across many flights rather than an exact one.
  • You're setting alerting thresholds — a flight is worth flagging when it exceeds its typical block time by some margin.

In all of those, "typical" is the correct answer, and paying for a live-updating prediction would buy precision you have no use for.

You need a live predictive ETA when:

  • Someone is dispatched based on the answer. Ground transport, a crew, a handling team, a customs slot.
  • Money moves on it. Contractual arrival guarantees, penalty clauses, time-definite freight.
  • Downstream decisions cascade. Gate assignment, connection protection, crew legality.
  • The cost of being fifteen minutes wrong is real rather than cosmetic.

If your product's answer is consumed by a human deciding what to do in the next hour, you want the live product.

The middle path

Most teams evaluating this sit between the two, and there's a workable pattern that costs less than a premium ETA product and is considerably better than a static block time.

Combine the block-time model with live status. Use the block time as the baseline expectation, then adjust it using the flight's actual reported delay from flight status, and cross-reference system conditions from FAA delays when the destination is under a ground delay programme:

# Baseline expectation from the model
base = requests.get(f"{BASE}/ml/flight-time", headers=H,
                    params={"from": "KSFO", "to": "KJFK",
                            "aircraft": "B738"}).json()

# What's actually happening to this flight right now
status = requests.get(f"{BASE}/flight_status/UA1234", headers=H).json()
dep_delay = status.get("departure_delay_minutes") or 0

# Is the destination itself constrained?
faa = requests.get(f"{BASE}/delays/faa", headers=H).json()
constrained = [d for d in faa.get("data", []) if d.get("airport") == "JFK"]

estimate = base["estimated_minutes"] + dep_delay
print(f"baseline {base['estimated_minutes']}m, dep delay {dep_delay}m "
      f"-> {estimate}m (band {base['min_minutes']}-{base['max_minutes']})")
if constrained:
    print(f"  destination constrained: {constrained[0].get('reason')}")

This is not as good as a proper live ETA engine and it would be dishonest to claim otherwise. It has no wind model, no terminal-area flow model, and no per-flight convergence. What it does have is most of the practical signal — a flight that left 40 minutes late is going to arrive late, and a destination under a ground delay programme is going to hold aircraft — at a fraction of the cost.

For many dashboards that is genuinely sufficient, and the honest framing to your own users is "expected arrival, based on typical block time and current delay," not "predicted arrival."

An airliner on short final over the runway threshold

Evaluating either one properly

If you're comparing predictive products, the vendor's headline accuracy figure is close to meaningless without knowing what it was measured on. Two things to insist on.

Measured against what, and when. An arrival prediction made 20 minutes out is a much easier problem than one made at departure. Any accuracy claim needs a horizon attached. A single number without one is not a claim you can compare between vendors.

Measured on which flights. Accuracy on major-hub domestic trunk routes is far better than on thin regional routes into airports with sparse historical data. If your traffic is the latter, a headline figure computed mostly on the former does not describe your experience.

The way to settle it is to run your own benchmark on your own routes, which is the same methodology as for any other flight data claim — evaluating flight data accuracy sets out how to do that in a way that's fair to everyone including us.

Getting started

The ML flight time endpoint is on all plans including the free trial, so testing whether a statistical block time is sufficient for your case costs nothing but an afternoon. Pull estimates for your routes, compare them against your own historical actuals, and look at how much of your variance the min/max band already covers.

If that band is too wide for the decision you're making, you've learned something useful and specific — and that's the point at which a live predictive product is worth its price rather than a guess that it might be. For the related question of predicting whether a flight will be delayed at all, flight delay prediction covers a different model with a different purpose, and predictive ETAs for logistics covers why scheduled times are the wrong baseline to start from.