msgpack-javascript: a MessagePack reference implementation for TypeScript
@msgpack/msgpack - MessagePack for JavaScript / msgpack.org[ECMA-262/JavaScript/TypeScript]
At a glance
- What is it?
- The @msgpack/msgpack package is the reference MessagePack implementation for TypeScript and JavaScript, with a synchronous encoder, several decoding shapes including streaming, and an extension codec for types the format does not cover. It suits anyone who needs a compact binary wire format across browsers, Node, Deno and Bun, and the encoder options are where the interesting decisions live.
- Who is it for?
- Adopt @msgpack/msgpack if you need a compact binary format across browser and server runtimes and want a maintained reference implementation with type definitions, since the package ships CommonJS, ESM and UMD builds with d.ts files. Skip it if you need a format with a JSON Schema ecosystem behind it, because MessagePack is a binary format with no self-describing schema.
- Can I use it commercially?
- Yes. ISC is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 103 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the package is, and the second-edition history
This library is an implementation of MessagePack for TypeScript and JavaScript, providing a compact and efficient binary serialization format. It serves as a comprehensive reference implementation of MessagePack for JavaScript with a focus on accuracy, compatibility, interoperability and performance. The primary language is TypeScript, the licence is ISC, the last push was on 2026-07-13, and the releases are v3.1.3 on 2025-12-26, v3.1.2 on 2025-06-25 and v3.1.1 on 2025-03-12. The topics list includes deno-library and universal-javascript, which is the direction of travel. The history is worth one paragraph because it explains the version numbers you see. This is the second edition of MessagePack for JavaScript, the first edition having been implemented in ES5 and never released to npmjs.com, and it is tagged as `classic` in the repository. That is why the package is TypeScript and ES2015+ rather than the ES5 code many older MessagePack ports still ship, and it is also why an older project has a modern-looking package.
The install, and the universal claim
The package is published to npmjs.com as @msgpack/msgpack:
npm install @msgpack/msgpackIt is described as a universal JavaScript library, compatible not only with browsers but with Node.js or other JavaScript engines that implement ES2015+ standards, and because it is written in TypeScript it bundles up-to-date type definition files. The distribution has three shapes, which the package manifest makes explicit. `main` points at `./dist.cjs/index.cjs` for CommonJS, `module` at `./dist.esm/index.mjs` for ESM, and the `cdn` and `unpkg` fields both point at `./dist.umd/msgpack.min.js` for a script tag. The `exports` map is conditional on `import` versus `require`, and each branch carries its own types file, with `index.d.mts` for the ESM side and `index.d.cts` for the CommonJS one. The package also sets `sideEffects` to false, which is the flag that lets a bundler drop the module entirely if nothing imports from it, and the README carries a tree-shaking badge for the same reason.
The API, from one call to a stream
The surface is small at the top and grows downward. `encode(data: unknown, options?: EncoderOptions): Uint8Array` encodes a value into a single MessagePack object and returns a byte array, throwing on non-serializable input such as a function or a symbol. `decode(buffer, options?): unknown` decodes a buffer into a value typed `unknown`. `decodeMulti` returns a Generator, which is how you read a concatenation of several MessagePack objects from one buffer. Then there are the stream forms, `decodeAsync` for a Promise of a single value and `decodeArrayStream` and `decodeMultiStream` returning AsyncIterables. The `ReadableStreamLike` type in the signatures is deliberately loose, so the stream functions accept a wide range of stream implementations rather than only the platform's own. The `unknown` return type is worth pausing on, because it means the library makes no claim about the shape of what it decodes, and the type safety you get comes from your own casting rather than from a schema.
The encoder options, and the two that change your data
The EncoderOptions table is the part of the API that decides what bytes come out, and two entries are worth real attention. `useBigInt64` defaults to false, so by default a BigInt is not encoded as a 64-bit integer, and turning it on changes how large integers cross the wire. `maxDepth` defaults to 100, which is a recursion guard, and a deeply nested structure hits it rather than exhausting the stack. `sortKeys` defaults to false, and setting it to true gives you deterministic output for the same object, which is what you want if you are hashing or diffing the encoded bytes. `forceFloat32` and `forceIntegerToFloat` let you widen or narrow how numbers are represented, `ignoreUndefined` controls whether undefined properties are skipped, `initialBufferSize` is 2048 as the starting allocation for the output buffer, and `extensionCodec` defaults to `ExtensionCodec.defaultCodec` while `context` is user-defined. The buffer allocation point matters for a library that runs on every message in a hot path, since the initial size is a guess you can tune.
Extension types, and how BigInt gets handled
MessagePack has a small set of built-in types, and the extension codec is how anything else crosses the wire. The README has a section on the ExtensionCodec context, on handling BigInt with ExtensionCodec, and on the temporal module as timestamp extensions, so the mechanism is a pluggable mapping between your types and the format's extension type space. The `context` field on the encoder options is the user-defined slot, which is where you would put the state a codec needs to resolve a type, and the `decode` side has its own options table for the same reason. The BigInt case is the one with a documented answer, since BigInt has no native MessagePack representation, and the temporal module section shows the same idea applied to dates. The reason this matters in practice is interoperability, because a peer that does not understand your extension type will decode it as an unknown type rather than as your value.
A fast path for large float arrays, and the Blob case
Two specialised sections in the README are worth a reader's attention because they are performance work rather than API documentation. There is a faster way to decode a large array of floating point numbers, which is a real problem when a message carries a time series or a point cloud and the generic decoder spends its time on per-element dispatch. And there is a section on decoding a Blob, which is the browser case where the bytes arrive in a type the library has to accept as a `BufferSource`. The README also has a MessagePack specification section with a mapping table, which is the reference for what each byte means, and it is the table to consult when you need to interoperate with a non-JavaScript implementation rather than guessing at the wire format.
The build, the tests and the runtime matrix
The repository is a serious piece of engineering, and the tool list shows it. The build has separate TypeScript projects for the CommonJS, ESM and webpack outputs, with `tsconfig.dist.cjs.json`, `tsconfig.dist.esm.json` and `tsconfig.dist.webpack.json`, and a post-processing step that rewrites the extension of the emitted files to `.mjs` and `.cjs` as appropriate. Tests run under mocha, under Karma in a browser via `karma.conf.ts`, under Deno with `deno test --allow-read test/deno_*.ts`, and under Bun with `bun test test/bun.spec.ts`, and there is a fuzz target that runs jsfuzz against a decode corpus for 60 seconds. Coverage uses nyc with its own configuration, and there is a `mod.ts` at the repository root for Deno. The Makefile wraps the npm scripts, adds a benchmark target that runs the msgpack-lite comparison, and provides `profile-encode` and `profile-decode` targets that use `node --prof` and flamebearer to find the hot spots. The `validate-git-status` target is a nice touch for a release pipeline, since it refuses to publish from a branch other than main or with uncommitted changes.
Editorial conclusion
Adopt @msgpack/msgpack if you need a compact binary format across browser and server runtimes and want a maintained reference implementation with type definitions, since the package ships CommonJS, ESM and UMD builds with d.ts files. Skip it if you need a format with a JSON Schema ecosystem behind it, because MessagePack is a binary format with no self-describing schema. Before you start, note that the package requires an ES2015+ engine, that the decoder returns `unknown` so you cast it yourself, and that the encoder options include a maxDepth of 100 and a useBigInt64 flag that is off by default, both of which change the shape of the data you produce.
Frequently asked questions
How do I install MessagePack for JavaScript?
Run `npm install @msgpack/msgpack`. The package is published to npmjs.com as @msgpack/msgpack and ships CommonJS, ESM and UMD builds with TypeScript definition files.
What does the decode function return in msgpack-javascript?
It returns the decoded object typed as unknown, so you cast it yourself. The buffer must be an array of bytes, typically a Uint8Array or an ArrayBuffer, and BufferSource is defined as ArrayBuffer or ArrayBufferView.
How do I encode BigInt values with msgpack-javascript?
The useBigInt64 encoder option is off by default, so BigInt is not encoded as a 64-bit integer unless you turn it on. The README also documents handling BigInt through the ExtensionCodec, and the temporal module as timestamp extensions.
How do I decode several MessagePack objects from one buffer?
Use decodeMulti, which returns a Generator, for a buffer containing concatenated objects, or decodeMultiStream for the stream form. decodeAsync returns a Promise of a single value and decodeArrayStream returns an AsyncIterable.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/msgpack-msgpack-javascript)Was this useful?