API
No API key or authentication is required.
GET /flights
Returns one page of flights, newest first. Up to limit flights per response (default
and max 1000); pass offset to skip ahead. Follow the next URL in the response, requesting it as-is, until it's null, to iterate the whole dataset.
By default each flight contains only url, a direct link to the .igc file. Use fields to ask for more.
Query parameters
| Param | Default | Description |
|---|---|---|
limit | 1000 | Flights to return, 1–1000 |
offset | 0 | Number of flights to skip |
fields | url | Which flight fields to return (see below) |
Choosing fields
fields takes a comma-separated list of the field names in the table below — for example fields=id,flight_date,url. Pass fields=all for every field. Only what you ask for is read from the database and sent
back, so requesting less is faster and cheaper for both of us. An unrecognised field name is an error (400) rather than being ignored, so typos don't silently return the wrong shape.
Fields come back in the order listed in the table, whatever order you ask for them in, and fields is carried over into the next URL — so paging keeps
your selection without you re-adding it.
Changed: this endpoint used to return every field by default. If you have an
existing integration that reads anything other than url, add ?fields=all to restore the old response, or better, list just the fields you use.
Examples
curl https://open-igc-database.pages.dev/flights
curl "https://open-igc-database.pages.dev/flights?fields=id,flight_date,duration_s,url"
curl "https://open-igc-database.pages.dev/flights?fields=all&limit=10" Response fields
| Field | Type | Description |
|---|---|---|
flights | array | Flight objects for this page (fields below) |
total | number | Total number of flights in the database |
limit | number | Effective limit used for this page |
offset | number | Effective offset used for this page |
next | string | null | URL for the next page, or null if this was the last one |
Every name below is a valid fields value. Each object in flights contains exactly the ones you selected:
| Field | Type | Description |
|---|---|---|
id | string | SHA-256 of the IGC file (also the file key) |
flight_date | string | Flight date, YYYY-MM-DD |
pilot_name | string | null | Pilot name from the IGC header |
takeoff_lat | number | Takeoff latitude |
takeoff_lon | number | Takeoff longitude |
landing_lat | number | Landing latitude |
landing_lon | number | Landing longitude |
duration_s | number | Flight duration in seconds |
max_altitude | number | null | Max altitude in metres |
point_count | number | Number of GPS fixes |
glider_type | string | null | Glider model from the IGC header |
size_bytes | number | Size of the IGC file in bytes |
takeoff_hour | number | null | Local hour of day at takeoff, 0–23 (null for flights stored before this field existed) |
takeoff_tz | string | null | IANA time zone at takeoff, e.g. Europe/Paris |
url | string | Direct link to the .igc file (the default; see note below) |
The file behind url is stored and served gzip-compressed (Content-Encoding: gzip). Browsers and fetch decode this automatically; with curl or wget add --compressed or you'll get the raw gzip bytes:
curl --compressed -o flight.igc "https://…/a1b2c3….igc" Sample response
Default (GET /flights):
{
"flights": [
{ "url": "https://…/a1b2c3….igc" },
{ "url": "https://…/d4e5f6….igc" }
],
"total": 4213,
"limit": 1000,
"offset": 0,
"next": "https://…/flights?limit=1000&offset=1000"
} With ?fields=all (the flights array only, other fields unchanged):
"flights": [
{
"id": "a1b2c3…",
"flight_date": "2024-06-15",
"pilot_name": "Jane Doe",
"takeoff_lat": 45.9237,
"takeoff_lon": 6.8694,
"landing_lat": 45.8992,
"landing_lon": 6.1294,
"duration_s": 5432,
"max_altitude": 2850,
"point_count": 5431,
"glider_type": "Ozone Zeno 2",
"size_bytes": 184320,
"uploaded_at": 1718460000,
"takeoff_hour": 14,
"takeoff_tz": "Europe/Paris",
"url": "https://…/a1b2c3….igc"
}
], POST /flights
Upload a single .igc file, sent as the raw request body. The file is parsed, validated and
stored. Flights are deduplicated by content, so re-uploading the same track is safe.
Add ?anonymous=1 to strip identifying headers (pilot, crew, glider registration,
competition id) before storing and list the pilot as Anonymous.
Example
curl --data-binary @flight.igc -H "Content-Type: application/octet-stream" https://open-igc-database.pages.dev/flights Responses
| Status | Meaning |
|---|---|
201 | Flight added |
200 | Duplicate — this track was already stored |
400 | Empty body or not a valid IGC track (see error) |
On success the response is the full flight object — every field listed above, as with ?fields=all — plus a status field of "added" or "duplicate". There is no fields param here; it's a single row, so it's always sent in full.
Sample response
{
"status": "added",
"id": "a1b2c3…",
"flight_date": "2024-06-15",
"pilot_name": "Jane Doe",
"takeoff_lat": 45.9237,
"takeoff_lon": 6.8694,
"landing_lat": 45.8992,
"landing_lon": 6.1294,
"duration_s": 5432,
"max_altitude": 2850,
"point_count": 5431,
"glider_type": "Ozone Zeno 2",
"size_bytes": 184320,
"uploaded_at": 1718460000,
"takeoff_hour": 14,
"takeoff_tz": "Europe/Paris",
"url": "https://…/a1b2c3….igc"
}