Developer guide

The DJI flight log (.txt) format, explained

A DJI flight log (DJIFlightRecord_*.txt) is a binary file, not text. It has three parts: a header with the format version, a stream of typed records (telemetry, battery, gimbal, camera, remote controller, app messages) written about ten times per second, and a summary block with the aircraft, serial numbers and flight totals. From format version 13 the records are AES-encrypted, and the keys have to be requested from DJI for each log.

This guide is based on the parser behind the Dronelog DJI flight log parser API, which decodes these files in production.

File names and where they come from

DJI Fly, DJI GO 4 and DJI Pilot 2 write one flight record per flight to the app's FlightRecord folder:

DJIFlightRecord_YYYY-MM-DD_[HH-MM-SS].txt

The exact folder depends on the app and device. Our guide to where DJI flight logs are stored lists every path for Android, iOS and DJI controllers.

DJI Pilot 2 and FlightHub 2 can also produce FTR_Record_<flight-id>.txt files. Despite the similar extension, these are a different format: gzip-compressed JSON with device, flight and frameState sections, where each frame lists only the values that changed since the previous one. The rest of this page is about the binary DJIFlightRecord format.

File layout and header

Every flight record starts with a fixed-size header, called the prefix: 100 bytes on format version 6 and later, 12 bytes before that. All numbers are little-endian.

Offset Type Field
0u64Offset of the details (summary) block
8u16Length of the details block
10u8Format version
11 – 99—Encryption magic and reserved bytes

After the header come two regions: the records (the flight itself) and the details block (a summary). Where each one sits depends on the version. Up to v11 the records start right after the header and the details block sits at the offset in the header. v12 is a transitional layout. From v13 the details move into an auxiliary "Info" block in front of the records, followed by a "Version" block that holds the keychain version and department needed for decryption.

The details block is where the DETAILS fields come from: take-off location (street, city, area), start time, home coordinates, total distance and time, maximum height and speeds, photo count and video time, take-off altitude, aircraft model and name, the aircraft, camera, remote controller and battery serial numbers, and the app platform and version.

Each record in the records region is framed the same way:

type u8 length u8 (v12 and older) or u16 (v13 and later) content [length] bytes end u8 = 0xFF

Older logs can also contain embedded JPEG thumbnails between records, which a parser has to skip.

Format versions and encryption

How a record's content is protected depends on the format version in the header:

Version Record protection Decodable offline?
v0 – v6 None. Record payloads are stored as they are. Yes
v7 – v12 Each record is XOR-scrambled with a key derived from the record type and its first byte. Yes
v13 and later XOR, then AES-256-CBC per record group. The AES keys are not in the file; they come from DJI's keychain API. No, a DJI API call is needed per log

How v13+ decryption works

  1. Every record type belongs to a feature point, a group with its own AES key, such as Base, Vision, Waypoint, AirLink, Gimbal, RC, Camera, Battery or FlySafe. DJI names them like FR_Standardization_Feature_Base_1.
  2. The log carries the encrypted key material in its own key-storage records (types 50 and 56), which are not encrypted themselves.
  3. The parser sends those descriptors, together with the keychain version and department from the Version block, to DJI's flight-record keychain API. The request is authenticated with a DJI developer API key.
  4. DJI returns an AES key and IV per feature point. Records are then XOR-decoded and AES-256-CBC decrypted.
  5. The IV chains from record to record within a feature point: each record's last ciphertext block is the IV for the next one. Records must therefore be decrypted in file order, and a record that can't be decrypted still has to advance the chain.

This is why older open-source converters fail on current DJI Fly and DJI Pilot 2 logs, and why any tool that reads them needs network access to DJI.

Record types

These are the record types a parser needs to turn a flight record into a table, and the field categories they feed. A log contains other record types too (waypoint, agriculture, FlySafe and more). Many are written only by certain aircraft or app versions.

Type id Record Contents Fields
1 OSD Main telemetry: position, height, speeds, attitude, flight mode, GPS satellites. One CSV row per OSD record. OSD
2 Home Home point, return-to-home height, height limit. HOME
3 Gimbal Gimbal pitch, roll and yaw, gimbal mode. GIMBAL
4, 62 RC, RC display field Stick positions and buttons. v13+ logs drop type 4 and carry switch state in type 62. RC
49 OFDM Radio link quality, reported as uplink and downlink signal. RC
5 Custom Wall-clock timestamp and the aircraft odometer. CUSTOM
7, 8, 22, 63 CenterBattery, SmartBattery, SmartBatteryGroup, remaining time Pack voltage, current, cell voltages, temperature, charge level and charge cycles. Newer logs only write the SmartBatteryGroup record. BATTERY
25 Camera Photo and video state, shooting mode, SD card status. CAMERA
17 Vision Obstacle-avoidance and braking flags. MC
13 Recover Aircraft identity: product type, names and serials. RECOVER
40 Component serial Serial numbers of components such as the battery, camera and remote controller. SERIAL
14 App GPS The pilot's phone or controller location. APPGPS
9, 10, 24 App tip, warning, serious warning The messages the DJI app showed during the flight. APP
50, 56 Key storage v13+ only: the encrypted keychain descriptors that are sent to DJI to get the decryption keys. —

Inside the OSD record, latitude and longitude are 64-bit floats in radians. Height, speeds and attitude angles are scaled integers in tenths of a unit. Some columns, such as distance from home, are not in the file at all and are calculated from the telemetry.

Sample rate and timestamps

  • OSD sets the clock. The OSD record is written about ten times per second. Parsers produce one row per OSD record, so a CSV export has a row every 0.1 s of flight time.
  • Everything else is forward-filled. Battery, gimbal, camera and other records arrive at their own rate. Some, like the Vision record on v13+ logs, are written only when a value changes. A parser keeps the last value of each one and attaches it to the next OSD row.
  • Flight time vs wall-clock time. OSD.flyTime counts flight time, while Custom records carry the wall-clock timestamp. The details block holds the start time of the flight. Together they give each row a UTC time (CUSTOM.updateTime [UTC]).

.txt vs .DAT

The .txt flight record described here is written by the DJI app on your phone or controller. The aircraft also writes its own .DAT log, with more detailed sensor data, which you download with DJI Assistant 2. The two formats are unrelated, and tools for one don't read the other. The Dronelog API and free DJI flight log viewer read the .txt record. More on .DAT logs and how to download them.

How to parse a DJI flight log

You have two practical options:

  • Run an open-source parser. dji-log-parser is an MIT-licensed Rust library that implements the format above. Logs below v13 work offline. For v13+ logs you need your own DJI developer API key, because the parser has to call DJI's keychain API for every log. You also maintain the integration and keep up with new aircraft and format changes.
  • Call an API. The Dronelog DJI flight log parser takes the file as it is (encrypted or not), handles the DJI keychain call, and returns CSV with up to 477 columns in one request.

Converting a flight record to CSV with Python and the Dronelog API:

parse_dji_log.py
import requests

with open("DJIFlightRecord_2026-05-16_[19-02-56].txt", "rb") as log:
    response = requests.post(
        "https://dronelogapi.com/api/v2/logs/upload/dji",
        headers={"Authorization": "Bearer YOUR_KEY"},
        files={"file": log},
        data={"fields[]": ["OSD.flyTime [s]", "OSD.latitude", "OSD.longitude", "OSD.height [m]"]},
    )

response.raise_for_status()
print(response.text[:500])  # CSV, one row per OSD record

Leave out fields[] to get every column. Field names are listed in the DJI flight log field reference. For a side-by-side look at the options, see DJI flight log parsers compared.

Frequently asked questions

Is a DJI flight log a text file?

No. DJIFlightRecord files use a .txt extension, but they are binary: a fixed header, a stream of typed records and a summary block. Opening one in a text editor shows mostly unreadable characters.

What changed in DJI flight log version 13?

From format version 13, the records are AES-256-CBC encrypted on top of the older XOR scrambling, and the summary moved into an auxiliary block in front of the records. The AES keys are not stored in the file. A parser has to send the encrypted keychain descriptors from the log to DJI's keychain API and decrypt the records with the keys it returns.

Can I decrypt a DJI flight log offline?

Logs below version 13 can be decoded fully offline, because the XOR scheme is derived from the data itself. Version 13 and later logs cannot: each log needs one call to DJI's keychain API, made with a DJI developer API key.

How often does a DJI flight log record data?

The main telemetry record (OSD) is written about ten times per second, so OSD.flyTime advances in 0.1 second steps. Other records are written at their own pace, some only when a value changes, and parsers carry the last value forward onto the OSD timeline.

What is the difference between a DJI .txt flight log and a .DAT file?

The .txt flight record is written by the DJI app on your phone or controller. The .DAT log is written by the aircraft itself, holds more detailed sensor data, is usually encrypted, and is downloaded with DJI Assistant 2. This page and the Dronelog API cover the .txt flight record.

Are DJI Pilot 2 FTR_Record files the same format?

No. FTR_Record_<flight-id>.txt files from DJI Pilot 2 and FlightHub 2 are gzip-compressed JSON with device, flight and frame-state sections, where each frame only lists the values that changed. The Dronelog API detects them and returns the same CSV columns as for a regular DJIFlightRecord file.

How do I convert a DJI flight log to CSV?

Upload the .txt file (or a .zip of it) to POST /api/v2/logs/upload/dji. The Dronelog API decrypts it if needed, decodes every record and returns CSV in the same response. The free tier includes 100 calls per month.

Skip the decoding

Look at one flight in the free viewer, or parse any number of logs through the API. 100 free calls per month, no credit card needed.