Skip to content

Biome SEGB File Format: v1 and v2 Byte-Level Reference

Byte-level reference for Biome SEGB v1 and v2: headers, trailers, record states, CRC32, alignment, file-name times and protobuf field numbers per stream.

Published on 10 min read

TL;DR. A Biome stream is a folder of SEGB files. v1 has a 56-byte header with SEGB at bytes 52–55 and the end-of-data offset in bytes 0–3; each record has a 32-byte header (length, state, two timestamps, CRC32, unknown) and is padded to 8 bytes. v2 starts with SEGB, an entry count and a creation time, and indexes its records through a trailer of 16-byte entries (end offset, state, time) at the end of the file; each record is a CRC32, an unknown int32 and the payload, aligned to 4 bytes. States are 1 written, 3 deleted, 4 empty. Payloads are protocol buffers without a published schema. None of this is documented by Apple.

This reference follows ccl-segb by CCL Forensics (MIT licence), which credits Cellebrite's research on the v2 layout, and it is what KnowledgeC Parser implements. For where these files live and why they matter, start with the knowledgeC.db forensics guide and knowledgeC vs Biome.

Where SEGB files sit

~/Library/Biome/streams/restricted/<Stream>/local/<file>
~/Library/Biome/streams/public/<Stream>/local/<file>
~/Library/Biome/streams/restricted/<Stream>/remote/<device UUID>/<file>
~/Library/Biome/streams/restricted/<Stream>/local/tombstone/<file>
/private/var/db/biome/streams/...

The stream name (App.InFocus, App.WebUsage, ...) is not stored in the file: it comes from the folder. Keep the folder layout when you collect, or you lose the stream name, the local / remote distinction and the device UUID. Files in tombstone/ are expired (Biome tombstone).

All integers below are little-endian. Times are Mac absolute time stored as 64-bit doubles: seconds since 2001-01-01 00:00:00 UTC. Add 978307200 for Unix time.

SEGB v1

File header (56 bytes)

OffsetSizeTypeField
0x004uint32End-of-data offset (absolute, from the start of the file)
0x0448Not documented
0x344ASCIIMagic SEGB (bytes 52–55)

Records start at byte 56 (0x38) and run until the end-of-data offset. If that offset points past the end of the file, the copy is truncated.

Record header (32 bytes)

Offset in recordSizeTypeField
0x004int32Payload length
0x044int32State
0x088doubletimestamp1 (Mac absolute)
0x108doubletimestamp2 (Mac absolute)
0x184uint32CRC32 of the payload
0x1C4int32Unknown
0x20lengthbytesPayload

After the payload, the next record starts at the next multiple of 8 from the start of the file. The names timestamp1 and timestamp2 are descriptive: public sources do not give them a fixed meaning for every stream, so report both raw values rather than labelling one "start" and one "end".

SEGB v2

File header (32 bytes)

OffsetSizeTypeField
0x004ASCIIMagic SEGB
0x044int32Entry count (number of trailer entries)
0x088doubleCreation time (Mac absolute)
0x1016Not documented

Trailer (16 bytes per entry, at the end of the file)

The trailer occupies the last count × 16 bytes of the file.

Offset in entrySizeTypeField
0x004int32End offset of the record, relative to byte 32
0x044int32State
0x088doubleTime (Mac absolute)

Records

Records start at byte 32. Each one is:

Offset in recordSizeTypeField
0x004uint32CRC32 of the payload
0x044int32Unknown
0x08variablebytesPayload, up to the end offset

A v2 record has no length field. To read it, sort the trailer entries by end offset, start at byte 32, and read up to 32 + end offset. The next record starts at the next 4-byte boundary. Because state and time live in the trailer, a v2 record header carries only the CRC and the unknown word.

Shared end offsets

Two trailer entries can carry the same end offset. The usual pattern is a record written (state 1) and later deleted (state 3): both entries point at the same bytes, each with its own time. A parser should report both, not treat the second one as a new record. KnowledgeC Parser shows the deleted entry with the same payload and flags it as deleted. It also ignores trailer entries with state 0, which reference no data.

Record states and CRC

StateMeaningWhat to do
1WrittenNormal record
3DeletedThe payload can still be present: decode it and report it as deleted
4Empty / unusedNo usable record

The CRC is standard CRC-32 as computed by zlib (zlib.crc32), over the payload only. A mismatch points to a partially written or damaged record, or a copy taken while the file was being written. Keep such records but mark them; do not silently drop them.

An annotated v2 example

The file below was constructed for this article with the layout above: one App.InFocus record saying Terminal came into focus. It is synthetic, and the undocumented header bytes are zero here.

00000000  53 45 47 42 01 00 00 00 00 00 00 a6 c0 2b c8 41   SEGB.........+.A
00000010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
00000020  67 88 af ff 00 00 00 00 18 01 21 00 00 00 80 ff   g.........!.....
00000030  2b c8 41 32 12 63 6f 6d 2e 61 70 70 6c 65 2e 54   +.A2.com.apple.T
00000040  65 72 6d 69 6e 61 6c 00 27 00 00 00 01 00 00 00   erminal.'.......
00000050  66 66 66 80 ff 2b c8 41                           fff..+.A
BytesValueMeaning
0x00–0x03SEGBv2 magic
0x04–0x0701 00 00 001 trailer entry
0x08–0x0Fdouble 811041100.0Created 2026-09-14 01:11:40 UTC
0x10–0x1FzerosUndocumented
0x20–0x230xffaf8867CRC32 of the payload
0x24–0x270Unknown
0x28–0x4631 bytesProtobuf payload (below)
0x4700Padding to a 4-byte boundary
0x48–0x4B27 00 00 00End offset 39: 32 + 39 = 0x47, the end of the payload
0x4C–0x4F01 00 00 00State 1, written
0x50–0x57double 811073280.82026-09-14 10:08:00.8 UTC

The payload decodes as:

BytesTagFieldValue
18 01field 3, varintstatus1 = in focus
21 + 8 bytesfield 4, 64-bittime811073280.0 = 10:08:00 UTC
32 12 + 18 bytesfield 6, length-delimitedbundle IDcom.apple.Terminal

A stored file of this kind would be named after its creation time in microseconds, here 811041100000000.

File-name times

SEGB file names are integers. mac_apt reads them as Cocoa time in microseconds, which gives an approximate creation time for the file:

date -u -r $(( 811041100000000 / 1000000 + 978307200 ))
# Mon Sep 14 01:11:40 UTC 2026

Treat it as a file-level hint. Event times come from the records and, for some streams, from the payload.

Protobuf payloads

Wire types in brief

A protobuf message is a sequence of fields. Each starts with a varint key: field number << 3 | wire type (encoding guide).

Wire typeEncodingTypical content
0VarintIntegers, booleans, enums
18 bytesdouble, fixed64
2Varint length + bytesStrings, bytes, nested messages
54 bytesfloat, fixed32

Wire types 3 and 4 (groups) are deprecated and not expected here.

Why schema-less decoding is ambiguous

Apple publishes no .proto files for Biome. Without a schema:

  • a length-delimited field can be a string, raw bytes or a nested message, and short strings such as bundle IDs sometimes parse as valid messages;
  • an 8-byte field can be a double or an integer;
  • a varint can be a signed, unsigned, zigzag-encoded or boolean value.

KnowledgeC Parser tries printable UTF-8 text first, then a nested message that consumes every byte, then raw bytes. It shows 8-byte values as doubles, with a date when the value is a plausible Mac absolute time. Some payloads embed binary property lists, which are shown as such. Field numbers are always kept, so you can check any interpretation against another tool.

Field numbers by stream

These numbers come from community reverse engineering in mac_apt's BIOME plugin and in iLEAPP. They are not Apple documentation; validate them against test data from the same OS build before relying on them.

StreamFieldMeaningSource
App.InFocus3Status: 1 in focus, 0 out of focusmac_apt
App.InFocus4Time (double)iLEAPP
App.InFocus6Bundle IDmac_apt
App.InFocus9, 10Version stringsmac_apt
App.WebUsage2TimeiLEAPP
App.WebUsage4 / 5 / 6URL / domain / bundle IDmac_apt
Safari.*1Domainmac_apt
ScreenTime.AppUsage1 / 3Status / bundle IDmac_apt
Notification.Usage4 / 8 / 9App / title / subtitlemac_apt
Device.Wireless.WiFi1 / 2SSID / statusmac_apt
Device.Wireless.Bluetooth1 / 2 / 3 / 4Address / name / product ID / statusmac_apt
SystemSettings.SearchTerms1Search termmac_apt

App.InFocus records are events, not intervals: an "in focus" record is followed later by an "out of focus" record for the same app. KnowledgeC Parser pairs them into intervals (same user, same device, same bundle ID, within 24 hours) and leaves unpaired records as single events.

What is unknown

  • The 48 undocumented bytes of the v1 header, the 16 of the v2 header, and the "unknown" int32 in every record.
  • A fixed meaning for v1 timestamp1 and timestamp2 across all streams.
  • Fields not listed in the table above, and every field of streams without a public decoder. App.MenuItem, documented by Unit 42 on macOS Tahoe 26, has no public field map: KnowledgeC Parser decodes it schema-less and shows raw field numbers.
  • The macOS release where v2 replaced v1.

When a report depends on one of these, say so and show the raw value.

Tools that read SEGB

ToolWhat it does
ccl-segbReference reader for single v1 and v2 files, raw records
mac_apt BIOME pluginReads streams from an image or a folder and decodes the streams above
iLEAPPiOS Biome streams
KnowledgeC Parserv1 and v2 in the browser, with states, CRC checks, remote and tombstone origin, and a merged timeline with knowledgeC.db

FAQ

Is the SEGB format documented by Apple?

No. The layouts of SEGB v1 and v2 come from community reverse engineering, implemented in ccl-segb (CCL Forensics), which credits research by Cellebrite. Payload field meanings come from mac_apt and iLEAPP. Anything those sources do not cover should be treated as unknown.

How do I tell SEGB v1 from v2?

Look for the SEGB magic. In v1 it sits at bytes 52 to 55, at the end of a 56-byte header. In v2 it is the first four bytes of the file, at the start of a 32-byte header.

Does a deleted SEGB record still contain data?

Often, yes. State 3 marks a record as deleted, but the payload can remain in the file. In v2 a deleted entry can share its end offset with a written one, so both point at the same bytes. Report such records as deleted, not as live activity.

Which macOS version switched from SEGB v1 to v2?

That boundary is not publicly documented for macOS. On iOS, v1 is reported for iOS 14 to 16 and v2 from iOS 17. Parsers detect the version from the header, so you do not need to know it in advance.

Related articles

Step-by-step: load knowledgeC.db with its -wal and Biome SEGB streams into a free in-browser parser, set a time range, review sessions and export a timeline.
What knowledgeC.db records on macOS, where it lives, how ZOBJECT and its streams work, how to convert its timestamps, and what the data does not prove.
knowledgeC.db or Biome? How the two macOS activity stores differ, which Biome stream matches which knowledgeC stream, and what to expect on recent releases.