python-hl7 – HL7 v2.x Message Parser
raw JSON → 0.4.5 verified Tue May 12 auth: no python install: verified quickstart: verified
A simple Python library for parsing HL7 v2.x messages. Provides segment, field, and component-level access to HL7 messages, along with MLLP (Minimal Lower Layer Protocol) client support. Does not handle HL7 FHIR (v4); it is strictly for the pipe-delimited v2.x wire format.
pip install hl7 Common errors
error IndexError: list index out of range ↓
cause The HL7 message was not correctly parsed, often due to incorrect segment termination characters (e.g., `\n` instead of `\r`), causing the library to only recognize the first segment or an empty message.
fix
Ensure the HL7 message uses carriage returns (
\r) as segment delimiters. If the input string uses newlines (\n), replace them with \r before parsing.
hl7_raw_string = "MSH|^~\\&|...\nPID|...\nOBX|..."
hl7_message = hl7_raw_string.replace('\n', '\r')
parsed_message = hl7.parse(hl7_message)
# Now you can access segments correctly, e.g., parsed_message['PID'] error NameError: name 'MLLPClient' is not defined ↓
cause The `MLLPClient` class is part of the `hl7.client` submodule and is not directly available in the top-level `hl7` module without explicit import.
fix
Import
MLLPClient specifically from hl7.client or reference it as hl7.client.MLLPClient.
from hl7.client import MLLPClient
host = '127.0.0.1'
port = 4106
with MLLPClient(host, port) as client:
client.send_message('test1')
# Alternatively, without explicit import:
# with hl7.client.MLLPClient(host, port) as client:
# client.send_message('test1') error AttributeError: 'Message' object has no attribute 'MSH' (or any other segment name) ↓
cause The `hl7.Message` object (from the `python-hl7` library) uses list-like or dictionary-like access for its segments and fields, not direct attribute access like `message.MSH`.
fix
Access segments using integer indices (e.g.,
message[0] for the first segment) or by segment name as a string key (e.g., message['MSH']).
import hl7
hl7_message_string = "MSH|^~\\&|APP|FAC|APP2|FAC2|202301010800||ADT^A01|MSG123|P|2.5\rPID|1||12345^6^7^^MR^MDC|...\r"
message = hl7.parse(hl7_message_string)
# Correct way to access the MSH segment
msh_segment = message['MSH']
print(msh_segment)
# Accessing by index (MSH is typically the first segment)
pids_segment = message # Assuming PID is the second segment
print(pids_segment)
# Accessing a specific field in a segment (e.g., PID.3)
patient_id = message['PID']
print(patient_id) Warnings
gotcha HL7 v2.x messages use \r (carriage return) as the segment separator, NOT \n. Messages with \n line endings will not parse correctly. ↓
fix Ensure raw messages use \r: raw = raw.replace('\n', '\r') before parsing.
breaking The 'mllp' installation extra was removed along with the synchronous MLLPClient class in 0.4.0. MLLP functionality is now async-only and does not require a separate 'mllp' extra. Attempting to install `hl7[mllp]` on versions >= 0.4.0 will result in a warning. ↓
fix Migrate to async: reader, writer = await open_hl7_connection(host, port). The async MLLP functionality is now part of the base `hl7` package and does not require the `[mllp]` extra.
gotcha This library only handles HL7 v2.x pipe-delimited messages. It does NOT support HL7 FHIR (v4 JSON/XML). Use fhir.resources or fhirclient for FHIR. ↓
fix Use the fhir.resources package for FHIR R4/R5 resources.
gotcha Field indexing is 0-based on the segment object but MSH segment counts the field separator as MSH.1, so MSH[1] returns '|' and MSH[9] returns the message type. This 1-off confusion is common. ↓
fix Use the string accessor message['MSH.9'] for clarity, or remember segment()[n] is 0-indexed.
gotcha Accessing a non-existent segment with message.segment('ZZZ') raises KeyError, not returning None. ↓
fix Check segments first: if message.segments('ZZZ'): ... or wrap in try/except KeyError.
Install
pip install hl7[mllp] Install compatibility verified last tested: 2026-05-12
python os / libc variant status wheel install import disk
3.10 alpine (musl) hl7 - - 0.02s 18.0M
3.10 alpine (musl) mllp - - 0.02s 18.0M
3.10 slim (glibc) hl7 - - 0.01s 18M
3.10 slim (glibc) mllp - - 0.01s 18M
3.11 alpine (musl) hl7 - - 0.05s 19.9M
3.11 alpine (musl) mllp - - 0.04s 19.9M
3.11 slim (glibc) hl7 - - 0.04s 20M
3.11 slim (glibc) mllp - - 0.04s 20M
3.12 alpine (musl) hl7 - - 0.03s 11.7M
3.12 alpine (musl) mllp - - 0.03s 11.7M
3.12 slim (glibc) hl7 - - 0.03s 12M
3.12 slim (glibc) mllp - - 0.03s 12M
3.13 alpine (musl) hl7 - - 0.03s 11.4M
3.13 alpine (musl) mllp - - 0.03s 11.4M
3.13 slim (glibc) hl7 - - 0.03s 12M
3.13 slim (glibc) mllp - - 0.03s 12M
3.9 alpine (musl) hl7 - - 0.02s 17.5M
3.9 alpine (musl) mllp - - 0.02s 17.5M
3.9 slim (glibc) hl7 - - 0.02s 18M
3.9 slim (glibc) mllp - - 0.02s 18M
Imports
- hl7.parse wrong
from hl7 import HL7Messagecorrectimport hl7 message = hl7.parse(raw_message_string) - MLLPClient wrong
from hl7 import MLLPClientcorrectfrom hl7.mllp import open_hl7_connection
Quickstart verified last tested: 2026-05-12
import hl7
raw = 'MSH|^~\\&|SND|SND_FAC|RCV|RCV_FAC|20230101120000||ADT^A01|MSG00001|P|2.3\rPID|||12345^^^MRG||DOE^JOHN||19800101|M\r'
message = hl7.parse(raw)
# Access fields using segment(field) notation
print(message.segment('MSH')) # Full MSH segment
print(message['MSH.9']) # Message type: ADT^A01
print(message['PID.5']) # Patient name: DOE^JOHN
print(message.segment('PID')[5]) # Same: DOE^JOHN