Library / SDK
avoidwork/filesize.js avatar
avoidwork/filesize.js

filesize turns byte counts into display strings without a dependency

A lightweight, high-performance file size utility that converts bytes to human-readable strings. Zero dependencies. 100% test coverage.

1,711 stars104 forksJavaScriptBSD-3-Clause

At a glance

What is it?
filesize is a zero-dependency JavaScript library that converts bytes to human-readable strings across the SI, IEC and JEDEC standards, and the whole configuration surface is options passed on every call or frozen into a reusable formatter.
Who is it for?
Adopt filesize when a client or server needs byte counts rendered with a real unit standard and you would rather not add a dependency to the tree; skip it if you need a component framework, a currency or metric formatter, or a release cadence signalled by tags, since the project publishes no GitHub releases and versions only through package.json.
Can I use it commercially?
Yes. BSD-3-Clause 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 received new commits within the last day.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One function, one options object, three unit conventions

The problem filesize solves is small and annoying: turning a raw byte count into something a person can read. Download counters, disk-usage reports and upload progress all need it, and every application tends to grow its own version of that arithmetic with its own rounding rules. The library is a single JavaScript package with no dependencies, published as `filesize`, and its entire API is one function plus a helper.

The interesting part is not the arithmetic but the standards. filesize supports three conventions that disagree in two independent ways, which is the base and the symbols:

| Standard | Base | Unit symbols | Example | |----------|------|--------------|---------| | SI | 1000 | kB, MB, GB | `filesize(1000)` → "1 kB" | | IEC | 1024 | KiB, MiB, GiB | `filesize(1024, {standard: "iec"})` → "1 KiB" | | JEDEC | 1024 | KB, MB, GB | `filesize(1024, {standard: "jedec"})` → "1 KB" |

The JEDEC row is the one that trips people up. It is binary in base but borrows the SI-looking symbols, so `filesize(1024, {standard: "jedec"})` and a plain SI call disagree on both the number and the letter.

Setting standard makes base silently irrelevant

The options table is long, but one rule collapses most of the confusion: when you set `standard`, the base is implied and `base` is ignored. `base` is only consulted when `standard` is not set. That is a defensible design, because the standards already fix the base, but it is silent. A caller who writes both gets no warning, no error, and a result that ignores half of what they asked for.

`base` itself defaults to `-1`, meaning auto, and accepts 2 for binary or 10 for decimal. The numeric formatting options form their own small precedence chain. `round` defaults to 2 and sets decimal places. `precision` defaults to 0, and when greater than 0 it takes precedence over `round` entirely. `pad`, defaulting to false, pads the decimal out to match `round`.

Rounding direction is a separate axis: `roundingMethod` accepts `round`, `floor` or `ceil` and defaults to `round`. Passing anything else throws.

Text assembly is separated from the number. `spacer` defaults to a single space between value and unit, `separator` lets you override the decimal separator, and `symbols` takes an object that overrides individual unit symbols, which is how a non-Latin script gets a localized unit without a full locale.

npm install filesize, then call filesize(1024)

Installation is a single package install, since the library ships no runtime dependencies:

bash
npm install filesize

The usage example in the documentation is short enough to state flatly. A default call uses the SI standard, and the standard and bit options change both the number and the symbol:

javascript
import {filesize, partial} from "filesize";

filesize(1024); // "1.02 kB"
filesize(265318); // "265.32 kB"
filesize(1024, {standard: "iec"}); // "1 KiB"
filesize(1024, {bits: true}); // "8.19 kbit"

Note what the defaults do not do. They do not localize, they do not round down, and they keep the space between number and unit. Setting `bits: true` multiplies by eight rather than changing the standard, so the SI base stays and the symbol becomes `kbit`. Combine it with `base: 2` and you get the IEC spelling instead, `8 Kibit`.

If you format many values with identical settings, build the formatter once. `partial()` returns a pre-configured formatter whose options are frozen, and the point of it is to avoid re-parsing the options object on every call:

javascript
import {partial} from "filesize";

const formatBinary = partial({standard: "iec"});
formatBinary(1024); // "1 KiB"
formatBinary(1048576); // "1 MiB"

Because the options are frozen, you cannot mutate a formatter in place. Build another one instead.

output selects the return shape, not the formatting

The `output` option decides what the function returns, with `string` as the default and `array`, `object` and `exponent` as alternatives. This is the mechanism that lets filesize sit under a UI instead of forcing string parsing on the caller:

javascript
// String (default)
filesize(1536); // "1.54 kB"

// Array: [value, symbol]
filesize(1536, {output: "array"}); // [1.54, "kB"]

// Object: {value, symbol, exponent, unit}
filesize(1536, {output: "object"});
// {value: 1.54, symbol: "kB", exponent: 1, unit: "kB"}

// Exponent: the unit index
filesize(1536, {output: "exponent"}); // 1

Returning an object with both `symbol` and `unit` looks redundant until you override symbols: the two fields separate the unit you configured from the unit that was ultimately rendered. A table that wants a sort key can ask for `exponent` and avoid formatting at all.

Two more options widen the output. `fullform` replaces the short symbol with the full unit name, producing "1.02 kilobytes" in SI and "1 kibibyte" when the base is 2, and `fullforms` lets you supply an array of your own names if the built-in set does not fit your language. `exponent` forces a specific unit index, with `-1` meaning let the function decide.

Intl localization through the locale option

Localization is delegated to the platform rather than reimplemented. `locale` takes a locale string such as `"de"`, and `true` selects the system locale, which is the right choice for a UI that follows the user's operating system. `localeOptions` passes extra options through to the underlying formatter.

javascript
filesize(265318, {locale: "de"}); // "265,32 kB"

That result differs from what `separator` alone gives you, and the difference matters. Passing `separator: ","` replaces the decimal point wherever it appears, producing the same visible characters here but without asking for a locale. If a target language groups thousands with a period or uses a non-Latin numbering system, `locale` is the option that reaches it, because `separator` only handles the single character that separates the fraction.

Where the platform has nothing to add, the symbol layer stays open. Overriding a single symbol keeps the numeric formatting intact:

javascript
filesize(1, {symbols: {B: "Б"}}); // "1 Б"

TypeError on bad input, including Infinity and overflowing BigInt

The library throws rather than returning a degraded string, and the documented invalid inputs are broader than the type name suggests. They include non-numeric values, `NaN`, `Infinity`, and BigInt values that overflow `Number.MAX_SAFE_INTEGER`.

javascript
try {
  filesize("invalid");
} catch (error) {
  // TypeError: "Invalid number"
}

try {
  filesize(1024, {roundingMethod: "invalid"});
} catch (error) {
  // TypeError: "Invalid rounding method"
}

That design has a cost worth naming. `Infinity` is a legitimate answer for an unknown byte count in some applications, and here it is an exception rather than a special return. Any code path that passes through a value the caller does not fully control, such as an API field, needs a try/catch or its own guard, because the failure mode is a thrown `TypeError` rather than a falsy result.

BigInt is supported for genuine large values, and the entry point is the BigInt literal rather than an option:

javascript
filesize(BigInt(1024)); // "1.02 kB"
filesize(-1024); // "-1.02 kB"

Three built files, one engine floor, and no GitHub releases

The published package is narrow. Its files array lists `dist/filesize.js`, `dist/filesize.cjs` and `types/filesize.d.ts`, and the exports map routes types, `import` and `require` respectively, so the same dependency works in ESM and CommonJS consumers without a bundler alias. The source of record is `src/filesize.js`, and the project structure breaks that directory into three files: the main implementation, `helpers.js` and `constants.js`, with the unit tables and symbol sets living in constants rather than inline.

The declared engine floor is `node >= 10.8.0`, and the package is `"type": "module"`. TypeScript users get the definitions from the same package, with the formatter type spelled out as a function from `number | bigint` to `string`:

typescript
import {filesize, partial} from "filesize";

const result: string = filesize(1024);
const formatted: {value: number; symbol: string; exponent: number; unit: string} = filesize(1024, {output: "object"});

const formatter: (arg: number | bigint) => string = partial({standard: "iec"});

Development runs on the platform test runner rather than a framework. `npm test` runs lint plus `node:test`, and the documented figures are 100% statement, branch, function and line coverage across constants.js, filesize.js and helpers.js with 255 tests. `npm run coverage` writes the report to `coverage.txt`.

Two maintenance facts deserve attention. The version in `package.json` is 11.0.26, so this is a mature major line rather than a new arrival. And the project has no GitHub releases at all: versioning happens through the package itself, so a pinned dependency version is the only meaningful upgrade marker, and there is no tagged changelog release entry to point at.

What filesize does not do, and what to use instead

The boundary is the arithmetic. filesize formats a single byte count and returns a string, array or object. It has no opinion about progress, no awareness of transfer state, and no ability to parse a string back into a number.

The natural alternative for a UI is writing the division yourself, which is what most applications do once. That approach costs a few lines and avoids a dependency entirely, but it forces every call site to decide base, symbol table and rounding independently, and it has no locale story worth the name.

For file-size display inside a component library or admin panel, the deciding factor is whether the surrounding code already wants the structured return. If your table sorts on size, the `output: "object"` and `output: "exponent"` modes are the reason to take this library rather than a one-line helper.

Editorial conclusion

Adopt filesize when a client or server needs byte counts rendered with a real unit standard and you would rather not add a dependency to the tree; skip it if you need a component framework, a currency or metric formatter, or a release cadence signalled by tags, since the project publishes no GitHub releases and versions only through package.json. Before adopting, check that the option precedence you rely on matches your expectations, especially that setting `standard` silently ignores `base`, and confirm your runtime satisfies the declared `node >= 10.8.0` engine range if you are not on a modern Node.

Frequently asked questions

How do I install filesize and format a value?

Run `npm install filesize`, then import the named export and call it: `import {filesize} from "filesize"; filesize(1024)` returns "1.02 kB". The package has no runtime dependencies.

What is the difference between the si, iec and jedec standards in filesize?

They differ in base and symbols. SI uses base 1000 with kB, MB, GB, IEC uses base 1024 with KiB, MiB, GiB, and JEDEC uses base 1024 with the shorter KB, MB, GB symbols.

Why is my base option ignored in filesize?

When `standard` is set, the base is implied and `base` is ignored. The `base` option is only consulted when `standard` is not set.

Does filesize handle very large values and localized formats?

Yes to both. Pass a BigInt for sizes beyond `Number.MAX_SAFE_INTEGER`, and use the `locale` option for Intl-based formatting, for example `filesize(265318, {locale: "de"})` returns "265,32 kB".

What happens when filesize receives invalid input?

It throws a `TypeError`. The documented invalid inputs include non-numeric values, `NaN`, `Infinity`, and BigInt values that overflow `Number.MAX_SAFE_INTEGER`, and an unrecognized `roundingMethod` raises "Invalid rounding method".

Official sources

  1. avoidwork/filesize.js on GitHub
  2. Issues
  3. License: BSD-3-Clause
  4. Project website
  5. README
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/avoidwork-filesize-js.svg)](https://hysenlabs.com/projects/avoidwork-filesize-js)

Was this useful?