Apple Biome / SEGB

What Is Apple Biome, and What Is SEGB?

Biome is the framework iOS uses to record contextual and behavioural events on the device. SEGB is the binary container those events are written into. Biome is what the data is. SEGB is the file format you have to read to get at it.

Together they hold app launches, notifications, device unlocks, web visits, location context and a great deal more, often for longer than the databases examiners usually reach for.

Locations

Where do the Biome streams live?

In two repositories, and both matter. Each stream is a folder rather than a file, named after what it records.

Both repositories
/private/var/mobile/Library/Biome/streams/   user level
   ├── ApplicationLaunch/
   ├── ApplicationInstall/
   ├── DeviceUnlock/
   ├── Notification/
   ├── WebPageVisit/
   └── …   300+ more
/private/var/db/biome/streams/   system level
   └── …   ~40 more

The number is the part people underestimate. Research published in July 2026 examined full file system acquisitions from iOS 18 and iOS 26 devices and counted the folders.

300+
Stream folders in the user-level repository on a modern device
84
Identified as containing information of potential forensic interest
2
Format dialects a tool has to read, and a device can hold both

Of those, 84 streams were identified as containing information of potential forensic interest.

Zena Forensics, 84 Streams Later

That is the shape of the problem. Not one artifact to parse, but several hundred folders of which a subset matter, and which subset depends on the case.

Byte level

What is inside a SEGB file?

SEGB stands for segmented buffer. It is a record container, used by Biome streams and by other iOS stores such as locationd and routined, and it identifies itself with four ASCII bytes.

The magic
53 45 47 42      S  E  G  B

These files carry no consistent extension, so they are found by content rather than by name. That is one reason they are missed when an examiner searches by file type.

Two layouts, and the difference matters

The two dialects put the same information in different places. Seeing them side by side is the fastest way to understand why a v1 parser reads a v2 file as a pile of anonymous payloads.

SEGB v1 · everything inline
56B header
32B hdr + payload
32B hdr + payload
32B hdr + payload
Each record carries its own length, state, two Cocoa timestamps and a CRC32 before the payload. The magic sits at offset 52, near the end of the file header.
SEGB v2 · state and time moved to the end
32B header
8B + payload
8B + payload
8B + payload
TRAILER 16B × n
Records carry only a CRC32 and one unknown value. The state, the timestamp and the end offset live in the trailer, one entry per record. Read the file front to back without it and you have payloads with no context at all.

Offset Type Field, in a v1 record header
0 i32 Record length
4 i32 State
8 f64 Timestamp, Cocoa time
16 f64 Second timestamp, Cocoa time
24 u32 CRC32
28 i32 Unknown
32 bytes Payload, usually a Protocol Buffer

Worth checking twice

Both versions store time as Cocoa time, which is Mac Absolute Time counting from 1 January 2001, exactly 31 years from the Unix epoch to the day. Read one as the other and the date looks entirely reasonable and is wrong by 31 years. The mechanics are on SQLite Forensic Analysis.

The payload being a Protocol Buffer is the second obstacle. Without a schema the fields come back as numbered values with no names, so a record can be parsed structurally and still tell you nothing until the fields are identified. Protobuf and varint forensics covers that step.

Recovery

How does SEGB mark a deleted record?

This is the part that makes SEGB unusually generous, and it is why the format is worth learning properly.

Every record carries a state as an integer. When a record is deleted, the state changes and the record stays where it is. The content is not removed. It is flagged.

Which means a parser that reads the state field can show you deleted events alongside live ones, and can tell you which is which, without carving or guessing.

Compare that with SQLite, where a deleted record loses the first four bytes of its cell and with them its rowid. Or with LevelDB, where a deletion writes a separate tombstone entry. In SEGB the record survives intact and announces its own status.

Each written record also carries a CRC32. Comparing the stored checksum against the computed one tells you whether the record is intact, which is a different question from whether it is live. The checksum is only meaningful for written records, so a tool that reports CRC status on a deleted entry is telling you something it cannot know.

State Value Meaning
Written 1 A live record, present in the stream and current.
Deleted 3 Marked as removed, and still readable in full.
Empty 4 A trailer slot never written. Carries no data region.
Unknown 0 State could not be determined, which is worth reporting.

What this means in a report

You can state that an event existed and was later removed, rather than that you recovered a fragment and believe it was a deletion. The format tells you, and the checksum lets you say whether the record is intact.

The version break

Why did iOS 17 break existing parsers?

Because Apple revised the format. SEGB version 2 arrived with iOS 17, and while it resembles the original, the binary structure changed enough that a v1 parser does not read it.

SEGB v1 SEGB v2
Introduced iOS 14 era iOS 17
File header 56 bytes, magic at offset 52 32 bytes, magic first
Record prefix 32 bytes, inline 8 bytes, CRC32 and one unknown
State and time In the record header In a 16 byte trailer entry per record
Record order Sequential By end offset from the trailer
Payload Commonly Protocol Buffers Commonly Protocol Buffers

For an examiner the practical consequence is a question worth asking before anything else: which iOS version produced this extraction, and does the tool in front of you read both dialects? A device that has been through an upgrade can hold files in both formats.

The wider point

This is what parser drift looks like from the inside. The format changed, the tools followed at their own pace, and for a period the honest answer to “is this stream supported” depended entirely on which build you were running.

Application activity

Launches, installs and app intents, often with the bundle identifier.

Device interaction

Unlocks and other handling events that place a person with the device.

Notifications

What arrived on screen, including from apps whose own databases are gone.

Web and search

Page visits and Siri requests, separate from browser history.

Location context

Visits and coordinates recorded as behavioural context rather than as GPS logs.

Communication events

That contact occurred, which survives even where the message store does not.

The evidence

What can you get out of Biome?

Biome exists so iOS can anticipate what a person is about to do. As a side effect it keeps a broad record of what they did.

The most useful property is persistence. Where the databases examiners reach for first have been cleared, capped or rotated, Biome frequently still holds the same events. An app can be uninstalled and its own storage gone while the launch and notification records remain.

That makes Biome a corroboration source as much as a discovery source. An event in a message store and the same event in a Biome stream are two independent records, and two agreeing records is a different thing from one.

The practical problem

Why is Biome hard at scale?

Not because any single file is difficult. Because there are several hundred of them, and the interesting ones differ from case to case. Three things compound.

  1. The count

    There are 300 or more stream folders on a modern device, and no index telling you which of them touched your time window.

  2. The payloads have no field names

    The records are Protocol Buffers, so without a schema every field comes back as a number rather than a label.

  3. Relevance is case dependent

    The streams that matter in a stalking case are not the streams that matter in a fraud case, so a fixed list of “the important ones” fails on the next case.

Opening them one at a time works when you already know which stream holds the answer. It does not work when the question is “did this device do anything relevant on the fourteenth”, which is the question that is usually asked.

What that situation needs is a query rather than a viewer. Ask for every record across every decoded stream within a time window, or every record containing a coordinate, or every record referencing a bundle identifier, and let the answer come from all of them at once.

Retention is a real variable

Streams do not all keep data for the same length of time. Some roll over in weeks, others hold months. Before concluding that a period is not covered, it is worth establishing what the relevant stream actually retains.

The workspace

Where does Elusive Data Firefly fit?

Firefly decodes both SEGB dialects and puts a query language over the result. SEGBQL is SQL shaped, so a question is written once and answered across every decoded record rather than by opening stream files one at a time.

SEGBQL
SELECT seq, timestamp, @coordinate
WHERE  state = ‘Deleted’ AND @coordinate *
ORDER BY timestamp DESC
LIMIT 50

Three kinds of field are queryable. Record columns such as state, timestamp, size and crc. Paths into the decoded protobuf tree, for when you know the structure. And @finding fields, which are the useful ones.

@coordinate, @phone, @email, @url and @address are resolved without a schema. That means a query for coordinates works on a stream you have never seen before, which matters when a device holds several hundred of them and no documentation exists for most.

Explore Firefly
Deliberately conservative

Findings are labelled as inferred rather than asserted, so an exhibit cannot overstate certainty. A ten digit telemetry value is not promoted to a phone number, and an adjacent pair of doubles is not promoted to a coordinate on shape alone.

Both dialects

v1 inline headers and v2 trailer entries, including the end-offset ordering.

State preserved

Deleted records shown as deleted rather than merged into the live set.

What was not read

Unprocessed trailer entries and leftover bytes are stated, not passed over.

Fault isolated

One malformed payload does not stop the rest of the file being decoded.

Training

Where do you learn the method?

Biome rewards the same habits as any other format: identify the container, read the record header, know what the state field means, and check the timestamp interpretation before relying on it.

Complete · 24 CPE · Certificate

Certified SQLite Forensics

The foundation the rest of it stands on. Record headers, serial types, varints, recovery and validation, taught on real training files you work on in your own tools.

  • Read a record header and know what each field is doing
  • Recover deleted content and name the mechanism that preserved it
  • Decode Protocol Buffers and other nested payloads
  • Verify a timestamp interpretation instead of accepting a conversion
  • Validate incomplete or unsupported tool output against the source
  • Explain how a finding was reached, in terms a reviewer can follow

The course runs in several formats. On demand is the fastest way to start, and it also runs live online and on-site. See the formats.

Start on demand
See all formats
Focused · On demand

WAL Frames and SHM Index

A shorter course on transaction files, and a good first step if you want to see how the training works before committing to the full programme.

  • Read a WAL frame header and find transaction boundaries
  • Recover page images written before the last checkpoint
  • Handle a file set without checkpointing away the evidence

Delivered through the Elusive Data Academy, where the on-demand courses and the practical labs live.

Open the Academy