guessit-js

Extract metadata from media filenames using smart pattern matching. Zero dependencies. TypeScript port of the Python guessit library.

v3.9.0 Zero dependencies TypeScript

Try it live

Type a filename above or click an example below.

📄 Examples

Click any filename to parse it instantly.

🔌 REST API

GET /api/guessit?filename=...&type=movie

Parse a media filename and return extracted metadata as JSON.

Parameters: filename (required), type (optional: movie | episode)

// Example
curl "/api/guessit?filename=Breaking.Bad.S01E02.720p.BluRay.x264-DEMAND.mkv"

// Response
{
  "title": "Breaking Bad",
  "season": 1,
  "episode": 2,
  "screen_size": "720p",
  "source": "Blu-ray",
  "video_codec": "H.264",
  "release_group": "DEMAND",
  "container": "mkv",
  "type": "episode"
}
POST /api/guessit

Parse with full options. Send JSON body with filename and optional options object.

// Example
curl -X POST /api/guessit \
  -H "Content-Type: application/json" \
  -d '{"filename": "The.Matrix.1999.REMASTERED.2160p.UHD.BluRay.x265-GROUP.mkv",
       "options": {"type": "movie"}}'

📦 Use as a library

Install
npm install guessit-js
ESM / TypeScript
import { guessit } from 'guessit-js';

const result = guessit('The.Dark.Knight.2008.1080p.BluRay.x264-GROUP.mkv');
console.log(result.title);       // "The Dark Knight"
console.log(result.year);        // 2008
console.log(result.screen_size); // "1080p"
console.log(result.type);        // "movie"
CommonJS
const { guessit } = require('guessit-js');

const result = guessit('Inception.2010.720p.BRRip.x264.mkv');
console.log(result.title);  // "Inception"
console.log(result.year);   // 2010
Options
// Force type detection
guessit('file.mkv', { type: 'episode' });

// Provide expected titles for better matching
guessit('file.mkv', { expected_title: ['My Show'] });

// Restrict languages & countries
guessit('file.mkv', { allowed_languages: ['en', 'fr'], allowed_countries: ['us', 'gb'] });

WASM

guessit-js compiles to WebAssembly for environments without a JavaScript runtime.

How it works
The WASM build embeds the entire QuickJS JavaScript engine inside a WebAssembly module via Javy. The guessit-js code runs as interpreted JS inside QuickJS inside WASM.

Build pipeline:  TypeScript → esbuild (IIFE) → Javy (QuickJS → WASM) → wasm-opt

When to use WASM:
  • Non-JS backends (Rust, Go, C++, Python) that need filename parsing
  • Edge compute / serverless (Cloudflare Workers, Fermyon Spin)
  • Sandboxed or embedded environments
  • CLI tools via wasmtime / wasmer

When to use JS directly:
  • Browser — use the IIFE bundle, runs at native V8/SpiderMonkey speed
  • Node.js / Deno / Bun — 3.5x faster than Python, ~2ms/parse
  • Any environment that already has a JS runtime

Note: WASM is ~40x slower than native JS in a browser because it runs a JS interpreter (QuickJS) inside WASM inside the browser's own JS engine. Use the JS bundle for browser/Node.js.
3.9 MB
WASM binary
1.6 MB
Gzipped
169 KB
JS code inside
Usage
# Parse a filename via stdin/stdout JSON
echo '{"filename":"The.Dark.Knight.2008.1080p.BluRay.x264-GROUP.mkv"}' | wasmtime guessit.wasm

# Build from source
npm run wasm   # requires Javy v3+ in tools/
Compatible runtimes
wasmtime     — Bytecode Alliance reference runtime
wasmer       — Universal WASM runtime
WasmEdge     — Cloud-native WASM runtime
Cloudflare Workers — Edge compute (WASI support)
Fermyon Spin — Serverless WASM platform

📈 Compatibility & Performance

100%
Test compatibility
1035 / 1035 Python tests pass
3.4x
Faster than Python
6.87ms vs 23.86ms per parse
0
Runtime dependencies
~220KB bundled (ESM + CJS)
40+
Detected properties
title, year, codec, lang...
Performance Benchmark

1000 parses of 10 diverse filenames on the same machine:

Runtime               ms/parse    vs Python
───────────────────────────────────────────────
Python 3.8 (guessit)   23.86 ms    baseline
Node.js 22 (JS)         6.87 ms    3.5x faster
Browser (IIFE bundle)  ~2-3  ms    ~10x faster
WASM (QuickJS)        ~75   ms    for non-JS envs only

🛠 Architecture

Overview
guessit-js is a complete TypeScript port of the Python guessit library (v3.9.0). It extracts metadata from media filenames using a multi-layer pattern matching engine with rule-based post-processing.

The codebase is ~8689 lines of TypeScript across 46 source files, organized into four layers:

1. Public API (src/api.ts)
   GuessItApi class — manages config, builds pattern matcher, converts matches to plain objects.

2. Rebulk Engine (src/rebulk/ — 14 files, 2,772 lines)
   Port of Python's rebulk library. Generic pattern matching with regex, string, functional, and chain patterns. Includes conflict resolution and match container.

3. Rules & Properties (src/rules/ — 35 files, 6,833 lines)
   Each property type (title, episodes, source, codec, language, etc.) is a separate module returning a configured Rebulk instance. Post-processing rules handle cross-property interactions.

4. Configuration (src/config/options.json)
   JSON-driven pattern definitions, property values, and aliases. Supports regex, string, and functional patterns with validators, formatters, and conflict solvers.
Test Suite
Tests use YAML fixtures ported directly from the Python guessit test suite:

movies.yml        208 test cases — movie filenames with paths
episodes.yml      523 test cases — TV episodes, anime, specials
various.yml       126 test cases — edge cases and mixed formats
streaming.yaml    197 test cases — streaming service detection

1035 / 1035 tests passing (100% compatibility with Python guessit)

All 1035 Python guessit tests passing.
    
Build Output
ESM  dist/guessit-js.js   — 329 KB (ES modules, tree-shakeable)
CJS  dist/guessit-js.cjs  — 329 KB (CommonJS, Node.js require())
DTS  dist/*.d.ts          — Full TypeScript type definitions

Zero runtime dependencies. Self-contained for browser, Node.js, and WASM.
WASM wasm/guessit.wasm — 3.9 MB (1.6 MB gzipped) — via Javy (QuickJS)
Built with Vite. Type-checked with tsc --noEmit.

📚 Detected properties

guessit-js can detect and extract these metadata fields from filenames: