Bite Apps/SafeFIX

SafeFIX — FIX log analyzer, dictionary validator & anonymizer

Paste a messy engine log or drop a .log file. SafeFIX strips timestamps and prefixes, detects the delimiter, decodes every tag against FIX 4.2/4.4 or your broker's own QuickFIX-format XML dictionary, explains rejects, traces each order's lifecycle with hop-by-hop latency, and produces a sanitized log for support tickets — with BodyLength (9) and CheckSum (10) recalculated so it still replays.

100% client-side 0 network requests since this page loaded No sign-up · no analytics · no cookies Works offline once loaded
Drop a FIX log (.log / .txt) to analyze it
or a data dictionary (.xml) to load it — nothing is uploaded
📄
0 lines Free: first 100 lines · Pro: unlimited, files up to 100 MB+

Nothing leaves this tab

Paste log lines above, open a file, or try the sample session (logon, new order, partial fill, replace, a 35=3 reject, a credit-limit reject, a cancel and a business reject).
Open DevTools → Network before you start: the request count stays at zero while SafeFIX parses.

Pricing

One payment, no subscription. Payments and tax are handled by Polar as Merchant of Record. Compare all Bite Apps plans →

Free

$0
  • Paste up to 100 log lines per analysis
  • Decode and validate single messages against built-in or custom dictionaries
  • Reject explainer for 35=3, 35=j, 35=9 and rejected execution reports
  • Order lifecycle and latency view
  • Basic anonymization with copy-to-clipboard
Start analyzing

SafeFIX Pro Lifetime

$19 one-time
  • Large .log / .txt files (100 MB+) streamed and processed locally
  • Batch download of sanitized logs and the token map
  • Save custom XML dictionaries in this browser (IndexedDB)
  • CSV and Excel (.xlsx) latency reports
  • All future SafeFIX updates

A FIX log analyzer built for NDA-bound teams

Support engineers, FIX onboarding teams, quants and prop-firm developers handle production FIX logs that contain account numbers, CompIDs, credentials and live order flow. Most compliance policies forbid pasting those logs into cloud parsers or AI chat tools. SafeFIX is a single static page: the parser, the dictionary validator, the anonymizer and the latency inspector all run in JavaScript inside your browser tab. Nothing is uploaded, nothing is stored on a server, and the page keeps working with the network cable unplugged once it has loaded.

How to verify it yourself: open Chrome DevTools → Network, tick Preserve log, then paste or drop a 10 MB log and analyze it. The request list stays empty. The page also ships a strict Content-Security-Policy (default-src 'none') whose only allowed outbound destination is api.polar.sh, used once when you activate a Pro license key.

What SafeFIX does

1. Dirty log multi-parser

Real logs are never clean. SafeFIX strips engine timestamps and prefixes (QuickFIX, QuickFIX/J and QuickFIX/n file logs, FIX.4.4:SENDER->TARGET session tags, syslog lines, IN/OUT markers), detects the delimiter per line — raw SOH \x01, |, ^A, <SOH>, TAB or ; — and handles several messages on one line, header-less fragments and values that contain the delimiter. Lines without FIX content are skipped from analysis and passed through unchanged by the anonymizer.

2. Custom data dictionary support

Pick a built-in dictionary (FIX 4.2, FIX 4.4, Binance Spot FIX, cTrader FIX or a oneZero / PrimeXM bridge profile) and drop your counterparty's QuickFIX-format XML (FIX44.xml, FIX50SP2.xml + FIXT11.xml, or a broker-customised file) on top. Custom fields in the user-defined range 5000–9999 are decoded with their names and enum values, required fields are checked per message type, and every tag that would trigger a session-level reject on a strict acceptor is highlighted with the matching SessionRejectReason (373) code.

3. Log anonymizer for support tickets

One click replaces Account (1), Username (553), Password (554), NewPassword (925), SenderCompID / TargetCompID (49 / 56), OnBehalfOf and DeliverTo IDs, ClOrdID (11), OrigClOrdID (41), OrderID (37), PartyID (448) and any custom tags you list. Tokens are consistent across the whole file — a ClOrdID becomes the same token wherever it appears, so order chains stay traceable. SafeFIX then recalculates BodyLength (9) and CheckSum (10) for every rewritten message, updates data-length pairs such as RawDataLength (95) / RawData (96), and re-checks each output message, so the sanitized log still replays through an engine.

4. Order lifecycle & latency inspector

Messages are grouped into order chains by ClOrdID (11), OrigClOrdID (41) and OrderID (37): 35=D → 35=8 New → 35=G → 35=8 Replaced → 35=8 Fill, or 35=F → 35=8 Canceled. Each hop shows its delta in milliseconds from SendingTime (52), TransactTime (60) or the engine's own log timestamp, with count / min / median / mean / p95 / p99 / max for New→Ack, New→First fill, Replace→Ack, Cancel→Ack and New→Reject. Any two messages can be compared side by side, with changed, added and removed tags highlighted.

How FIX BodyLength (9) and CheckSum (10) are calculated

BodyLength (9) is the number of bytes after the 9=…<SOH> field up to and including the SOH that precedes 10=. CheckSum (10) is the sum of every byte from the start of 8= up to and including that same SOH, modulo 256, written as exactly three digits. Both are computed on the wire format, where the delimiter is the single byte 0x01 — if your log shows | or ^A, count each delimiter as one byte.

8=FIX.4.4|9=55|35=0|49=CLIENT|56=BROKER|34=2|52=20261102-13:45:31.120|10=077|

Body (after 9=55|, up to and including the | before 10=):
35=0|49=CLIENT|56=BROKER|34=2|52=20261102-13:45:31.120|   → 55 bytes  → 9=55
Sum of all bytes from "8=" through that last SOH = 3661
3661 mod 256 = 77                                          → 10=077

Editing any value — for example masking a CompID — changes both numbers. Engines reject a message with a wrong BodyLength or CheckSum before the application ever sees it (QuickFIX typically logs it as a garbled message and drops it), which is why naive find-and-replace sanitizing breaks log replay.

Troubleshooting 35=3 session-level rejects

A Reject (35=3) means the counterparty's FIX engine refused your message before it reached their business logic. Read RefSeqNum (45) to find the rejected message, RefTagID (371) for the offending tag, RefMsgType (372) for its type, and SessionRejectReason (373) for the cause. SafeFIX links the reject to the original message automatically.

373ReasonTypical cause and fix
0Invalid tag numberThe tag is not in their dictionary at all — often a custom tag in the 5000–9999 range. Remove it or ask them to add it. QuickFIX acceptors relax this with ValidateUserDefinedFields=N or AllowUnknownMsgFields=Y.
1Required tag missingTheir dictionary marks the field required="Y" for this MsgType (including required components and groups). Compare against their rules of engagement.
2Tag not defined for this message typeThe tag exists but not in this message. Move it, or have them extend the message definition.
3Undefined tagSimilar to 0 on many engines — the number is unknown.
4Tag specified without a valueAn empty field such as 58=|. Never send empty tags; ValidateFieldsHaveValues=N relaxes the check.
5Value is incorrect (out of range) for this tagAn enum value they do not support, e.g. an OrdType (40) or TimeInForce (59) the venue does not offer.
6Incorrect data format for valueA decimal in an INT field, a timestamp not in YYYYMMDD-HH:MM:SS[.sss], a lowercase boolean.
9CompID problemSenderCompID / TargetCompID or SubIDs do not match the session configured on their side.
10SendingTime accuracy problemYour clock drifts beyond their tolerance. Sync with NTP/PTP; QuickFIX controls the check with CheckLatency and MaxLatency.
11Invalid MsgTypeThe message type is not supported on that session.
13Tag appears more than onceUsually a repeating group sent without its NumInGroup field, or a header tag duplicated by middleware.
14Tag specified out of required orderHeader fields must come first and 8, 9, 35 must be the first three. ValidateFieldsOutOfOrder=N relaxes ordering checks.
15Repeating group fields out of orderThe first field after NumInGroup must be the group's delimiter field, and members must follow the dictionary order.
16Incorrect NumInGroup countThe number of entries does not match the NumInGroup value.
99OtherRead Text (58) and the counterparty's rules of engagement.

Business Message Reject (35=j)

A 35=j passes session validation but is refused by the application. BusinessRejectReason (380): 0 Other, 1 Unknown ID, 2 Unknown security, 3 Unsupported message type, 4 Application not available, 5 Conditionally required field missing, 6 Not authorized, 7 DeliverTo firm not available, 18 Invalid price increment. Order-level refusals arrive instead as an Execution Report with OrdStatus (39)=8 and OrdRejReason (103), or as an Order Cancel Reject (35=9) with CxlRejReason (102).

QuickFIX DataDictionary settings that change validation

UseDataDictionary, DataDictionary (FIX 4.x), TransportDataDictionary + AppDataDictionary (FIXT 1.1 / FIX 5.0), ValidateUserDefinedFields, AllowUnknownMsgFields, ValidateFieldsOutOfOrder, ValidateFieldsHaveValues, CheckLatency / MaxLatency and CheckCompID. When a counterparty rejects with 373=0 or 373=2 for a tag you know is valid, the usual root cause is that their acceptor loads an older or un-customised XML.

FIX tag reference — the tags you read every day

TagNameMeaning
8BeginStringProtocol version: FIX.4.2, FIX.4.4, FIXT.1.1. Always first.
9BodyLengthByte count of the body; always second.
10CheckSumByte sum modulo 256, three digits; always last.
35MsgTypeMessage type (see the table below); always third.
34MsgSeqNumPer-direction sequence number used for gap detection and resends.
49 / 56SenderCompID / TargetCompIDSession identity of each side.
52SendingTimeUTC time the message was sent; basis for latency deltas.
43 / 97 / 122PossDupFlag / PossResend / OrigSendingTimeSet on retransmitted messages after a ResendRequest.
1AccountTrading account — sensitive, masked by the anonymizer.
11ClOrdIDClient-assigned order ID, unique per order request.
41OrigClOrdIDClOrdID of the order being replaced or canceled.
37OrderIDVenue-assigned order ID.
17ExecIDUnique ID of each execution report.
150ExecTypeWhat this report is: 0 New, 4 Canceled, 5 Replaced, 8 Rejected, F Trade (4.4), I Order status.
39OrdStatusOrder state after this report: 0 New, 1 Partially filled, 2 Filled, 4 Canceled, 8 Rejected.
54Side1 Buy, 2 Sell, 5 Sell short.
55SymbolInstrument symbol (venue-specific symbology).
38OrderQtyOrder quantity.
40OrdType1 Market, 2 Limit, 3 Stop, 4 Stop limit.
44 / 99Price / StopPxLimit price / stop trigger price.
59TimeInForce0 Day, 1 GTC, 3 IOC, 4 FOK, 6 GTD.
32 / 31LastQty / LastPxQuantity and price of this fill (LastShares in FIX 4.2).
14 / 151 / 6CumQty / LeavesQty / AvgPxFilled so far, remaining open, average fill price.
60TransactTimeBusiness time of the event at the originator.
58TextFree text — often contains the real reject reason.
45 / 371 / 372 / 373RefSeqNum / RefTagID / RefMsgType / SessionRejectReasonFields of a 35=3 Reject.
380 / 379BusinessRejectReason / BusinessRejectRefIDFields of a 35=j Business Message Reject.
103 / 102 / 434OrdRejReason / CxlRejReason / CxlRejResponseToOrder and cancel reject reasons.
98 / 108 / 141EncryptMethod / HeartBtInt / ResetSeqNumFlagLogon parameters.
553 / 554 / 95 / 96Username / Password / RawDataLength / RawDataLogon credentials and signatures — masked by the anonymizer.
112TestReqIDEchoed in the Heartbeat that answers a TestRequest.
1128ApplVerIDApplication version on FIXT.1.1 sessions (FIX 5.0 SP2 = 9).
5000–9999User-definedCustom tags agreed bilaterally — load the counterparty's XML to decode them.

MsgType (35) values

35Message35Message
0HeartbeatDNewOrderSingle
1TestRequestFOrderCancelRequest
2ResendRequestGOrderCancelReplaceRequest
3Reject (session level)8ExecutionReport
4SequenceReset9OrderCancelReject
5LogoutHOrderStatusRequest
ALogonjBusinessMessageReject
VMarketDataRequestW / XMarketData snapshot / incremental refresh
YMarketDataRequestRejectAETradeCaptureReport
AFOrderMassStatusRequestAN / APRequestForPositions / PositionReport

FAQ

Does SafeFIX upload my FIX logs?

No. Parsing, validation, anonymization and latency analysis run entirely in your browser tab. The page's Content-Security-Policy blocks every network destination except api.polar.sh, which is contacted only when you activate a Pro license key — and only the key is sent. You can confirm in DevTools → Network that analyzing a log makes zero requests.

Which log formats can it read?

Raw SOH-delimited messages, pipe (|), ^A, <SOH>, TAB or semicolon delimited logs, with or without engine prefixes such as QuickFIX "YYYYMMDD-HH:MM:SS.sss : " timestamps, session identifiers or IN/OUT markers. Several messages per line and header-less fragments are handled.

Can I validate against my broker's custom FIX dictionary?

Yes. Load any QuickFIX-format XML DataDictionary (FIX44.xml, FIX50SP2.xml with FIXT11.xml, or a broker-customised file). It is layered over the selected built-in dictionary, so custom tags in the 5000–9999 range are decoded and required fields are checked per message type. Pro users can save dictionaries in the browser.

Will an anonymized log still replay through a FIX engine?

Yes. After masking, SafeFIX recalculates BodyLength (9) and CheckSum (10) for every message, updates data-length fields such as RawDataLength (95), keeps tokens consistent across the file and re-verifies each output message. Choose SOH output to feed the file straight into a replay tool.

How is order latency measured?

SafeFIX links messages by ClOrdID (11), OrigClOrdID (41) and OrderID (37) and computes deltas from SendingTime (52), TransactTime (60) or the engine's log-line timestamp. SendingTime is stamped by each sender, so cross-host deltas include clock skew; the log timestamp gives single-host round-trip times.

What does a 35=3 reject with 373=0 mean?

SessionRejectReason 0 is "Invalid tag number": the counterparty's engine does not know the tag in RefTagID (371). It is usually a custom tag missing from their data dictionary. Remove the tag or ask them to add it; QuickFIX acceptors can also relax the check with ValidateUserDefinedFields=N.

What does SafeFIX Pro include, and is it a subscription?

Pro is a one-time $19 payment, not a subscription. It unlocks large file processing (100 MB+ streamed locally), downloads of sanitized logs and token maps, saving custom XML dictionaries in the browser, and CSV/Excel latency report exports. Payment is processed by Polar as Merchant of Record.

Can you build a custom FIX bridge or fix our dictionary problems?

Yes. Bite Apps is run by a trading platform support engineer with six years of daily FIX work. Email support@biteapps.cc for custom FIX API bridges, QuickFIX dictionary troubleshooting, log forensics and trading infrastructure support.

SafeFIX Pro — $19 one-time

  • Stream and analyze 100 MB+ log files locally
  • Download sanitized logs and token maps
  • Save custom XML dictionaries in this browser
  • CSV / Excel latency reports

Buy SafeFIX Pro ($19) Secure checkout by Polar. After payment your license key is shown in your Polar customer portal (linked from the receipt email).


Activation sends only your license key to api.polar.sh. Log contents are never sent anywhere — the page's Content-Security-Policy blocks every other destination.

Side-by-side message diff