Reading an HL7 message for the first time

An HL7 v2 message looks like a wall of pipes and carets. It is actually a very simple shape, and you can learn it in ten minutes.

Published 2026-08-27 · by M.R. Sterling

The first time you open an HL7 v2 message it looks like line noise. Pipes, carets, and a lot of empty space where you expected data.

It is simpler than it looks. There are only four ideas, and once you have them the whole thing reads like a form.

One: a message is a stack of segments

Each line is a segment. Each segment starts with three capital letters that say what it is.

  • MSH is the message header. Every message has one, and it is always first.
  • PID is patient identification.
  • OBR is an observation request, and OBX is an observation result.

There are many more, but a message you actually have to read usually has a handful.

Two: fields are separated by pipes

Inside a segment, the vertical bar separates fields. Counting them is the whole skill.

The catch is that MSH counts differently from every other segment, and this is worth learning once rather than being confused by repeatedly. In MSH, the field separator character itself is treated as the first field. So in MSH the piece of data after the encoding characters is field 2, while in PID the piece of data after the segment name is field 1.

Most parsing bugs written by beginners are an off by one in exactly this spot.

Three: fields have parts inside them

A field can hold more than one value, and the caret separates those parts.

A patient name arrives as a single field with components inside it: family name, then given name, then a middle name or initial. So one field holds the whole name, and the caret splits it into pieces. The same idea covers addresses, coded values, and identifiers.

Two more separators appear once you go deeper. The tilde repeats a whole field, which is how a patient ends up with two addresses. The ampersand splits a component into subcomponents.

Four: empty means empty, and there is a special case

Two pipes with nothing between them mean the field was not sent. That is common and it is not an error.

There is one distinction that matters when you are updating a record rather than creating one. A field that is simply absent means "no information provided". A field containing a pair of double quotes means "delete what you have". Those are different instructions, and treating them as the same thing is how good data gets wiped.

Where to start

Open a real message and do this in order:

  • Find MSH and read the message type. That tells you what the message is for.
  • Find PID and pull the patient name and identifier.
  • Count the pipes carefully, and remember that MSH counts differently.
  • Split the name field on the caret.

That is a first parser. Everything after it is more of the same shape.

More articles

One email when a new book lands

No schedule, no filler. Just the new titles and the odd free chapter.