Use the data
Read any record on the web, hand it to an LLM as Markdown, or download the whole release as DuckDB, SQLite and Parquet. No sign-up and no API key.
Permalinks for all documents
Every document has its own predictable URL at openairdocs.org.
Each document has an AI-friendly Markdown version at the same URL plus .md, to give to an LLM.
Every list shows the DuckDB query that reads it from the Parquet files. Pages are cached for a day and change when a new release lands.
Records
Lists and search
Give your model these directions
Paste them into ChatGPT, Claude or another assistant that can run code. It will query the DuckDB file over HTTPS, with no API key, and link the pages it used.
An assistant that browses can start from llms.txt instead, and read any record by adding .md to its address.
You can query OpenAirDocs, an open copy of U.S. aviation data: FAA airworthiness directives (ADs) with their full text, proposed ADs, SAIBs, type certificate data sheets, STCs, advisory circulars, the aircraft registry with every cancelled registration, service difficulty reports, FAA accident and incident reports, and every NTSB aviation investigation since 1962. Public domain (CC0), release 2026-10-21. QUERY with DuckDB (1.2 or later). Attach the release's one database file over HTTPS; DuckDB reads only the parts each query needs: ATTACH 'https://openairdocs.org/data/latest/openair.duckdb' AS openair (READ_ONLY); USE openair; Tables are then named (FROM faa_directive). Every table and column is described in the file; read a table's descriptions before querying it: SELECT table_name, comment FROM duckdb_tables() WHERE database_name = 'openair'; SELECT column_name, data_type, comment FROM duckdb_columns() WHERE table_name = 'ntsb_case_detail'; Views for common questions: ntsb_pre1982_cause: The causes and factors of NTSB cases before 1982, in words: one row per coded cause or factor, decoded the way NTSB's brief prints it (WEATHER - LOW CEILING). ntsb_case: Every NTSB case in one row, with the facts most questions need: local date, place and point, injuries, aircraft, N-numbers, probable cause (decoded for cases before 1982) and the case's page. aircraft_history: Everything recorded about one N-number, a row each: the aircraft registered now, cancelled registrations, NTSB investigations, FAA accident and incident reports, and service difficulty reports, with a one-line summary and the record's page. geo_location: Every point of the geo_* tables, with its dataset and record id (as text): one place to map everything. openair_page: each record table's web page address, with the SQL that builds it. SELECT record, event_date, summary, page_url FROM aircraft_history WHERE n_number = 'N222UM' ORDER BY event_date; Joins: - faa_directive.ad_id joins every faa_directive_* table, and the candidate tables faa_aircraft_model_directive and faa_engine_model_directive that match ADs to registry models. - faa_aircraft_registration (and faa_aircraft_deregistration, where N-numbers repeat) point to faa_aircraft_model.code by aircraft_model_code and to faa_engine_model.code by engine_model_code. - A model_key is the model in upper case with only letters, digits and + (PA-28-181 is PA28181); faa_aircraft_model, faa_engine_model and the product tables carry one. - Each NTSB case is one row of ntsb_case_detail, keyed by mKey; every other ntsb_ table joins on case_mkey. ntsb_aircrafts, faa_incident_report and faa_service_difficulty_report carry n_number. Watch for: - Matches between records (an AD to an aircraft, an NTSB case to a registration) are candidates. Check each AD's applicability (serial numbers, part numbers, configuration) before saying it applies, and cite AD numbers. - NTSB's eventDate is the UTC date from 1982 on, so an evening event shows the next day: use ntsb_case.event_date_local. - Owner and operator names are spelled as each record reports them: compare upper(name). - Only the Federal Register PDF on govinfo.gov is the official text of an AD. CITE every record by its page on OpenAirDocs. Add .md to any page for a Markdown copy to read: Airworthiness directive (AD) https://openairdocs.org/ad/<AD number> Registered aircraft https://openairdocs.org/aircraft/<N-number> Cancelled registration https://openairdocs.org/deregistered/<N-number>-<cancellation date> Aircraft model https://openairdocs.org/model/<maker-model> Type certificate data sheet (TCDS) https://openairdocs.org/tcds/<number> Supplemental type certificate (STC) https://openairdocs.org/stc/<number> Special airworthiness information bulletin (SAIB) https://openairdocs.org/saib/<number> Advisory circular (AC) https://openairdocs.org/ac/<number> Service difficulty report https://openairdocs.org/sdr/<id> FAA accident or incident report https://openairdocs.org/incident/<report number> NTSB investigation https://openairdocs.org/ntsb/<NTSB number> Without SQL, read pages directly: https://openairdocs.org/aircraft/N333UM.md has an aircraft's registration, the ADs that may apply, and its NTSB and FAA reports. Search: https://openairdocs.org/search.md?q=fuel+selector. Every table and recipes: https://openairdocs.org/data/dictionary.md. Everything else: https://openairdocs.org/llms.txt.
Query the DuckDB file
Every table is in one DuckDB file, 821 MB. Attach it over HTTPS and DuckDB fetches only the parts a query needs, so there’s nothing to download first. Or download it and work offline.
Install DuckDB (1.2 or later), start it in a terminal, then run a query. Each table is also a Parquet file, for tools that read Parquet.
duckdb
ATTACH 'https://openairdocs.org/data/latest/openair.duckdb' AS openair (READ_ONLY); USE openair; -- ADs that name a model SELECT d.ad_number, d.status, d.subject, d.effective_date FROM faa_directive_product p JOIN faa_directive d USING (ad_id) WHERE p.model_key = 'PA28181' ORDER BY d.effective_date DESC; -- Every table and column is described in the file SELECT column_name, data_type, comment FROM duckdb_columns() WHERE table_name = 'faa_directive';
-- ADs that name a model, straight from the Parquet files SELECT d.ad_number, d.status, d.subject, d.effective_date FROM 'https://openairdocs.org/data/latest/faa_directive_product.parquet' p JOIN 'https://openairdocs.org/data/latest/faa_directive.parquet' d USING (ad_id) WHERE p.model_key = 'PA28181' ORDER BY d.effective_date DESC;
Download SQLite
The SQLite files hold every table, with indexes and full-text search, for offline use. Service difficulty reports are in their own file.
curl -O https://openairdocs.org/data/latest/openair.sqlite.zst zstd -d openair.sqlite.zst sqlite3 openair.sqlite " SELECT ad_number, subject, effective_date FROM faa_directive WHERE status = 'Current' ORDER BY effective_date DESC LIMIT 10;"
-- Full-text search over every AD paragraph (SQLite FTS5)
SELECT s.ad_id, s.heading,
snippet(faa_directive_section_fts, -1, '[', ']', '…', 8) AS match
FROM faa_directive_section_fts
JOIN faa_directive_section s ON s.rowid = faa_directive_section_fts.rowid
WHERE faa_directive_section_fts MATCH '"fuel selector"'
ORDER BY rank
LIMIT 10;Load it from Hugging Face
Every table is also on Hugging Face, in the dataset openairdocs/openairdocs. Browse a table in its viewer, or load it with the datasets library or DuckDB.
Each release is a tag there, so code pinned to one keeps getting the same rows.
from datasets import load_dataset
# One table (a subset) at a time
ads = load_dataset("openairdocs/openairdocs", "faa_directive",
split="train")
# Pinned to a release
ads = load_dataset("openairdocs/openairdocs", "faa_directive",
split="train", revision="2026-10-21")SELECT ad_number, subject, effective_date FROM 'hf://datasets/openairdocs/openairdocs/faa_directive.parquet' ORDER BY effective_date DESC LIMIT 10;
Download
Release statusDocumentation · 2
Read these first.
Databases · 3
Every table, ready to query. Most people want the DuckDB file: one file, described inside, that DuckDB can read over HTTPS. The SQLite files add full-text search, for offline use.
duckdb -c "ATTACH 'https://openairdocs.org/data/latest/openair.duckdb' AS openair (READ_ONLY); SELECT ad_number, subject, effective_date FROM openair.faa_directive ORDER BY effective_date DESC LIMIT 10"
Parquet · 68
One file per table. Query them over HTTPS without downloading, or load them into anything that reads Parquet.
duckdb -c "SELECT ad_number, subject, effective_date FROM 'https://openairdocs.org/data/latest/faa_directive.parquet' ORDER BY effective_date DESC LIMIT 10"