Skip to content

Output

Each new log entry becomes one JSON object on one line of stdout, marked "kind": "event". The tool's own messages go to stderr, also as JSON lines but marked "kind": "log", see Own log lines.

{"kind": "event", "event_time": "2026-10-09T08:31:57+02:00", "time_estimated": false, "box_time": "09.10.26 08:31:57", "device": "fritz.box", "host": "fritz.box", "serial": "...", "group": "net", "id": 22, "msg": "Internetverbindung wurde erfolgreich hergestellt. ...", "repeat": 1}

Fields

Field Meaning
kind Always event; the tool's own log lines say log
event_time When it happened, ISO 8601 with the box's UTC offset (without one if the box does not tell its time zone)
time_estimated true for entries the box logged after a reboot, before it had synced its clock; see below
box_time The time as the box shows it
device, host, serial The device's name from the configuration, its hostname and its serial number
group sys, net, wlan, …
id The message type; does not depend on the box's language
msg The message as the box words it, in its language, without the counter of repeats
repeat How many occurrences this line stands for, see Repeats

Every field comes from the box and may hold text typed by someone else, for example a user name in a failed login. JSON encoding escapes it, so it cannot break a line. URLs keep only scheme and host (https://ddns.example.com/<redacted>): a DynDNS update URL can carry user name, password or token anywhere after the host. A DynDNS token outside a URL (q=...) becomes q=<redacted>.

Repeats

When the same message comes again right away, the box does not add a row: it bumps a counter on the existing row ([3 Meldungen seit …]) and moves the row to the time of the latest occurrence. The tool prints one line per such change, with repeat set to the number of new occurrences and event_time the latest one; the times in between are lost on the box.

A repeat with another message in between gets a row of its own on the box, and a line with repeat: 1 from the tool.

Restarts and reboots

The tool keeps a state file per device in state_dir, so a restart does not print the log again. A reboot of the box empties its log; the tool notices it from the uptime and prints everything the box logs after it. Entries the box logs in the last moments before a reboot are lost if no poll fetched them.

Entries before time sync

After a reboot, the box dates its entries 01.01.70 until it has synced its clock, with the time since boot as time of day. Once synced, it rewrites them to the real time. The tool works out the real time from the uptime right away and marks these lines with time_estimated: true. The estimate is within a second or so of what the box shows later. While the box has no time of its own yet, event_time is in UTC.

Mesh

A FRITZ!Box that is mesh master also shows the log of its repeaters, as rows starting with [fritz.repeater]. Polling the box is enough; polling the repeaters as well gives their entries twice.

Own log lines

The tool logs to stderr, by default as one JSON object per line:

{"time": "2026-10-31T16:30:51.485+00:00", "kind": "log", "level": "INFO", "logger": "fritzlogextractor", "msg": "Configured 1 device(s), polling every 60s"}
Field Meaning
time When it was logged, in UTC
kind Always log
level DEBUG, INFO, WARNING, ERROR or CRITICAL
logger Which part logged it, e.g. fritzlogextractor.extractor, or a library such as urllib3
msg The message
exc Only on errors with a traceback: the traceback, in the same line

So a log stack that gets stdout and stderr mixed can still sort events and log lines apart on kind. For reading in a terminal, --log-format text switches to the classic format:

2026-10-31 17:30:51,485     INFO fritzlogextractor | Configured 1 device(s), polling every 60s

Own logins

Each login of the tool shows up in the log as "Anmeldung einer App" (id 506 or 507), once per session: at start and after connection errors.