npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@tnnquang/file-type-detector

v1.0.0

Published

Detect real file type by analyzing magic bytes - secure and reliable

Readme

File Type Detector

Detect real file types by analyzing magic bytes (file signatures), not file extensions.

npm version License

Perfect for: Upload validation, security checks, file processing pipelines.


Installation

npm install @tnnquang/file-type-detector

Quick Start

import { detectFileType } from "@tnnquang/file-type-detector";

// Node.js
const buffer = fs.readFileSync("image.jpg");
const result = await detectFileType(buffer);

// Browser
const file = event.target.files[0];
const result = await detectFileType(file);

console.log(result);
// {
//   mimeType: 'image/jpeg',
//   typeName: 'JPEG',
//   extension: 'jpg',
//   category: 'image',
//   confidence: 'high',
//   isValid: true,
//   isSpoofed: false,
//   magicBytes: 'FF D8 FF E0...'
// }

API

detectFileType(input, options?)

Detect file type from buffer/blob/file.

const result = await detectFileType(file, {
  bytesToRead: 65536, // Bytes to analyze (default: 64KB)
  expectedExtension: "jpg", // For validation
  expectedMimeType: "image/jpeg", // For validation
});

Returns:

{
  mimeType: string | null; // 'image/jpeg'
  typeName: string; // 'JPEG'
  extension: string | null; // 'jpg'
  category: FileCategory; // 'image'
  confidence: ConfidenceLevel; // 'high' | 'medium' | 'low' | 'none'
  isValid: boolean; // Matches expected type?
  isSpoofed: boolean; // Extension was faked?
  magicBytes: string; // First 16 bytes in hex
}

isFileType(input, mimeType)

Quick check for specific MIME type.

const isPNG = await isFileType(buffer, "image/png");

isFileCategory(input, category)

Check by category.

const isImage = await isFileCategory(file, "image");

validateWhitelist(input, allowedTypes)

Whitelist validation.

const result = await validateWhitelist(file, [
  "image/jpeg",
  "image/png",
  "application/pdf",
]);

if (!result.isAllowed) {
  throw new Error("File type not allowed");
}

validateBlacklist(input, blockedTypes)

Blacklist validation.

const result = await validateBlacklist(file, [
  "application/x-msdownload", // Block .exe
  "application/x-executable", // Block Linux executables
]);

Use Cases

Express.js Upload

import { validateWhitelist } from "@tnnquang/file-type-detector";

app.post("/upload", upload.single("file"), async (req, res) => {
  const result = await validateWhitelist(req.file.buffer, [
    "image/jpeg",
    "image/png",
    "application/pdf",
  ]);

  if (!result.isAllowed || result.isSpoofed) {
    return res.status(400).json({ error: "Invalid file" });
  }

  // Process file...
});

React Component

const handleFile = async (e) => {
  const file = e.target.files[0];
  const result = await detectFileType(file);

  if (result.isSpoofed) {
    alert("File type mismatch detected!");
    return;
  }

  if (result.category !== "image") {
    alert("Only images allowed");
    return;
  }

  // Upload file...
};

Security Scanner

import { detectFileType } from "@tnnquang/file-type-detector";

async function scanFile(buffer, filename) {
  const ext = filename.split(".").pop();
  const result = await detectFileType(buffer, { expectedExtension: ext });

  // Detect spoofed extensions
  if (result.isSpoofed) {
    console.warn(`${filename} is fake! Actually ${result.typeName}`);
  }

  // Block executables
  if (result.category === "executable") {
    console.error(`Executable detected: ${filename}`);
  }
}

Supported File Types (70+ formats)

Images (11 formats)

| Extension | MIME Type | Format Name | | --------------- | --------------- | -------------- | | .jpg, .jpeg | image/jpeg | JPEG | | .png | image/png | PNG | | .gif | image/gif | GIF (87a, 89a) | | .webp | image/webp | WebP | | .bmp | image/bmp | BMP | | .tiff, .tif | image/tiff | TIFF (LE/BE) | | .ico | image/x-icon | ICO | | .svg | image/svg+xml | SVG | | .heic | image/heic | HEIC | | .heif | image/heif | HEIF | | .avif | image/avif | AVIF |

Videos (6 formats)

| Extension | MIME Type | Format Name | | --------- | ------------------ | --------------- | | .mp4 | video/mp4 | MP4 | | .avi | video/x-msvideo | AVI | | .mkv | video/x-matroska | MKV | | .webm | video/webm | WebM | | .flv | video/x-flv | FLV | | .mov | video/quicktime | MOV (QuickTime) |

🎵 Audio (6 formats)

| Extension | MIME Type | Format Name | | --------- | ------------- | ----------- | | .mp3 | audio/mpeg | MP3 (ID3) | | .wav | audio/wav | WAV | | .ogg | audio/ogg | OGG | | .flac | audio/flac | FLAC | | .aac | audio/aac | AAC | | .m4a | audio/x-m4a | M4A |

Documents (7 formats)

| Extension | MIME Type | Format Name | | --------- | --------------------------------------------------------------------------- | ------------------ | | .pdf | application/pdf | PDF | | .doc | application/msword | DOC (Word 97-2003) | | .docx | application/vnd.openxmlformats-officedocument.wordprocessingml.document | DOCX | | .xlsx | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | XLSX (Excel) | | .pptx | application/vnd.openxmlformats-officedocument.presentationml.presentation | PPTX (PowerPoint) | | .rtf | application/rtf | RTF | | .odt | application/vnd.oasis.opendocument.text | ODT (OpenDocument) |

Archives (6 formats)

| Extension | MIME Type | Format Name | | --------- | ------------------------------ | ------------------ | | .zip | application/zip | ZIP | | .rar | application/x-rar-compressed | RAR (v1.5+, v5.0+) | | .7z | application/x-7z-compressed | 7Z | | .gz | application/gzip | GZIP | | .bz2 | application/x-bzip2 | BZIP2 | | .tar | application/x-tar | TAR |

Executables (4 formats)

| Extension | MIME Type | Format Name | | -------------- | --------------------------- | ------------------------ | | .exe, .dll | application/x-msdownload | EXE/DLL (Windows) | | - | application/x-executable | ELF (Linux) | | - | application/x-mach-binary | Mach-O (macOS 32/64-bit) | | .jar | application/java-archive | JAR (Java) |

Fonts (4 formats)

| Extension | MIME Type | Format Name | | --------- | ------------ | ----------- | | .ttf | font/ttf | TTF | | .otf | font/otf | OTF | | .woff | font/woff | WOFF | | .woff2 | font/woff2 | WOFF2 |

3D Models (3 formats)

| Extension | MIME Type | Format Name | | --------- | ------------------- | ------------------ | | .glb | model/gltf-binary | GLB | | .obj | model/obj | OBJ | | .stl | model/stl | STL (ASCII/Binary) |

Security Best Practices

DO

  • Always validate on server-side
  • Use whitelist (not blacklist)
  • Check for spoofed extensions
  • Limit file sizes
  • Validate both extension and content

DON'T

  • Trust file extensions alone
  • Only validate client-side
  • Use blacklist for dangerous files
  • Skip validation for "trusted" users

Example: Complete Validation

import { detectFileType } from "@tnnquang/file-type-detector";

async function validateUpload(file: File) {
  // 1. Check file size
  const MAX_SIZE = 10 * 1024 * 1024; // 10MB
  if (file.size > MAX_SIZE) {
    throw new Error("File too large");
  }

  // 2. Detect real file type
  const result = await detectFileType(file, {
    expectedExtension: file.name.split(".").pop(),
  });

  // 3. Check for spoofing
  if (result.isSpoofed) {
    throw new Error("File extension does not match content");
  }

  // 4. Whitelist validation
  const allowedTypes = ["image/jpeg", "image/png", "application/pdf"];
  if (!result.mimeType || !allowedTypes.includes(result.mimeType)) {
    throw new Error("File type not allowed");
  }

  // 5. Category check
  if (result.category === "executable") {
    throw new Error("Executable files are blocked");
  }

  return result; // File is safe
}

⚡ Performance

  • Detection speed: < 5ms for most files
  • Memory efficient: Only reads first 64KB by default
  • Zero dependencies: No external packages
  • Small bundle: ~15KB minified

🔧 TypeScript Support

Full TypeScript support with complete type definitions:

import type {
  DetectionResult,
  FileCategory,
  ConfidenceLevel,
} from "@tnnquang/file-type-detector";

// Type-safe usage
const result: DetectionResult = await detectFileType(buffer);
const category: FileCategory = result.category; // 'image' | 'video' | ...

More Examples

Batch Processing

async function validateMultipleFiles(files: File[]) {
  const results = await Promise.all(files.map((file) => detectFileType(file)));

  const invalid = results.filter((r) => r.isSpoofed || !r.isValid);

  if (invalid.length > 0) {
    console.warn("Invalid files detected:", invalid);
  }

  return results;
}

Custom Validation Logic

async function customValidation(file: File) {
  const result = await detectFileType(file);

  // Custom rules
  if (result.category === "image") {
    if (file.size > 5 * 1024 * 1024) {
      throw new Error("Images must be under 5MB");
    }
  }

  if (result.category === "document") {
    if (result.mimeType !== "application/pdf") {
      throw new Error("Only PDF documents allowed");
    }
  }

  return result;
}

FAQ

Q: Does it work in the browser?
A: Yes! Works in both Node.js and all modern browsers.

Q: Can I detect files without extensions?
A: Yes, detection is based on magic bytes, not extensions.

Q: How accurate is the detection?
A: Very accurate. Uses official file signatures from format specifications.

Q: What about encrypted/compressed files?
A: Detects the container format (ZIP, RAR, etc.), not contents inside.

Q: Performance impact?
A: Minimal. Only reads first 64KB of file by default.

License

Proprietary Software - Copyright © 2025 Tra Ngoc Nhat Quang. All Rights Reserved.

This is commercial software. See LICENSE for terms.

Key restrictions:

  • ❌ No reverse engineering
  • ❌ No code extraction
  • ❌ No redistribution
  • ✅ Use in your applications
  • ✅ Commercial use allowed

Support


Made with 🔐 by Tran Ngoc Nhat Quang • Securing file uploads since 2025