DICOM

DICOM metadata in one line, without a pixel pipeline.

@cosyte/dicom reads the headers of real-world, vendor-quirky Part 10 files (patient, study, series, image, codes and UIDs), records every deviation it tolerated as a stable warning code, and never decodes pixels. Zero runtime dependencies.

@cosyte/dicom
npm install @cosyte/dicom

Need it integrated? Talk to us.

The standard

DICOM is the international standard for medical images.

  • DICOM is the international standard for medical images and related information. It defines the formats for images exchanged with the data and quality needed for clinical use. Source: DICOM Standard, About
  • It is implemented in almost every radiology, cardiology imaging and radiotherapy device, and increasingly in other domains such as ophthalmology and dentistry. Source: DICOM Standard, About
  • ISO recognizes DICOM as ISO 12052, and NEMA serves as the DICOM Secretariat. Source: DICOM Standard, About
  • Part 15, Annex E defines attribute confidentiality profiles: which attributes to remove or replace so a data set does not leak identifying information. Source: DICOM PS3.15, Annex E

@cosyte/dicom

The metadata half, on its own.

Most software that touches imaging needs a handful of header fields: who the patient is, which study and series an instance belongs to, and how the pixels are to be interpreted. Getting them usually means adopting a toolkit built around a pixel pipeline you will not use. This library is the metadata half only.

  • Views for patient, study, series and image. An absent value reads as absent, never as a substituted default.
  • Lazy typed value decode across all 34 value representations.
  • The four native transfer syntaxes and every encapsulation syntax in PS3.5 section A.4 are read, with pixel fragments returned as raw bytes.
  • A spec-clean serializer that writes an object back in its source transfer syntax.
  • Metadata de-identification with deidentify(), driven by the PS3.15 action table.
  • Source and vendor profiles, and a stable warning code for everything tolerated.
  • Zero runtime dependencies.
read-headers.tsts
import { parseDicom } from "@cosyte/dicom";

// A synthetic CT object, saved without its 128-byte preamble: an invented patient and example-root
// UIDs, no real PHI. In your integration these are the bytes of the file you read.
const buf = Buffer.from(
  "AgAAAFVMBAAcAAAAAgAQAFVJFAAxLjIuODQwLjEwMDA4LjEuMi4xAAgAFgBVSRoAMS4yLjg0MC4xMDAwOC41LjEuNC4xLjEuMgAIABgAVUkeADEuMi44MjYuMC4xLjM2ODAwNDMuOC40OTguMTExAAgAIABEQQgAMTkwMDAxMDEIAGAAQ1MCAENUEAAQAFBOCABEb2VeSmFuZRAAIABMTwYATVJOLTQyEAAhAExPDABTQU1QTEUtSE9TUCAgAA0AVUkeADEuMi44MjYuMC4xLjM2ODAwNDMuOC40OTguMS4xACAADgBVSR4AMS4yLjgyNi4wLjEuMzY4MDA0My44LjQ5OC4xLjIAIAARAElTAgAyICgAEABVUwIAAAIoABEAVVMCAAACKAAAAVVTAgAQACgAAwFVUwIAAQAoAFIQRFMGAC0xMDI0ICgAUxBEUwIAMSAoADAARFMIADAuNVwwLjUg",
  "base64",
);
const ds = parseDicom(buf);

console.log("patient", ds.patient.id, "issuer", ds.patient.issuerOfId);
console.log("study", ds.study.instanceUid);
console.log("series", ds.series.modality, "image", ds.image.rows, "x", ds.image.columns);
console.log("rescale slope", ds.image.rescaleSlope, "intercept", ds.image.rescaleIntercept);
console.log("tolerated", ds.warnings.length, ds.warnings[0]?.code);

// The values printed above, which the test suite asserts on every run.
// NOT globally unique on its own: pair it with ds.patient.issuerOfId.
ds.patient.id; // => "MRN-42"
// The global study anchor.
ds.study.instanceUid; // => "1.2.826.0.1.3680043.8.498.1.1"
ds.series.modality; // => "CT"
ds.image.rows; // => 512
// number | undefined: undefined means "absent", never a substituted 1.
ds.image.rescaleSlope; // => 1
// What the parser tolerated, as stable codes.
ds.warnings.map((w) => w.code); // => ["DICOM_MISSING_PREAMBLE"]

From the @cosyte/dicom README on GitHub, verbatim. Every value in it is synthetic.

Limits

What it does not do.

It is metadata-first by design. Its README says not to rely on it for:

  • Pixel data: nothing is decoded, decompressed or rendered.
  • Burned-in annotations: they are not removed, so de-identified output is metadata-only, and the library warns about it.
  • Networking: no DIMSE (C-STORE, C-FIND, C-MOVE) and no DICOMweb.
  • Transcoding: no transfer-syntax conversion.
  • Terminology: coded values are surfaced, not validated against SNOMED or LOINC.
  • Its README measures and discloses the open de-identification residuals. Read them before pointing it at real data.

The full status and limits, in the README

Alternatives

What else you could use.

Each description comes from the project’s own documentation or listing, linked below.

JavaScript library

dcmjs

An MIT-licensed JavaScript implementation of DICOM manipulation. Its latest npm release dates from May 2026.

Source: npm, dcmjs

JavaScript library

dicom-parser

An MIT-licensed JavaScript parser for DICOM Part 10 data, from the Cornerstone project. Its latest npm release dates from February 2023.

Source: npm, dicom-parser

Node.js library

dcmjs-dimse

An MIT-licensed DICOM DIMSE implementation for Node.js, built on dcmjs. If you need DIMSE networking, which @cosyte/dicom does not do, this is where to look.

Source: npm, dcmjs-dimse

DICOM server

Orthanc

An open-source DICOM server for healthcare and medical research. A server stores and serves studies; @cosyte/dicom reads and writes files inside your own code.

Source: Orthanc, about

Works with

  • De-identification@cosyte/deid applies a policy to DICOM metadata through the same manifest as every other format.
  • HL7 v2Imaging orders and results travel as HL7 v2 alongside the DICOM objects: @cosyte/hl7.

Try @cosyte/dicom on your own messages.

It is free and MIT-licensed. If it saves you a day, a star on GitHub helps other engineers find it.

Need it integrated? Talk to us, or see what our integration services cover.