# FAA Aircraft Registry Scraper (`normdata/faa-aircraft-registry-scraper`) Actor

Get the FAA registry of US civil aircraft: N-Number, manufacturer/model, engine, owner, address, registration status and expiration. Look up by N-Number or filter into a list. Also covers FAA dealer certificates, reserved N-Numbers and documents. No API key

- **URL**: https://apify.com/normdata/faa-aircraft-registry-scraper.md
- **Developed by:** [Norm Data](https://apify.com/normdata) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $11.05 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

![Norm Data](https://i.ibb.co/rGbhM5Y8/Chat-GPT-Image-Sep-8-2026-02-20-50-PM.png)

## FAA Aircraft Registry Scraper

Get the full **FAA registry of US-registered civil aircraft** with no API key and no login. Every
active N-Number: about 290,000 aircraft with manufacturer, model, engine, owner name and address,
registration status and expiration date. Filter into a list, or look up a specific aircraft by
N-Number. Also covers 3 more FAA datasets no other Apify Actor exposes: **dealer/manufacturer
certificates**, **reserved N-Numbers**, and **recorded aircraft documents** (liens, bills of
sale). Built for **aircraft ownership research, B2B lead generation, and fleet and title
verification**.

Here is one real row:

```json
{
  "n_number": "N172SP",
  "serial_number": "17280001",
  "manufacturer": "CESSNA",
  "model": "172 SKYHAWK",
  "year_manufactured": 2015,
  "type_aircraft": "Fixed Wing Single Engine",
  "number_of_engines": 1,
  "number_of_seats": 4,
  "engine_manufacturer": "LYCOMING",
  "engine_model": "IO-360",
  "type_engine": "Reciprocating",
  "engine_horsepower": 180,
  "registrant_type": "Corporation",
  "owner_name": "ACME AVIATION LLC",
  "co_owners": [],
  "city": "AUSTIN",
  "state": "TX",
  "address": "123 MAIN ST, AUSTIN, TX, 78701",
  "status": "Valid Registration",
  "is_valid_registration": true,
  "airworthiness_class": "Standard",
  "expiration_date": "2027-06-30",
  "scraped_at": "2026-09-11T12:00:00.000Z"
}
```

### What it does

Reads the FAA's own release of the aircraft registration database in one pass, joins each
aircraft against the FAA's manufacturer and engine reference tables, and normalizes every entry
into a flat row. Five modes:

- **Search** filters the active registry into a list: by N-Number, owner name, manufacturer,
  model, city, state, year range, aircraft type, or registrant type.
- **Look up** resolves exact N-Numbers, one row per identifier. An identifier not in the active
  registry comes back as an `error` row.
- **Dealers** lists FAA-certificated aircraft dealers and manufacturers, filterable by name,
  city, state, and whether the certificate is expired.
- **Reserved** lists N-Numbers reserved but not yet assigned to an aircraft, filterable by
  N-Number and registrant.
- **Documents** lists recorded liens, bills of sale, and other filed documents against
  aircraft, engines and propellers, filterable by N-Number and filed party.

Missing source values are returned as `null`, never invented.

### Why this scraper

- **Manufacturer and engine names, not raw codes.** The FAA's own files store an aircraft's
  make/model and engine as opaque codes; this Actor joins them against the FAA's reference
  tables so `manufacturer`, `model`, `engine_manufacturer` and `engine_model` are real names.
- **Registration status decoded.** `status`, `is_valid_registration` and `expiration_date` in one
  place, for an ownership or compliance check.
- **Registrant type filter.** Corporation, LLC, individual, co-owned, government and non-citizen
  registrants are all distinguishable, useful for a targeted B2B lead list.
- **Complete in one request.** The whole active registry, about 290,000 aircraft, comes back in
  one keyless request.
- **Dealers, reserved N-Numbers and recorded documents, not just the active registry.** Three
  more FAA datasets in the same Actor, no separate tool needed.
- **No API key, no login, no browser.** Reads only what the FAA publishes.

### Use cases

- **Aircraft ownership research.** Look up who owns a specific tail number, and their address.
- **B2B lead generation.** A filtered list of aircraft owners by state, aircraft type or
  registrant type (corporations and LLCs, for charter, maintenance or insurance outreach).
- **Fleet tracking.** Pull every aircraft registered to a company name across its N-Numbers.
- **Title and registration verification.** Confirm an aircraft's registration is valid before a
  purchase, and check its manufacturer, model and engine match what's represented.
- **Market research.** Track new-registration volume by manufacturer, model, state or year.
- **CRM and data enrichment.** Attach FAA registration status to aircraft or owner records.

### Quickstart

Search: Cessna aircraft registered to a corporation or LLC in Texas.

```json
{ "mode": "search", "manufacturer": "CESSNA", "state": ["TX"], "typeRegistrant": ["corporation", "llc"], "maxItems": 200 }
```

Every validly registered rotorcraft manufactured since 2015:

```json
{ "mode": "search", "typeAircraft": ["rotorcraft"], "yearFrom": 2015, "statusValidOnly": true, "maxItems": 500 }
```

Look up a batch:

```json
{ "mode": "lookup", "identifiers": ["N172SP", "N1", "N999ZZ"] }
```

Active dealers and manufacturers in California:

```json
{ "mode": "dealers", "state": ["CA"], "dealerExpiredOnly": false }
```

Reserved N-Numbers matching a name:

```json
{ "mode": "reserved", "ownerName": "ACME AVIATION" }
```

Recorded documents against a specific N-Number:

```json
{ "mode": "documents", "documentNNumber": "N172SP" }
```

### Input reference

| Field | Applies to | Description |
|---|---|---|
| `maxItems` | all | Ceiling on rows written. |
| `mode` | all | `search`, `lookup`, `dealers`, `reserved`, or `documents`. |
| `nNumber` | search | N-Number contains this text, with or without the leading N. |
| `ownerName` | search, reserved | Registrant name contains this text. |
| `manufacturer` / `model` | search | Aircraft manufacturer/model name contains this text. |
| `state` | search, dealers | Two-letter US state code(s) for the registrant/dealer address. |
| `city` | search, dealers | Registrant/dealer city contains this text. |
| `yearFrom` / `yearTo` | search | Year manufactured range. |
| `typeAircraft` | search | `fixed_wing_single`, `fixed_wing_multi`, `rotorcraft`, `glider`, `balloon`, `gyroplane`, `weight_shift_control`, `powered_parachute`, `blimp_dirigible`, `hybrid_lift`, `other`. |
| `typeRegistrant` | search | `individual`, `partnership`, `corporation`, `co_owned`, `government`, `llc`, `non_citizen_corporation`, `non_citizen_co_owned`. |
| `statusValidOnly` | search | Only aircraft with a currently valid registration. |
| `identifiers` | lookup | N-Numbers, with or without the leading N. |
| `dealerName` | dealers | Dealer/manufacturer name contains this text. |
| `dealerExpiredOnly` | dealers | Only dealers whose certificate has expired. |
| `reservedNNumber` | reserved | Reserved N-Number contains this text, with or without the leading N. |
| `documentNNumber` | documents | Aircraft N-Number contains this text (documents filed against an aircraft, not an engine or propeller). |
| `documentPartyName` | documents | Filed party name contains this text. Note: the FAA's current file ships this column empty for every document; see FAQ. |

### Output reference (selected)

| Field | Description |
|---|---|
| `n_number` / `serial_number` | Identity. |
| `manufacturer` / `model` / `year_manufactured` / `type_aircraft` | Airframe. |
| `number_of_engines` / `number_of_seats` | From the manufacturer reference table. |
| `engine_manufacturer` / `engine_model` / `type_engine` / `engine_horsepower` / `engine_thrust_lbs` | Engine. |
| `registrant_type` / `owner_name` / `co_owners` | Registrant. |
| `street1` / `street2` / `city` / `state` / `zip` / `region` / `address` | Location. |
| `status_code` / `status` / `is_valid_registration` / `airworthiness_class` | Registration status. |
| `last_activity_date` / `cert_issue_date` / `airworthiness_date` / `expiration_date` | Key dates. |
| `mode_s_code` / `mode_s_code_hex` | Transponder code, for ADS-B correlation. |
| `fractional_ownership` | Fractional-ownership program flag. |
| `query` / `error` | Set on an unresolved look-up row. |
| `certificate_number` / `ownership_type` / `name` | Dealer identity. |
| `is_expired` / `cumulative_issue_count` | Dealer certificate status. |
| `registrant` / `reserve_date` / `reservation_type` / `expiration_notice_date` / `n_number_for_change` / `purge_date` | Reserved N-Number. |
| `collateral_type` / `collateral` / `party_name` / `document_id` | Document identity. |
| `receipt_date` / `correction_date` / `correction_type` / `serial_id` / `document_type` | Document detail. |
| `street1` / `street2` / `city` / `state` / `zip` / `address` | Shared by dealers and reserved N-Numbers too. |
| `scraped_at` | ISO 8601 collection timestamp. |

### Run via API and CLI

```bash
curl -X POST "https://api.apify.com/v2/acts/USERNAME~faa-aircraft-registry-scraper/run-sync-get-dataset-items?token=<TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"mode":"lookup","identifiers":["N172SP"]}'
```

```bash
apify call USERNAME/faa-aircraft-registry-scraper --input '{"mode":"search","state":["CA"],"typeRegistrant":["llc"],"maxItems":1000}'
```

### Fetch results

```bash
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=json"
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=csv"
```

### Billing and limits

- **Pay per result.** Billed per aircraft row written.
- **No charge on failure.** A run that produces zero rows fails with a message and is not
  billed.
- An unresolved look-up identifier still writes one `error: "not found"` row and is billed as a
  base row.
- **Free Apify plans** run the built-in 10-row sample only.
- The whole registry comes back in a single keyless request, so a full run finishes quickly.
  There is no pagination.

### FAQ and troubleshooting

**Do I need an API key?** No. The FAA aircraft registry is public, with no key and no login.

**Why did my run return zero rows?** No aircraft matched the filters. Loosen them. A zero-row
run fails and is not billed.

**Why is `manufacturer` or `model` null for some aircraft?** A small share of aircraft carry a
manufacturer/model code the FAA's own reference table does not define (amateur-built and kit
aircraft especially). The Actor reports `null` rather than guessing; `kit_manufacturer` and
`kit_model` cover most of the amateur-built gap.

**Can I look up an aircraft that's been sold, scrapped or deregistered?** Only if it is still on
the active registry. A deregistered N-Number comes back as an `error` row; deregistered aircraft
are not covered by this Actor.

**Why is `party_name` empty on every `documents` row?** Verified against the FAA's current file:
it ships this column empty for all recorded documents, not a bug in this Actor. `collateral`
(the N-Number, engine or propeller the document is filed against), `document_id`, `receipt_date`
and `document_type` are all populated.

**How current is the data?** The FAA refreshes its release file daily. It is not real time.

**Is this an official FAA tool?** No. Independent, not affiliated with the Federal Aviation
Administration. It reads only data the FAA publishes.

### Local development

```bash
bun install
bun test                       # offline: parsing, normalisation, input logic
bun run src/main.ts            # reads storage/key_value_stores/default/INPUT.json
bun scripts/verify-live.mjs    # hits registry.faa.gov directly, checks every mode (search/lookup/dealers/reserved/documents)
```

# Actor input Schema

## `maxItems` (type: `integer`):

Caps how many aircraft rows this run writes. Starts at 10 for a quick sample; raise it for a full run (the active registry is about 290,000 aircraft).

## `mode` (type: `string`):

Search/Look up cover the active aircraft registry. Dealers, Reserved and Documents are 3 separate FAA datasets with their own filters below.

## `nNumber` (type: `string`):

Match aircraft whose N-Number contains this text (with or without the leading N).

## `ownerName` (type: `string`):

Match aircraft whose registrant name contains this text.

## `manufacturer` (type: `string`):

Match aircraft whose manufacturer name contains this text, e.g. CESSNA, CIRRUS, ROBINSON.

## `model` (type: `string`):

Match aircraft whose model name contains this text.

## `state` (type: `array`):

Two-letter US state code(s) for the registrant address, e.g. CA, TX, FL. Leave empty for all states.

## `city` (type: `string`):

Match aircraft whose registrant city contains this text.

## `yearFrom` (type: `integer`):

Only aircraft manufactured in or after this year.

## `yearTo` (type: `integer`):

Only aircraft manufactured in or before this year.

## `typeAircraft` (type: `array`):

Restrict by airframe type.

## `typeRegistrant` (type: `array`):

Restrict by owner/registrant type. Corporation and LLC are the two most useful for B2B lead lists.

## `statusValidOnly` (type: `boolean`):

Only aircraft with a currently valid registration on file, excluding expired, revoked, pending and reserved records.

## `identifiers` (type: `array`):

FAA N-Numbers, with or without the leading N (e.g. N172SP or 172SP). Unmatched identifiers come back as an error row.

## `dealerName` (type: `string`):

Match dealer certificate holders whose name contains this text. Also uses State and City above.

## `dealerExpiredOnly` (type: `boolean`):

Only dealer certificates flagged expired in the source.

## `reservedNNumber` (type: `string`):

Match a reserved N-Number, with or without the leading N. Also uses Owner name (registrant) and State above.

## `documentNNumber` (type: `string`):

Match recorded documents (liens, bills of sale, security agreements) filed against this N-Number, with or without the leading N.

## `documentPartyName` (type: `string`):

Match documents where the named party (lienholder, buyer, seller) contains this text.

## Actor input object example

```json
{
  "maxItems": 10,
  "mode": "search",
  "state": [
    "CA"
  ],
  "statusValidOnly": false,
  "dealerExpiredOnly": false
}
```

# Actor output Schema

## `results` (type: `string`):

One dataset row per aircraft (or per look-up N-Number), with N-Number, manufacturer/model, engine, owner and address, and registration status/expiration.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "maxItems": 10,
    "mode": "search",
    "state": [
        "CA"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("normdata/faa-aircraft-registry-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "maxItems": 10,
    "mode": "search",
    "state": ["CA"],
}

# Run the Actor and wait for it to finish
run = client.actor("normdata/faa-aircraft-registry-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "maxItems": 10,
  "mode": "search",
  "state": [
    "CA"
  ]
}' |
apify call normdata/faa-aircraft-registry-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,normdata/faa-aircraft-registry-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/4K0cs8cq4C6vgViiW/builds/ujoeRu0KhtiCBQt7t/openapi.json
