mrkeyoor.com_
Sun 20 Sept 07:01 UTC
npmUtilsupdated 20 Sept 2026

file-type review

file-type 22.0.2 examines magic bytes and returns an extension plus MIME hint for a path, byte array, Blob, web stream, or tokenizer. It targets binary formats; plain text, CSV, and core SVG detection are explicitly outside its scope. The 22.0.2 patch fixes ZIP entries with data descriptors on Node 24 and prevents UTF-16 LE text from being classified as MPEG audio. A match identifies a signature, not a safe or complete file. Our full browser import measured 64.6 KB minified and 19.1 KB gzipped.

40.6Mdownloads / wk
Verdict

file-type 22.0.2 took 2.6 seconds to install 10 packages and produced a 19.1 KB gzipped browser bundle in our sandbox, with 0 audit findings. It is a useful binary-upload hint on Node 22+, but it cannot validate a file, scan malware, or identify ordinary text formats.

We installed it

Lab card: what happened when we installed file-typeScreenshot of file-type documentation
Install✓ · 2.6s10 packages on disk · 1 MB
ImportESM import works · require() works · ESM package with exports map
Browser19.1 KBgzipped (64.6 KB minified), bundled with esbuild
Typesno TypeScript types found
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does file-type install cleanly?

Yes. In a fresh container with an empty cache, npm install file-type finished in 3 seconds, leaving 10 packages and 1 MB on disk. npm audit reported no known vulnerabilities.

How much does file-type add to a browser bundle?

19.1 KB gzipped (64.6 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does file-type work with both ESM and CommonJS?

Yes. Both import 'file-type' and require('file-type') worked in Node 22 in our run. The package is published as ESM with an exports map.

Does file-type include TypeScript types?

No type declarations were found in our install, so TypeScript users need their own declarations.

file-type or magic-bytes.js: which should you use?

magic-bytes.js: Choose it for synchronous byte matching and a smaller browser-oriented signature table. file-type 22.0.2 took 2.6 seconds to install 10 packages and produced a 19.1 KB gzipped browser bundle in our sandbox, with 0 audit findings.

When should you not use file-type?

Inputs are text, CSV, or SVG and lack a dependable core binary signature. The README excludes these formats.

API stability3/5Version 22.0.2 retains fileTypeFromFile, fileTypeFromBuffer, fileTypeFromBlob, fileTypeFromStream, fileTypeStream, and tokenizer-based detection. Recent majors have raised the Node floor and moved stream usage to web ReadableStream, so code can break even when the detected formats are unchanged. Pin the major and rerun representative fixtures because parser fixes can also alter a returned type without producing a compile error.
Docs5/5The current README documents all 6 main input paths, supported MIME and extension Sets, custom detectors, remote tokenizers, sample sizing, and MPEG offset tolerance. It states that text formats are excluded and that a magic-byte match is only a best-effort hint. The custom-detector section also explains tokenizer position and concurrency hazards, giving implementers enough detail to avoid two subtle failure modes.
Maintenance5/5file-type 22.0.2 was released on August 15, 2026, and the unarchived repository was pushed the same day. GitHub showed 0 open issues and pull requests. The patch corrects ZIP detection under Node 24 and a UTF-16 LE false positive for MPEG audio, both concrete parser defects. Frequent runtime-floor changes add upgrade work, but signature and container handling are receiving current fixes.
Ecosystem4/5npm recorded 56,139,681 downloads from August 19 through 25, 2026, and GitHub reported 4,321 stars. Separate tokenizer packages cover HTTP and S3 access, while optional detectors add XML, PDF variants, CFBF, and finer media distinctions. The Node 22 requirement and ESM-first documentation narrow compatibility, and our install found no TypeScript declarations despite the library's broad JavaScript use.

Discussed on

  1. hnMagika: AI powered fast and efficient file type identification695 points
  2. hnAlternative File-Type extension for TypeScript files (.ts = MPEG-2 video)13 points
  3. hnThere Is No .bro in Brotli: Google/Mozilla Engineers Nix File Type as Offensive5 points

Use it if

  • An upload service needs to compare sender-provided names and content types with the bytes it received.
  • Remote S3 or HTTP objects should be identified through range-capable tokenizers before a full transfer.
  • One detector table must cover common images, archives, media, fonts, executables, and compound containers.
  • Unknown binary formats can be rejected by an allowlist before a specialized decoder touches them.
Skip it if

Setup reality

We installed file-type 22.0.2 in a fresh Node 22 Bookworm sandbox. npm took 2.6 seconds and left 10 packages occupying 1 MB. The package declares 4 direct dependencies and no peers, with 164 KB unpacked. npm audit found 0 known vulnerabilities. It requires Node 22, uses ESM with an exports map, and both require() and ESM import worked in our check. We found no TypeScript declarations.

No config file or credentials are required. Detection helpers return promises, including fileTypeFromBuffer(). A miss resolves to undefined, which must be an explicit rejection branch in an upload allowlist. The result's ext and mime are routing hints; enforce request-size limits, decode the selected format, and isolate expensive processing separately.

fileTypeFromStream() consumes a web ReadableStream. Convert an fs stream with Readable.toWeb(), or use fileTypeFromFile() when the filesystem is available. fileTypeStream() samples bytes and returns a replayable stream carrying fileType. Its default sample is 4,100 bytes; a smaller value reduces buffering per concurrent request while also reducing the signatures it can identify.

HTTP and S3 tokenizers can seek to relevant ranges instead of downloading an entire object. Custom detectors run ahead of built-ins and are not safe to share concurrently. Create a parser per call when using them. A detector that moves tokenizer.position and returns undefined prevents later detectors from evaluating the original position. Our complete browser build was 64.6 KB minified and 19.1 KB gzipped, so import it client-side only when the supported table earns that cost.

Patterns

Detect a local file identify-file-path

import { fileTypeFromFile } from 'file-type';

const detected = await fileTypeFromFile('incoming/upload.bin');
if (!detected) throw new Error('Unsupported binary type');

No signature match resolves to undefined rather than throwing.

Inspect bytes already in memory identify-memory-bytes

import { fileTypeFromBuffer } from 'file-type';

const detected = await fileTypeFromBuffer(bytes);
console.log(detected?.ext, detected?.mime);

fileTypeFromBuffer returns a promise even though the input bytes are already available.

Allow specific detected types enforce-upload-allowlist

const allowed = new Set(['image/jpeg', 'image/png']);
const detected = await fileTypeFromBuffer(body);
if (!detected || !allowed.has(detected.mime)) throw new Error('File type rejected');

Reject undefined too. Body caps and decoder validation remain separate controls.

Check a browser File inspect-browser-file

import { fileTypeFromBlob } from 'file-type';

const selected = fileInput.files[0];
const detected = await fileTypeFromBlob(selected);

File inherits from Blob. Repeat detection on the server because the sender controls browser code and request metadata.

Convert an fs stream convert-node-readable

import fs from 'node:fs';
import { Readable } from 'node:stream';
import { fileTypeFromStream } from 'file-type';

const webStream = Readable.toWeb(fs.createReadStream(path));
const detected = await fileTypeFromStream(webStream);

Version 22 expects a web ReadableStream, not a Node stream.Readable.

Detect without losing stream bytes sample-and-replay-stream

import { fileTypeStream } from 'file-type';

const replayable = await fileTypeStream(response.body, { sampleSize: 4100 });
console.log(replayable.fileType);
await consume(replayable);

The returned stream starts at byte 0 after fileTypeStream buffers its sample.

Check the built-in MIME set validate-supported-mime

import { supportedMimeTypes } from 'file-type';

if (!supportedMimeTypes.has(expectedMime)) {
  throw new Error('MIME is not covered by this detector');
}

supportedMimeTypes and supportedExtensions are Set instances, so use has() for membership.

Detect a remote object by ranges probe-http-ranges

import { makeTokenizer } from '@tokenizer/http';
import { fileTypeFromTokenizer } from 'file-type';

const tokenizer = await makeTokenizer(url);
const detected = await fileTypeFromTokenizer(tokenizer);

A range-capable tokenizer can seek without transferring the full remote object.

Add an XML detector extend-xml-detection

import { detectXml } from '@file-type/xml';
import { fileTypeFromFile } from 'file-type';

const detected = await fileTypeFromFile('map.kml', { customDetectors: [detectXml] });

KML, SVG, RSS, and other XML-family formats require the separate detector.

Use the result as a storage hint route-by-extension

const detected = await fileTypeFromFile(source);
if (!detected) throw new Error('Unknown file');
await rename(source, `${target}.${detected.ext}`);

A detected extension is suitable for routing, but it does not prove that the full file is well formed.

Allow a shifted MPEG frame set-mpeg-tolerance

const detected = await fileTypeFromBuffer(bytes, { mpegOffsetTolerance: 10 });

The default tolerance is 0. Raising it accepts malformed media with a slightly shifted first frame and can increase false matches.

Create a parser per concurrent call isolate-custom-parser

import { FileTypeParser } from 'file-type';

async function detect(path) {
  const parser = new FileTypeParser({ customDetectors: [myDetector] });
  return parser.fromFile(path);
}

Custom-detector parser instances are not safe for concurrent reuse, so construct one for each overlapping operation.

Alternatives

PackageRegistryPick it when
magic-bytes.jsnpmChoose it for synchronous byte matching and a smaller browser-oriented signature table.
mime-typesnpmChoose it when trusted filename extensions are enough and file contents need no inspection.
mmmagicnpmChoose libmagic-backed recognition when a native addon is acceptable in deployment.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.