Two carriers fly London to Madrid. One schedules 2h20, the other 2h35, and they're flying the same distance through the same airspace. Some of that is taxi time at different terminals and some is schedule padding, but a real part of it is that one is flying an A320 and the other a 737-800, and those aircraft don't cruise at the same speed.
That's the kind of question the aircraft performance endpoint answers. Before going further, it's worth being clear about what it does not answer, because the phrase "aircraft performance" means something specific to a pilot and something looser to a developer.
What this endpoint is not
If you need certified takeoff distance for a given weight, temperature, and runway slope, or a climb profile for fuel planning, this is not that data and no general flight API has it. Those numbers come from the manufacturer's Aircraft Flight Manual, they're specific to an individual airframe's weight and configuration on the day, they're regulated, and they're licensed commercially by the OEM. A performance calculation that dispatch actually uses is done in certified software against AFM data, not against a public REST API.
What this endpoint returns is type-level reference data — the standing characteristics of an aircraft type, drawn from ICAO Doc 8643 and associated reference sources. It describes a B738 in general, not the B738 with the tail number you're looking at, and not that aircraft at 68 tonnes on a hot day.
That distinction matters for what you build on it. Range rings, wake separation hints, seat estimates, and block-time reasoning are all fair uses. Anything a dispatcher or pilot relies on operationally is not.
What you actually get
One call, one path parameter, an ICAO type designator:
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}/aircraft/performance/B738", headers=H)
spec = r.json()
print(spec){
"icao_type": "B738",
"name": "BOEING 737-800",
"engine_type": "Jet",
"engine_code": "L2J",
"wake_category": "M",
"cruise_speed_ktas": 460.0,
"service_ceiling_ft": 35000.0,
"max_range_nm": 2900.0,
"wing_span_m": 34.4,
"length_m": 39.5,
"mtow_t": 78.2,
"max_passengers": 189
}Cruise speed in knots true airspeed, service ceiling, maximum range, the ICAO wake category, physical dimensions, maximum take-off weight in tonnes, and a maximum passenger count.
The engine_code is worth knowing how to read: L2J is landplane, two engines, jet. L2T would be a twin turboprop. It's a compact way to filter a fleet without string-matching on model names.
You need the type code first
The endpoint takes an ICAO type designator, not a tail number and not a hex address. If you're starting from something you saw in a live feed, resolve it first through aircraft lookup, then call performance with the type you get back:
# hex -> type -> specs
a = requests.get(f"{BASE}/aircraft/icao24/4008f3", headers=H).json()
icao_type = a.get("icao_type")
if icao_type:
spec = requests.get(f"{BASE}/aircraft/performance/{icao_type}", headers=H).json()
print(f"{a.get('registration')} {spec['name']} "
f"{spec['cruise_speed_ktas']} KTAS wake {spec['wake_category']}")Cache the result aggressively. A type's reference specs do not change — a B738 will have the same entry next year — so this is a lookup you do once per type and store, not once per aircraft and certainly not once per position update.

Why block times differ by type
Back to the opening question. There are three type-driven contributions, and one of them is much bigger than people expect.
Cruise speed. The obvious one. A 460 KTAS narrowbody and a 490 KTAS widebody separate by about 6% in the cruise phase. Over a two-hour sector that's a matter of minutes, not the fifteen in the example. Cruise speed alone rarely explains a big schedule difference on short routes, and it explains a lot on long ones.
Climb and descent. Not in this endpoint, and it's where much of the short-sector difference lives. A heavier aircraft with a lower thrust-to-weight ratio takes longer to reach cruise, and on a 600 nm sector the aircraft may barely level off before starting down. On short routes the cruise-speed number is close to irrelevant, because so little of the flight is spent in cruise.
Taxi and turnaround. Nothing to do with the aircraft type at all, and often the single largest term. A widebody at a remote stand with a long taxi to the active runway can lose more time on the ground than the entire cruise-speed difference gains in the air.
So if you want block-time estimates that account for all three, don't compute them from cruise speed. Use the ML flight time endpoint, which is trained on historical operational data and takes an aircraft type as an optional parameter:
for t in ("B738", "A320", "B77W"):
r = requests.get(f"{BASE}/ml/flight-time", headers=H,
params={"from": "EGLL", "to": "LEMD", "aircraft": t})
d = r.json()
print(f"{t}: {d}")Passing the aircraft type tightens the estimate; omitting it makes the model fall back to typical jet parameters for the city pair.
Be clear-eyed about what that model is, though. Wind and live en-route weather are not inputs. It's a statistical average for the route and aircraft category, which is exactly what you want for schedule planning and connection buffers, and is not a forecast for a particular departure on a particular windy Tuesday. If you need the latter you're looking at a different class of product, which is covered in Foresight-style ETAs vs ML block-time models.
Wake category, which is more useful than it looks
The wake_category field is an ICAO classification based on maximum take-off weight — L light, M medium, H heavy, and J for the A380. It governs the minimum separation air traffic control must apply behind an aircraft, because the vortices coming off the wingtips are dangerous to whatever follows.
This shows up in two practical places. If you're modelling runway capacity, the mix of wake categories in the arrival stream matters more than the raw count of aircraft — a sequence alternating heavy and light needs much more spacing than a uniform stream of mediums, so the same runway delivers fewer movements per hour. And if you're building a dispatch or ground-ops tool, showing the wake category next to an inbound aircraft is a cheap, genuinely useful hint.
# Wake mix for a live arrival stream, via type lookups you've cached
from collections import Counter
mix = Counter(spec_cache[t]["wake_category"] for t in inbound_types)
print(mix) # Counter({'M': 14, 'H': 3, 'L': 1})
Range rings, and the mistake in drawing them
max_range_nm invites you to draw a circle and say "this aircraft can reach anywhere in here." That circle is wrong in a way worth understanding before a customer points it out.
Maximum range is a still-air figure at optimum weight and altitude. A real flight carries reserves, has payload, faces wind, and may be restricted by runway length or ETOPS constraints at the far end. Westbound transatlantic against the jet stream can cost a large fraction of still-air range. A full passenger load costs more.
So a range ring is a marketing shape, not an operational one. If you're drawing one, either label it clearly as theoretical maximum, or apply a haircut — many people use something in the region of 80% of book range as a rough planning circle, which is a heuristic rather than a rule and should be presented as such.
The same caution applies to cruise_speed_ktas. It's true airspeed, which is speed through the air, not over the ground. Dividing route distance by it gives you a number that ignores wind entirely, and on a long sector wind is worth tens of minutes in either direction. If you catch yourself computing flight time that way, use the ML endpoint instead — that's the problem it exists for.
Getting started
The aircraft performance endpoint is available on every plan including the free trial, and because the sensible pattern is to cache one lookup per type, even a small quota goes a long way — most fleets resolve to a few dozen distinct type codes.
Pair it with aircraft lookup to get from a tail number or hex to a type code, and with the ML flight time endpoint when the question is really about duration rather than about the aircraft.
