How to Map Helicopters, Gliders and Balloons by State From the FAA Registry
On this page
Problem statement
The FAA registry codes every aircraft by type: glider, balloon, fixed wing, rotorcraft, weight-shift, powered parachute, gyroplane and hybrid lift. Mapping one type by state shows where each kind of flying happens, such as balloons in New Mexico. But the codes are older than the aircraft now being registered under them. Since large agricultural and delivery drones have to be registered, "rotorcraft" and "hybrid lift" increasingly mean drones, and a state map of rotorcraft is now partly a map of spray drones. This page separates them by engine type and maps helicopters, drones, gliders and balloons with the 16 October 2026 file.
Quick answer
Keep valid US registrations, split rotorcraft by engine (code 10 is electric), and cross-tabulate by state:
us = reg[(reg.COUNTRY == "US") & (reg["STATUS CODE"] == "V") & reg.STATE.isin(STATEFP.index)].copy()
us["kind"] = us["TYPE AIRCRAFT"].map(TYPE_AIRCRAFT)
drone = (us.kind == "rotorcraft") & (us["TYPE ENGINE"] == "10")
us.loc[drone, "kind"] = "electric rotorcraft"
us.loc[us.kind == "rotorcraft", "kind"] = "helicopter"
tab = pd.crosstab(us.STATE, us.kind)
print(tab[["helicopter", "electric rotorcraft", "hybrid lift", "glider", "balloon"]].sum().to_string())
kind
helicopter 14838
electric rotorcraft 12497
hybrid lift 3300
glider 4802
balloon 5171
Of the valid rotorcraft, 14,838 have a fuel-burning engine and 12,497 are electric. Electric rotorcraft are almost as numerous as helicopters, and 3,300 more drones sit under hybrid lift.
Counts, shares and per resident
1. Where each kind is most numerous
for k in ["helicopter", "electric rotorcraft", "glider", "balloon", "gyroplane", "powered parachute"]:
top = tab[k].nlargest(3)
print(f"{k:18} " + ", ".join(f"{s} {v:,}" for s, v in top.items()))
helicopter TX 1,574, FL 1,290, CA 1,260
electric rotorcraft TX 1,164, IA 1,013, OH 804
glider CA 613, TX 341, FL 278
balloon NM 613, CO 325, TX 274
gyroplane TX 54, FL 35, CA 33
powered parachute TX 159, MI 121, WI 103
Texas leads for helicopters (1,574) and electric rotorcraft (1,164), but Iowa is second for electric rotorcraft with 1,013, more than California or Florida. New Mexico has the most balloons, 613, home of the Albuquerque balloon fiesta; California the most gliders.
2. As a share of each state's aircraft
share = tab.div(tab.sum(axis=1), axis=0)
big = share[tab.sum(axis=1) >= 1000]
for k in ["helicopter", "electric rotorcraft", "balloon"]:
print(f"{k:19} US {tab[k].sum() / tab.values.sum():.2%}; highest " + ", ".join(f"{s} {v:.1%}" for s, v in big[k].nlargest(3).items()))
helicopter US 4.85%; highest LA 13.7%, OR 8.8%, MD 8.4%
electric rotorcraft US 4.09%; highest IA 23.1%, NE 14.7%, NJ 14.6%
balloon US 1.69%; highest NM 19.9%, IA 4.5%, CO 4.4%
As a share of a state's registered aircraft, electric rotorcraft are 23.1% in Iowa, 14.7% in Nebraska and 14.6% in New Jersey. Helicopters are 13.7% in Louisiana, whose offshore platforms are reached by helicopter, and balloons 19.9% in New Mexico.
3. Per resident
spop = pop.assign(STUSPS=pop.STATE.map({v: k for k, v in STATEFP.items()})).groupby("STUSPS").POPESTIMATE2025.sum()
per = tab.div(spop, axis=0).mul(100_000).dropna()
print("helicopter:", ", ".join(f"{s} {v:.1f}" for s, v in per.helicopter.nlargest(4).items()))
print("electric rotorcraft:", ", ".join(f"{s} {v:.1f}" for s, v in per["electric rotorcraft"].nlargest(4).items()))
print("balloon:", ", ".join(f"{s} {v:.1f}" for s, v in per.balloon.nlargest(4).items()))
helicopter: DE 76.7, AK 53.8, MT 35.4, WY 30.6
electric rotorcraft: IA 31.3, ND 24.1, NE 21.2, SD 16.5
balloon: NM 28.8, SD 7.7, VT 7.4, IA 6.1
Per resident, the electric rotorcraft are a Corn Belt map: Iowa 31.3 per hundred thousand, North Dakota 24.1, Nebraska 21.2, South Dakota 16.5. Helicopters per resident are highest in Delaware, 76.7, an address effect, and in Alaska and Montana. Balloons are 28.8 per hundred thousand in New Mexico, nearly four times the next state.
Engines, and a state map
The data used on this page
The FAA's Releasable Aircraft Database, public domain, downloaded on 16 October 2026 and saved on this site, because the FAA replaces it every day. The saved copy leaves out the owners' names and street addresses and keeps five-digit ZIP codes; every other column is as published. With it come the Census Bureau's Vintage 2025 county population estimates, 2024 county boundaries and 2024 ZCTA gazetteer.
from pathlib import Path
import zipfile
import geopandas as gpd
import numpy as np
import pandas as pd
import requests
Path("data").mkdir(exist_ok=True)
# FAA Releasable Aircraft Database, 16 October 2026: MASTER.txt without the NAME, STREET, STREET2 and OTHER NAMES
# columns and with five-digit ZIP codes (MASTER-no-names.txt), ACFTREF.txt and ENGINE.txt as published; Census
# Vintage 2025 county estimates, 2024 cartographic boundary counties and 2024 ZCTA gazetteer. Saved here unchanged
# otherwise, because the FAA replaces the file daily.
# Live: https://registry.faa.gov/database/ReleasableAircraft.zip (needs a browser User-Agent),
# https://www2.census.gov/geo/docs/maps-data/data/gazetteer/2024_Gazetteer/2024_Gaz_zcta_national.zip
ARCHIVE = "faa-aircraft-registry-2026-10-16.zip"
if not Path(f"data/{ARCHIVE}").exists():
Path(f"data/{ARCHIVE}").write_bytes(requests.get(f"https://data.spatialworkflow.io/{ARCHIVE}", timeout=600).content)
Z = zipfile.ZipFile(f"data/{ARCHIVE}")
def faa(name):
"""One registry file: comma-separated, every field padded with spaces, a byte-order mark and a trailing comma."""
d = pd.read_csv(Z.open(name), dtype=str, encoding="utf-8-sig", keep_default_na=False)
d.columns = d.columns.str.strip()
d = d.loc[:, [c for c in d.columns if c and not c.startswith("Unnamed")]]
return d.apply(lambda c: c.str.strip())
reg = faa("MASTER-no-names.txt")
ref = faa("ACFTREF.txt")
TYPE_AIRCRAFT = {"1": "glider", "2": "balloon", "3": "blimp", "4": "fixed wing single engine", "5": "fixed wing multi engine",
"6": "rotorcraft", "7": "weight-shift", "8": "powered parachute", "9": "gyroplane", "H": "hybrid lift", "O": "other"}
REGISTRANT = {"1": "individual", "2": "partnership", "3": "corporation", "4": "co-owned", "5": "government", "7": "LLC",
"8": "non-citizen corporation", "9": "non-citizen co-owned", "": "blank"}
Path("data/cb_2024_us_county_20m.zip").write_bytes(Z.read("cb_2024_us_county_20m.zip"))
counties = gpd.read_file("data/cb_2024_us_county_20m.zip")
STATEFP = counties.drop_duplicates("STUSPS").set_index("STUSPS").STATEFP
pop = pd.read_csv(Z.open("co-est2025-alldata.csv"), encoding="latin-1", dtype={"STATE": str, "COUNTY": str})
pop = pop[pop.SUMLEV == 50].assign(GEOID=lambda p: p.STATE + p.COUNTY)
print(f"FAA registry, 16 October 2026: {len(reg):,} aircraft, {len(ref):,} make-and-model codes")
FAA registry, 16 October 2026: 317,604 aircraft, 94,115 make-and-model codes
Example 1: what the electric rotorcraft are
e = us[us.kind.isin(["electric rotorcraft", "hybrid lift"])].merge(ref[["CODE", "MFR", "MODEL"]], left_on="MFR MDL CODE", right_on="CODE", how="left")
print(e.groupby(["kind", "MFR", "MODEL"]).size().nlargest(6).to_string())
kind MFR MODEL
hybrid lift ZIPLINE INTERNATIONAL INC P2 ZIP 2979
electric rotorcraft DJI AGRAS T40 1737
AGRAS T50 1442
AGRAS T100 748
UVIFY 810-00028 650
AMAZON.COM SERVICES LLC MK30 615
The electric rotorcraft are DJI Agras T40, T50 and T100 crop-spraying drones, the most common three models, then UVify and Amazon's MK30 delivery drone. Nearly all hybrid-lift aircraft are Zipline P2 delivery drones, 2,979 of them.
Example 2: helicopters on a state map
states = counties[~counties.STUSPS.isin(["AK", "HI", "PR"])].dissolve("STUSPS").to_crs(5070)
m = states.join(per.helicopter.rename("heli"))
print(m.heli.describe()[["min", "50%", "max"]].round(1).to_string())
ax = m.plot(column="heli", cmap="Oranges", legend=True, figsize=(10, 6))
ax.set_axis_off()
min 0.8
50% 3.6
max 76.7
Helicopters per hundred thousand residents range from 0.8 to 76.7 across the lower 48, with a median of 3.6. Delaware's figure is a registration address, not a heliport count; after it come Alaska, 53.8, Montana, 35.4, and Wyoming, 30.6.
Internal links
- Read the FAA registry β the type codes and the reader
- Registered aircraft per resident β all aircraft by county
- Age of the fleet β how old each kind is
- Make and model β which helicopters these are