B738 is a Boeing 737-800. A20N is an Airbus A320neo. B77W is a Boeing 777-300ER. These are ICAO aircraft type designators, the codes of up to four characters that appear in flight plans, on flight trackers, and in almost every aviation dataset.
They look cryptic at first, but there's a pattern to most of them. This guide explains how they're built, lists the codes you'll see most often, sorts out the other code systems that get confused with them, and shows how to handle them in code.
Where the codes come from
ICAO publishes the list in Doc 8643, Aircraft Type Designators, with a searchable online version. Every aircraft type that files flight plans gets one, from the A380 down to small single-engine trainers and helicopters.
A few rules shape the codes:
- At most four characters, starting with a letter.
- Where possible, the code comes from the manufacturer's own model number: B738 from 737-800, A333 from A330-300, E190 from E-190.
- Different variants get different codes only when they differ in ways that matter to air traffic control, such as performance or size. Customer options and cabin layouts don't get their own codes.
- A type with no designator is filed as
ZZZZ, with the actual type written in the remarks.
Reading the common patterns
Boeing: B + model digits. B737 is the 737-700, B738 the 737-800, B739 the 737-900. B744 is the 747-400, B763 the 767-300, B788 and B789 are the 787-8 and 787-9.
When the digits run out, a letter takes over. The 787-10 would be "B7810", which is five characters, so it became B78X. The 777-300ER is B77W, where the W is often explained as "wide" for its bigger wingspan. The 777-200LR and the 777 freighter share B77L. The plain 777-300 stays B773.
Re-engined versions get N or M. The A320neo family is A19N, A20N and A21N. The 737 MAX family is B37M, B38M, B39M and B3XM for the MAX 7, 8, 9 and 10. This is the distinction people most often need, because the neo and the MAX burn noticeably less fuel than the aircraft they replaced.
Airbus widebodies: A + three digits. A332 and A333 are the A330-200 and -300, and A339 is the A330-900neo. The A350-900 is A359 and the A350-1000 is A35K. The A380 is A388.
Renamed aircraft keep their old code. The Airbus A220 began life as the Bombardier CSeries, so its codes are still BCS1 and BCS3.
Reference table: the codes you'll see most
| Code | Aircraft | Code | Aircraft |
|---|---|---|---|
| A319 | Airbus A319 | B737 | Boeing 737-700 |
| A320 | Airbus A320 | B738 | Boeing 737-800 |
| A321 | Airbus A321 | B739 | Boeing 737-900 |
| A19N | Airbus A319neo | B38M | Boeing 737 MAX 8 |
| A20N | Airbus A320neo | B39M | Boeing 737 MAX 9 |
| A21N | Airbus A321neo (incl. LR, XLR) | B752 | Boeing 757-200 |
| BCS1 | Airbus A220-100 | B763 | Boeing 767-300 |
| BCS3 | Airbus A220-300 | B772 | Boeing 777-200 / -200ER |
| A332 | Airbus A330-200 | B77L | Boeing 777-200LR / 777F |
| A333 | Airbus A330-300 | B77W | Boeing 777-300ER |
| A339 | Airbus A330-900neo | B744 | Boeing 747-400 |
| A359 | Airbus A350-900 | B748 | Boeing 747-8 |
| A35K | Airbus A350-1000 | B788 | Boeing 787-8 |
| A388 | Airbus A380-800 | B789 | Boeing 787-9 |
| E190 | Embraer E190 | B78X | Boeing 787-10 |
| E75L | Embraer E175 (long wing) | CRJ9 | Bombardier CRJ900 |
| AT76 | ATR 72-600 | DH8D | De Havilland Dash 8-400 |
| C172 | Cessna 172 | C208 | Cessna 208 Caravan |
| PC12 | Pilatus PC-12 | GLF6 | Gulfstream G650 |
Some codes span several marketed variants. Ryanair's high-capacity 737 MAX 8-200 is still a B38M. The A321LR and A321XLR are both A21N, even though one can fly much further than the other.

Codes that get confused with ICAO designators
IATA aircraft codes are three characters and used in airline schedules and booking systems: 738 for the 737-800, 7M8 for the 737 MAX 8, 32N for the A320neo, 77W, 359, 388, 789. They're often more detailed than ICAO's, splitting variants by things like winglets (73H is a 737-800 with winglets). If you're joining schedule data to tracking data, you'll need a mapping between the two. ICAO vs IATA codes covers the same split for airports and airlines.
Boeing customer codes are the extra characters in a full model name like 737-8AS or 777-36N. The middle characters identify the customer that first ordered that configuration: AS is Ryanair, so a 737-8AS is a Ryanair 737-800. A British Airways 777-300ER appears in registries as 777-36NER. The ICAO code for both is just the type: B738 and B77W. Boeing has stopped using customer codes on its newest models, but they're all over older registry data.
Description codes such as L2J are a separate ICAO field: landplane, two engines, jet. An A380 is L4J and a helicopter with two turboshaft engines is H2T. Along with the wake category (L, M, H, or J for the A380 alone), they're used for separation and airport planning rather than to identify a model.
Handling type codes in data
Type codes show up in three places in SkyLink's data, and they don't always look the same.
The aircraft lookup returns a clean icao_type alongside the registry's full model name, for example B77W and BOEING 777-36NER for a British Airways 777. The aircraft performance endpoint takes a designator and returns the engine_code, wake_category, cruise speed and dimensions for that type.
The live ADS-B feed is messier. Its aircraft_type field is sometimes a bare designator and sometimes a label such as "Boeing B738", and it can be null. The docs recommend resolving it through aircraft lookup when you need a reliable code. Here's a normaliser that uses the label when it can and looks the aircraft up when it can't:
import re
import requests
from collections import Counter
from functools import lru_cache
BASE = "https://skylink-api.p.rapidapi.com"
H = {"X-RapidAPI-Key": KEY, "X-RapidAPI-Host": "skylink-api.p.rapidapi.com"}
def get(path, **params):
r = requests.get(f"{BASE}{path}", headers=H, params=params, timeout=20)
r.raise_for_status()
return r.json()
CODE = re.compile(r"^[A-Z][A-Z0-9]{1,3}$")
@lru_cache(maxsize=50_000)
def type_from_hex(icao24):
d = get(f"/aircraft/icao24/{icao24}")
return (d.get("aircraft") or {}).get("icao_type") if d.get("found") else None
def designator(plane):
"""Live records carry either a bare code ('B77W') or a label ('Boeing B738')."""
raw = (plane.get("aircraft_type") or "").strip()
last = raw.split()[-1].upper() if raw else ""
if CODE.match(last) and any(ch.isdigit() for ch in last):
return last
return type_from_hex(plane["icao24"])The digit check is deliberately strict. It stops a word like "Jet" or "Boeing" being read as a code. The price is that the few designators with no digits, such as CONC for Concorde, go through the lookup instead, which still gets them right. Cache the lookups, because a hex address keeps the same type for years.
For charts and dashboards, individual codes are usually too fine-grained. Group them into families:
FAMILY = {
"B37M": "737 MAX", "B38M": "737 MAX", "B39M": "737 MAX", "B3XM": "737 MAX",
"B736": "737 NG", "B737": "737 NG", "B738": "737 NG", "B739": "737 NG",
"A19N": "A320neo family", "A20N": "A320neo family", "A21N": "A320neo family",
"A318": "A320ceo family", "A319": "A320ceo family", "A320": "A320ceo family", "A321": "A320ceo family",
"B788": "787", "B789": "787", "B78X": "787",
"A359": "A350", "A35K": "A350",
"B772": "777", "B77L": "777", "B77W": "777", "B773": "777",
}
def fleet_mix(planes):
mix = Counter()
for p in planes:
code = designator(p)
mix[FAMILY.get(code, code or "Unknown")] += 1
return mixRun that over a live snapshot of an area and you get the share of new-generation aircraft in the sky right now. Run it over an airport's traffic history and you can watch an airline's fleet renewal happen.

Common mistakes
Treating B772 as one aircraft. It covers both the 777-200 and the -200ER, and B77L covers both the long-range passenger version and the freighter. If the distinction matters, you need the registry's full model name, not the designator.
Expecting every code to have digits. CONC, GLEX (Bombardier Global Express) and others don't. Validate against a list, or against a lookup, rather than a pattern alone.
Mixing IATA and ICAO in one column. 738 and B738 are the same aircraft, and a join on raw strings will miss it.
Assuming the code tells you the cabin. Two B77Ws can seat anywhere from about 260 to over 400 passengers depending on the airline. The designator identifies the type and nothing about the cabin.
If you want to resolve type codes for your own project, the free trial covers personal, non-commercial use, and paid plans cover commercial products. For registrations rather than types, see the tail number lookup guide.
