A Financial Information Exchange (FIX) message looks simple on the wire: tag=value pairs separated by a single control character, readable by eye within minutes. That invites a shortcut: split on the delimiter, split on the equals sign, look up the tags you care about. It works on clean samples and fails in production, because the tag=value format carries structural rules a string split cannot see, and because the TCP stream underneath refuses to deliver one message per read. This article sets out those rules, from framing and checksums to repeating groups and version selection, and you can test every example against the free online OnixS FIX Parser as you read.
FIX tags, fields and the tag=value format
Each field is tag=value terminated by the SOH control character (ASCII 0x01): the tag is a positive integer in ASCII digits with no leading zeros, and because SOH is non-printing, logs substitute a pipe or <SOH>. The OnixS FIX Protocol overview sets out this wire syntax, and the OnixS FIX Message reference explains it from an implementation perspective.
Structure is positional at the outer level. Four FIX tags hold fixed positions, and each does framing work:
|
Position |
Field |
Parser role |
|
First |
BeginString (8) |
Identifies the protocol version or, from FIX 5.0, the FIXT.1.1 session layer |
|
Second |
BodyLength (9) |
Declares the framed content length in bytes |
|
Third |
MsgType (35) |
Selects the message definition the rest of the parse depends on |
|
Last |
CheckSum (10) |
Carries the integrity check that closes the frame |
Between the standard header and standard trailer sit the body fields, specific to the message type: 35=D is a New Order Single, 35=8 an Execution Report; the OnixS FIX Message reference sets out the full session-level and application-level message-type breakdown. The OnixS FIX Dictionary documents every message type, field and enumerated value across versions. Session-level messages such as Logon and Heartbeat manage delivery; application messages carry the business content, and the session layer carrying them is the subject of Inside the FIX Session Layer.
BodyLength and CheckSum establish the message boundary
The two integrity fields deserve computation rather than a skipped read. BodyLength counts bytes from the character after the delimiter ending tag 9 through the delimiter ending the field before CheckSum; treating it as a character count breaks when an encoding uses more than one byte per character. CheckSum is a modulo-256 sum of every byte from BeginString through the delimiter before tag 10, written as three decimal characters: a compact check against truncation and corruption, not a form of authentication. OnixS FIX Message reference sets out the exact computation, with a worked example and sample code.
Framing is why these fields matter beyond validation. TCP delivers an ordered byte stream with no message boundaries: one read can return a fragment, a complete message, or the tail of one and the head of the next. A streaming parser retains incomplete input, uses the header plus BodyLength to identify a candidate frame, confirms the terminal CheckSum, and leaves following bytes for the next cycle. Code that assumes one read equals one FIX message fails under valid network behaviour.
Message anatomy: required fields and data type hazards
The specification defines, per message type, which fields are required, which are optional and which become required when another field is present. A parser that treats every field as optional accepts messages a counterparty's engine rejects; one that hard-codes a single version's requirements rejects valid messages from another.
Data types carry their own traps. Fields of the data type, such as RawData (tag 96), hold arbitrary bytes whose length is declared by a preceding count field (RawDataLength, tag 95), and the value can legitimately contain SOH. A length-aware parser consumes exactly the declared bytes before resuming delimiter processing, and rejects a data field with no preceding length or a frame that ends before the payload does. Timestamp fields use the UTCTimestamp format with fractional-second precision that varies by version and counterparty agreement, so storage and comparison logic cannot assume one width.
Repeating groups are where string splitting breaks down
Some fields legitimately appear more than once, inside a repeating group announced by a count field, the NoXXX field (for example NoPartyIDs, tag 453), which must immediately precede the entries. Within each entry the first field acts as the delimiter and must come before any other field of that entry, fields must follow the defined order, and the group has no closing marker: any field that does not belong to it ends the group.
Groups also nest, so a parser maintains a stack of contexts: a TradeCaptureReport carries a Parties group inside each entry of its Sides group, and only the message definition says which tags belong to which group at which depth. This is where silent corruption lives: an entry that omits its delimiter field still splits into plausible tag=value pairs, and application code attaches a field to the wrong entry. A regex sees a flat list of duplicated tags and cannot reconstruct which Party belongs to which Side. The OnixS FIX Repeating Group reference walks through a worked nested example byte by byte.
Why the FIX version changes the parse
The same tag can mean different things, carry a different requirement or be absent depending on the version and dictionary in force.
|
Version stage |
What it introduces |
Parse consequence |
|
FIX 4.0 to 4.4 |
Successive application versions revising messages, fields and code sets |
The governing dictionary decides validity; 4.2 traffic validated against 4.4 rules fails in both directions |
|
FIX 5.0 and FIXT.1.1 |
The session layer splits into FIXT.1.1 |
BeginString names the session protocol; the application version travels via DefaultApplVerID (1137), overridable per message by ApplVerID (1128) |
|
FIX 5.0 SP2 and FIX Latest |
Service packs, then continuous evolution through extension packs |
In March 2026 FIX Trading Communitylisted FIX 4.2, FIX 4.4 and FIX Latest as supported and moved FIX 5.0 SP2 to unsupported: no further standards-body error correction, no prohibition on use |
|
Venue dialects |
User-defined tags, custom messages, altered requirements |
The parser must validate against the counterparty's dialect; base standard rules are wrong for that session in both directions |
The dialect row is the everyday one, and it makes dictionary ownership a discipline: version the dictionary with the code and certification baseline, and treat the counterparty's Rules of Engagement as the production authority. A large part of that overhead is not the initial mapping but the ongoing tracking and maintenance of venue-specific Rules of Engagement updates: a venue revises its FIX Rules of Engagement over time, adding user-defined tags, custom messages or custom enumerations that extend or specialise the base FIX Protocol, and each revision has to be caught, re-certified and rolled out before it affects a live session. That is not the only source of change to track: the base FIX Standard itself keeps moving between full versions through FIX Trading Community's own Extension Packs (EP), incremental releases to FIX 5.0 SP2 and FIX Latest that add or revise fields, messages and enumerations between full version updates; a dictionary has to absorb both a venue's Rules of Engagement changes and the standard's own Extension Pack releases to stay current. The OnixS FIX Engine implementations expose XML-based and API-based dictionaries for this, and where a venue's Rules of Engagement is complex enough to warrant it, OnixS packages the calibrated dictionary as a venue-specific FIX Support Pack, tracked and maintained by OnixS as the venue's Rules of Engagement evolve, rather than leaving that upkeep to the integrating team. The free online FIX Parser makes that dependence visible for the base standard: paste or upload a message, pick a version from FIX 4.0 through FIX Latest or use autodetect, and read the Tag, Name, Value and Description breakdown resolved against that standard dictionary. It does not resolve a venue's own user-defined tags, custom messages or enumerations, which is exactly the gap a venue-specific FIX Support Pack closes.
The FIXML format, briefly
FIXML is the XML representation of the same standard: semantically equivalent to tag=value FIX, sharing the same data dictionary and business rules, with no session layer of its own. Its main production home is post-trade; CME Straight Through Processing (CME STP API) distributes cleared-trade information as FIXML 5.0 SP2 messages. FIXML also turns up inside firms that never send it externally: because it is XML, it drops straight into standard XML tooling, schema validation, XSLT transforms, XML databases and off-the-shelf parsers, so some firms convert internal FIX traffic to FIXML for archiving, reconciliation or reporting pipelines built on that tooling rather than a bespoke tag=value parser. Where a system moves between the two representations, the OnixS FIX to/from FIXML Converter is a utility library in the OnixS FIX Engine .NET and Java distributions, and the OnixS FIXML Tutorial shows both forms side by side.
What a production FIX message parser must get right
An acceptance test for a FIX decoder, built or bought, should prove each of these before production flow:
- Reassemble one message fed across many fragments, with splits inside a tag, a value, a data field and the checksum; then handle several messages in one buffer plus a partial, carrying the remainder over.
- Report corrupted BodyLength and CheckSum as framing damage, in separate tests, before anything reaches application code.
- Disregard a garbled message, as the protocol expects, without misparsing the stream; recovery is the session layer's job through gap detection and resend.
- Exercise empty, populated and nested repeating groups, then break them: wrong counts, missing delimiter fields, members out of order.
- Accept raw data containing SOH bytes and equals signs, unknown fields, unknown message types and empty values.
- Run every supported standard version and every deployed dialect dictionary through the same test suite.
- Measure throughput at your peak message rates with production validation and logging settings, run on the target production deployment architecture and platform so the numbers hold up in practice, recording the measurement boundary: whether it includes dictionary validation, repeating groups and error reporting.
Each item is tractable alone; together they need to be a sustained, ongoing, automated commitment, because dictionaries change, venues issue new dialects and the standard keeps moving.
The OnixS FIX Engine SDK: from free parser to production
For inspection, troubleshooting and validation, the free online OnixS FIX Parser needs no signup: it checks a message's tag=value structure, BodyLength and CheckSum framing, and field values against the selected dictionary, surfacing malformed fields, out-of-spec values or version mismatches before a message reaches a counterparty.
When requirements go beyond ad hoc decoding, the OnixS FIX Engine SDKs provide production parsing as part of a full FIX Protocol implementation, in four editions: the OnixS FIX Engine SDK - .NET implementation, the OnixS FIX Engine SDK - .NET Framework implementation, the OnixS FIX Engine SDK - C++ implementation and the OnixS FIX Engine SDK - Java implementation. Each ships with dictionary support for standard versions and venue dialects, per-session validation, and parser and repeating-group reference samples; where a venue's Rules of Engagement is complex enough to warrant it, that dictionary support comes packaged as a calibrated, venue-specific FIX Support Pack.
A parser that passes on clean standard samples has proved little. Run the acceptance list with your counterparties' actual Rules of Engagement dictionaries, your captured traffic and your peak message rate before committing a build-or-buy decision.
One distinction worth noting is that the OnixS FIX Parser implementations can be used independently of the network and FIX session-level support. Parsing is one concern; keeping a session connected, sequenced and recoverable is another, which Inside the FIX Session Layer covers in full.
The OnixS FIX Engine SDK distributions also include FIX/FAST decoder and encoder implementations, so a team asking for a FIX decoder should establish the wire encoding first and select the component to match. Simple Binary Encoding (SBE) has since overtaken FAST as the binary wire format in a number of these market contexts; it does not ship inside the FIX Engine SDK distributions above, but OnixS's SBE Decoder and Encoder codecs are available as a separate free evaluation, with background in The Evolution and Implementation of FIX SBE and their own release notes.
Every mechanism this article covers, from framing and checksums to repeating groups and versioning, is already built, certified and supported in the OnixS FIX Engine SDK implementations: request a free 30-day evaluation for your platform, .NET, .NET Framework, C++, or Java.
