Airport Lookup¶
The simulator ships with a built-in airport database (4,003 entries covering the US, Canada, Europe, and the Pacific). The UI exposes it through the Position panel's airport picker; the REST API exposes it through the /api/airports/* endpoints.
This page documents the database, the lookup behavior in the UI, and the API endpoints you'd use from a script. For the wider position-setting workflow, see Navigation Controls.
What's in the database¶
backend/airports.py defines a single dictionary (AIRPORTS) keyed by ICAO code. Each entry is a tuple of (name, lat, lon, elevation_ft).
| Region | Entries | ICAO prefix |
|---|---|---|
| Continental US + Alaska | 3,642 | K* |
| US Pacific (Hawaii, Guam, US territories) | 253 | P* |
| Europe (UK, Germany, France, Italy, Switzerland, Scandinavia, etc.) | 82 | E*, L* |
| Canada | 25 | C* |
| Other (Iceland, Greenland, etc.) | 1 | B* |
| Total | 4,003 |
The database is static - baked into the Python package at build time. To add or remove entries, edit backend/airports.py and rebuild the image. There is no runtime "load from file" option, by design - the data is small enough to live in memory, lookups are O(1), and the static nature means a known build matches a known data set.
The Position panel airport picker¶
| Behavior | Detail |
|---|---|
| Input field | Free text; auto-uppercased on each keystroke. |
| Debounce | 200 ms between the last keystroke and the search request. |
| Search endpoint | GET /api/airports/search?q=<query>&limit=10 |
| Search matches | ICAO prefix match and name substring match (case-insensitive). |
| Result limit | 10 per query. |
| Dropdown | Shows ICAO + name for each result. Click to select. |
Selecting an airport:
- Sets
lat,lon,altitude_ft,airport_icaoon the server. - Closes the dropdown.
- Renders the selected-airport card (ICAO + name + elevation).
- Marks "airport selected" so the Start button validation clears.
The selected-airport card¶
Once you've picked an airport, a small blue panel appears under the search input:
| Element | Source |
|---|---|
| ICAO | The four-letter code (e.g., KCRQ). |
| Name | Full airport name (e.g., "McClellan-Palomar Airport"). |
| Elevation | Field elevation in feet with thousands separators. |
The card is informational only - there's no editing here. Type a new ICAO into the field above to change the selection.
REST API for airport lookup¶
Three endpoints under /api/airports. They use the same backing dictionary as the UI, so the data is identical.
| Endpoint | Method | Purpose |
|---|---|---|
/api/airports/lookup/{icao} |
GET | Fetch one airport by exact ICAO. Returns 404 if not found. |
/api/airports/search |
GET | Search by ICAO prefix or name substring. ?q= (required), ?limit= (default 10). |
/api/airports/list |
GET | Return every airport in the database. Useful for client-side filtering or for populating a UI dropdown once. |
All three require an authenticated session unless BYPASS_AUTH=true.
Response shape¶
{
"airport": {
"icao": "KCRQ",
"name": "McClellan-Palomar Airport",
"lat": 33.1283,
"lon": -117.2803,
"elevation_ft": 331
}
}
The search endpoint returns {"airports": [...]} - same shape per entry, wrapped in a list.
Search behavior - what matches what¶
| Query | Matches |
|---|---|
KCRQ |
Exact ICAO match. |
KCR |
All ICAOs starting with KCR. |
palomar |
Names containing "palomar" (case-insensitive). |
los |
ICAOs starting with LOS and names containing "los" (which is a lot). |
Single character K |
Up to limit airports whose ICAO starts with K. Useful for the picker's UX, ugly for batch work. |
| Empty string | Returns an empty list (the front end doesn't fire requests for empty queries anyway). |
For complex queries the right approach is /api/airports/list followed by client-side filtering.
When ICAO lookup fails¶
| Cause | What you see |
|---|---|
| Mistyped ICAO | 404 from /api/airports/lookup/{icao}. In the UI: the dropdown shows "No airports found." |
| Airport exists in the real world but not in the database | Same as mistyped. The database is curated, not exhaustive - if it's a niche airport, add it to backend/airports.py and rebuild. |
| Lower-case ICAO | The UI uppercases as you type; if you're hitting the API directly, send uppercase to match the dictionary keys. The lookup endpoint normalizes to uppercase internally. |
Adding more airports¶
The data file is a Python dictionary literal. Append your entries and rebuild:
# backend/airports.py
AIRPORTS = {
"KLAX": ("Los Angeles International Airport", 33.9425, -118.4081, 125),
...
"KMYAIRPORT": ("My Custom Airport", 12.3456, -78.9012, 1234),
}
After rebuild and redeploy, both the UI picker and the REST endpoints see the new entry. No restart of the database is needed because there is no database - the dict is loaded on import.
Coordinates and elevation conventions
Latitude and longitude are decimal degrees (north and east positive). Elevation is feet MSL. The simulator uses this elevation as the initial altitude when an airport is picked, so accuracy here matters - a wrong elevation means your aircraft starts buried in the runway or floating above it.
How the picker handles multi-browser sync¶
When a second browser is open and the first browser picks an airport, the second browser's picker syncs:
- Server-side state
airport_icaoupdates. - The WebSocket broadcasts the new state.
- The second browser's
useStatushook fires. - The
PositionInputcomponent'suseEffectnotices the changedairportIcaoprop. - It calls
api.lookupAirport(icao)to fetch the full record (name, elevation) and renders the card.
The picker is careful not to overwrite what the operator is currently typing - if you start typing in a browser while another browser changes the selection, your keystrokes win.
Persistent state¶
| Setting | UI control | Env var | Survives restart? |
|---|---|---|---|
| Selected airport | Picker | (no var directly) | No - per run. |
| Default lat / lon | Picker (or env vars at boot) | DEFAULT_LAT, DEFAULT_LON |
Yes (env var) |
| Default altitude (from elevation) | Picker sets it on selection | DEFAULT_ALT_FT |
Yes (env var, used at boot before any airport is picked) |
What's next¶
- Navigation Controls - how the picker plugs into altitude/airspeed/heading.
- API Reference - full Swagger UI link for the
/api/airports/*endpoints.