BIN, LOG & TLOG supported

ArduPilot flight log parser, as an API

Upload any dronelog from Copter, Plane, Rover, or Sub — dataflash .BIN / .LOG, or MAVLink .TLOG — and get back a clean CSV. No Mission Planner exports, no parsing code to maintain.

Free tier includes 100 API calls/month. No credit card required.

Terminal
# Queue a dataflash .BIN log
curl -X POST \
https://dronelogapi.com/api/v2/logs/upload/ardupilot \
-H "Authorization: Bearer YOUR_KEY" \
-F "file=@00000001.BIN"
# 202 — queued for async processing
{
"statusCode": 202,
"message": "Flight log queued for processing.",
"flightId": "9f2c8b3e-4b6a-4a1e-9c2d-7a1f6e0d5b21"
}
.BIN
Dataflash binary logs
.LOG+
Dataflash text & MAVLink .TLOG
Async*
Queued via job, poll for result
Any
Copter, Plane, Rover, Sub
How the parser works

From raw log file to structured data

01

Upload the raw log

POST the file straight off the SD card or telemetry radio — dataflash .BIN/.LOG, or MAVLink .TLOG, no conversion needed.

02

We decode & parse

The upload returns a flightId immediately. A background worker decodes MAVLink/dataflash messages — GPS, mode, battery — and merges them onto a single timeline.

03

Poll for the CSV

Poll the status endpoint with your flightId. Once status is processed, pull back the parsed CSV.

Parser output

What the parser pulls out of every log

GPS track

Lat/lng, altitude, and satellite count at every GPS fix — the timeline anchor for the rest of the log.

Flight mode

Current mode from dataflash MODE messages or MAVLink HEARTBEAT, forward-filled onto each GPS fix.

Battery telemetry

Voltage and current from dataflash BAT messages or MAVLink BATTERY_STATUS.

One row per GPS fix, with the latest known flight mode and battery state merged in — ready to drop into a spreadsheet or database.

Code examples

Convert an ArduPilot .BIN log to CSV

Upload the log, then poll the status endpoint with the returned flightId. Polling doesn't count toward your monthly API usage.

# 1. Upload — returns 202 with a flightId
curl -X POST https://dronelogapi.com/api/v2/logs/upload/ardupilot \
  -H "Authorization: Bearer YOUR_KEY" \
  -F "file=@00000001.BIN"

# 2. Poll until status is "processed" (or "failed")
curl https://dronelogapi.com/api/v2/logs/status/FLIGHT_ID \
  -H "Authorization: Bearer YOUR_KEY"
import time
import requests

API = "https://dronelogapi.com/api/v2/logs"
HEADERS = {"Authorization": "Bearer YOUR_KEY"}

with open("00000001.BIN", "rb") as log:
    upload = requests.post(API + "/upload/ardupilot", headers=HEADERS, files={"file": log})
upload.raise_for_status()
flight_id = upload.json()["flightId"]

while True:
    result = requests.get(API + "/status/" + flight_id, headers=HEADERS).json()
    if result["status"] in ("processed", "failed"):
        break
    time.sleep(2)

if result["status"] == "failed":
    raise RuntimeError(result["error"])

with open("flight.csv", "w") as out:
    out.write(result["csv"])
import { openAsBlob } from "node:fs";
import { writeFile } from "node:fs/promises";
import { setTimeout as sleep } from "node:timers/promises";

const API = "https://dronelogapi.com/api/v2/logs";
const headers = { Authorization: "Bearer YOUR_KEY" };

const form = new FormData();
form.append("file", await openAsBlob("00000001.BIN"), "00000001.BIN");

const upload = await fetch(API + "/upload/ardupilot", { method: "POST", headers, body: form });
if (!upload.ok) throw new Error(await upload.text());
const { flightId } = await upload.json();

let result;
do {
  await sleep(2000);
  result = await (await fetch(API + "/status/" + flightId, { headers })).json();
} while (!["processed", "failed"].includes(result.status));

if (result.status === "failed") throw new Error(result.error);
await writeFile("flight.csv", result.csv);
GET /api/v2/logs/status/{flightId} — 200
{"status": "pending"}

{"status": "processed", "csv": "..."}

{"status": "failed", "error": "decode error"}

Full request and error reference in the API documentation. Flying DJI too? See the DJI flight log parser.

FAQ

ArduPilot flight log parser — common questions

Dataflash binary .BIN logs (from the flight controller's SD card), dataflash text .LOG exports, and MAVLink telemetry .TLOG captures from a ground station. You upload the file as-is — the vendor and format are auto-detected.
ArduPilot writes dataflash logs to the SD card in the APM/LOGS folder, numbered per arming (00000001.BIN, 00000002.BIN, …). Copy them off the card, or download them over MAVLink from a ground station such as Mission Planner or QGroundControl.
A .BIN dataflash log is recorded on board by the flight controller at full rate. A .TLOG is recorded by the ground station from the MAVLink telemetry stream, so it only contains what was sent over the radio link. Both are accepted; .BIN usually has more detail.
Any vehicle running ArduPilot firmware — Copter, Plane, Rover, or Sub. The parser reads the standard dataflash/MAVLink message set shared across firmware types, so it isn't tied to a specific flight controller board.
ArduPilot logs can be large, so the upload endpoint returns a flightId right away with a 202 status and a background job decodes the log. Poll the status endpoint until status is processed, then read the csv field. Status checks don't count toward your monthly usage.
Both work. POST to the generic /api/v2/logs/upload endpoint and the vendor is detected from the file's magic bytes and extension, or POST directly to /api/v2/logs/upload/ardupilot to skip detection.
Every account gets 100 free API calls per month, no credit card required — enough to parse and inspect real logs before committing to a paid plan.

Stop parsing ArduPilot logs by hand

Get your API key in 30 seconds. 100 free calls per month, no credit card needed.

Free tier included No credit card Cancel anytime