Codec 8, 8E and 16 explained: how Teltonika packages AVL data

· Updated 
Codec 8, 8E y 16: cómo Teltonika empaqueta los datos AVL

If you have worked with a Teltonika in production, at some point you have hit the question: which codec should I use, 8, 8E or 16? The short answer is almost always Codec 8E. The long answer requires understanding how Teltonika packages AVL data, why three formats exist, and when each is right. This post is the reference we would have liked when we integrated the first FMC920.

What a codec is in Teltonika

A codec in the Teltonika world is not audio or video. It is the binary format the device uses to serialise telemetry records (position, speed, IOs, events) before sending them to the server over TCP. It is the protocol's "schema": it defines which fields are sent, in what order, with what type and size.

When you configure a Teltonika pointing at your server (Traccar, Wialon, Fletaro or your own), the codec is the contract between the two. If the server does not implement the codec the device sends, it cannot decode the frame.

The three most used codecs today are:

  • Codec 8 — the original classic. 1-byte AVL ID. Limited but compact.
  • Codec 8 Extended (8E) — extends AVL ID to 2 bytes. It is the default codec on all modern Teltonika devices (FMB, FMC, FMM and later).
  • Codec 16 — additional, adds an explicit generation type per record. Useful to distinguish events from periodic records.

General structure of an AVL packet

Before getting into each codec, this is the common TCP envelope of any Teltonika packet:

Preamble (4 bytes)      → 0x00000000
Data Field Length (4)   → number of bytes in the data field
Codec ID (1)            → 0x08, 0x8E, 0x10 (16 decimal)
Number of Data 1 (1)    → how many AVL records follow
[AVL Data ...]          → AVL records in codec format
Number of Data 2 (1)    → same number as the first
CRC-16 (4)              → CRC of Data Field Length+Data

The Codec ID identifies the AVL block format. What changes between codec 8, 8E and 16 is how each AVL record is serialised inside that block.

Codec 8 (Codec ID = 0x08)

The original codec. Each AVL record includes:

Timestamp (8 bytes)         → ms since epoch (UTC)
Priority (1 byte)           → 0=low, 1=high, 2=panic
GPS Element (15 bytes):
  Longitude (4)             → signed int, multiply by 10⁻⁷ degrees
  Latitude (4)              → same format
  Altitude (2)              → metres
  Angle (2)                 → 0-359°
  Satellites (1)            → number of satellites in use
  Speed (2)                 → km/h
IO Element:
  Event IO ID (1)           → AVL ID that triggered this record (0 = periodic)
  Total IO (1)              → total number of IOs in the record
  N1 (1) + [IO ID (1) + Value (1 byte)] × N1
  N2 (1) + [IO ID (1) + Value (2 bytes)] × N2
  N4 (1) + [IO ID (1) + Value (4 bytes)] × N4
  N8 (1) + [IO ID (1) + Value (8 bytes)] × N8

Key limitation: the AVL ID is encoded in 1 byte (0-255). That is enough for basic IOs (ignition, speed, voltage, GSM signal) but not for all AVL IDs that exist in modern Teltonika. The FMC920 alone has ~190 declared AVL IDs. The total ecosystem (with CAN bus, external sensors, LV-CAN modules) exceeds 1,500. They do not fit in 1 byte.

Codec 8 still works for basic cases (tracking + a handful of IOs), but it is deprecated. If you are starting a new project, do not use it.

Codec 8 Extended / 8E (Codec ID = 0x8E)

The natural extension of 8: AVL ID goes from 1 byte to 2 bytes (65,535 possible values), and a Variable Length IO field is added for arbitrary-length data (needed for sensors that return strings, binary blobs or long data such as CAN event maps).

Timestamp (8 bytes)            → identical to Codec 8
Priority (1)                   → identical
GPS Element (15 bytes)         → identical
IO Element:
  Event IO ID (2 bytes)        → ← change: now 2 bytes
  Total IO (2)                 → ← change: now 2 bytes
  N1 (2) + [IO ID (2) + Value (1)] × N1
  N2 (2) + [IO ID (2) + Value (2)] × N2
  N4 (2) + [IO ID (2) + Value (4)] × N4
  N8 (2) + [IO ID (2) + Value (8)] × N8
  NX (2) + [IO ID (2) + Length (2) + Value (Length)] × NX   ← variable length

Codec 8E is the recommended default choice for any modern Teltonika device. It supports the full range of current and future AVL IDs, supports variable payloads (needed for CAN-CONTROL, 1-Wire readers, BLE sensors), and every serious platform implements it.

Example: decoding a real 8E AVL Element

Sample frame (in hex), captured from an FMC920 sending position + 5 IOs:

00000000 00000089 8E 01
00 0001 87B2 33BE 00
00 01D6CC9F 4F35EAD2
0064 0000 0F 09 00
0005 0000  ← Event IO ID (=0, periodic) and Total IO (=5)
0005       ← N1 (5 IOs of 1 byte)
  0015 03  → IO 21 (GSM signal) = 3
  0001 01  → IO 1 (Digital Input 1) = 1
  0042 5C  → IO 66 (Battery voltage centiV) = 92  → 9.2V
  00B5 0F  → IO 181 (GNSS HDOP) = 15
  00B6 0B  → IO 182 (GNSS PDOP) = 11
0000       ← N2 (0 IOs of 2 bytes)
0000       ← N4
0000       ← N8
0000       ← NX
01
00007D8B   ← CRC

That same frame in Codec 8 would be ~10 bytes shorter (because AVL IDs would be 1 byte), but IO 181 and IO 182 would not even fit (their IDs are > 255).

Codec 16 (Codec ID = 0x10)

Codec 16 introduces a Generation Type field for each AVL record. It is similar to Codec 8 (1-byte AVL ID), but adds information on the cause of the record:

Timestamp (8 bytes)
Timestamp Extension (1 byte)     ← microseconds / generation
Priority (1)
GPS Element (15)
Event IO ID (2 bytes)            ← same extension as 8E
Generation Type (1 byte)         ← cause of the record: 0=on exit, 1=on entrance,
                                   2=on both, 3=reserved, 4=hysteresis,
                                   5=on change, 6=eventual, 7=periodical
N1 ... NX (identical to 8E)

Codec 16 is for cases where you need to know exactly why a record was generated without having to infer it from the Event IO ID. Useful in large fleets where you want to post-process events discriminating between "periodic record every 30s" and "event-triggered record" without looking at the AVL ID.

In practice almost nobody uses Codec 16. If you need it, you already know why; if you don't, stick with 8E.

When to use each codec

Scenario Recommended codec
New project, modern device (FMB, FMC, FMM, MTB) Codec 8E
You will read the CAN bus or connect BLE/RS485 sensors Codec 8E (you need IDs >255 and variable length)
Integration with a legacy server that only supports Codec 8 Codec 8 (short term, migrate to 8E as soon as possible)
Regulatory audit that requires explicit generation type per record Codec 16
Legacy FM devices (FM1100, FM2200, FM3622) in inherited production Codec 8 (8E not supported on old hardware)

Rule of thumb: if your device is FMB / FMC / FMM and your platform is modern (Wialon, Traccar >= 5.0, Fletaro, GpsGate, Flespi), pick Codec 8E and forget about it.

Additional codecs that exist but you rarely see

  • Codec 12 — GPRS commands: the server sends commands to the device (reboot, configuration change, status query). Used by the remote configuration tool and platforms that send remote commands.
  • Codec 13 — response to Codec 12. The device replies.
  • Codec 14 — commands by IMEI / direct addressing, similar to 12 but with explicit IMEI addressing.
  • Codec 7 / 7E — for file download (typically digital tachograph). The FMC650 downloads DDDs using Codec 7E.

These do not compete with Codec 8/8E/16: they are parallel channels for specific tasks (commands, file download). Your server probably implements them transparently.

How to configure the codec on a Teltonika

Via the official configuration tool (FM Configurator connected by USB cable) or via FOTA with the FOTA Web platform:

  • System → Codec: dropdown with the options available in the current firmware.
  • Set GPRS Server, port, APN.
  • Apply configuration.

Sub-detail: in some firmware the device chooses automatically between 8 and 8E based on the number of active IOs. If you only have IOs with 1-byte IDs, it sends 8; as soon as you enable one >255, it jumps to 8E. Check this in the log of the first frame received on your server — the Codec ID is in byte 9 of the packet.

Typical integration mistakes

1. The server decodes AVL ID as 1 byte and you receive gigantic IDs. Your frame is 8E but your decoder treats the first byte of the AVL ID as the whole ID. Result: AVL ID 0x01B5 is decoded as 0x01 + 0xB5 separately. Check that your decoder respects the Codec ID and applies the correct format.

2. CRC fails and you discard the frame. Teltonika's CRC-16 uses polynomial 0xA001 (CRC-16/IBM, "IBM Bisync"), not the standard CRC-16/CCITT. If your CRC library is not the right one, every CRC will fail even if the frame is fine.

3. The device "sends 8E" but IOs are missing. If you enabled an IO in the configuration but it doesn't show up, normally the IO requires another IO to be enabled first, or requires CAN/BLE connectivity that is not physically connected. Check the model's documentation for IO dependencies.

4. Latency is high and you blame the network, but it's the codec. Codec 8E produces larger frames than Codec 8. With a very slow data plan (2G in rural areas) you may notice a difference. On 4G it is irrelevant.

Summary

If you take away just two ideas:

  • Codec 8E is the modern default choice: 2 bytes for AVL ID, variable length for sensors, compatible with the entire current Teltonika ecosystem.
  • Your CRC is CRC-16/IBM, not CCITT. If your server drops frames with invalid CRC and nothing adds up, start there.

For an official guide with byte-by-byte detail and AVL IDs per device, the Teltonika wiki has the full reference (in English). If you build your own decoder, that wiki + this note should be enough for a clean integration.

If you already have Teltonika hardware and want a management platform that already implements every codec and processes the frames correctly, Fletaro is our SaaS sister company that does it natively. Or if you need hardware with codecs correctly configured from the factory, we ship the devices in our store pre-configured for standard integration.