CLI tool
j4k0xb/webcrack avatar
j4k0xb/webcrack

webcrack supports Node 22 and 24, and the requirements section still carries a TODO for 26

Deobfuscate obfuscator.io, unminify and unpack bundled javascript

2,947 stars337 forksTypeScriptMIT

At a glance

What is it?
A TypeScript tool that deobfuscates obfuscator.io output, unminifies, transpiles and unpacks webpack or browserify bundles, shipped as a CLI and a library. The published package is a workspace member, npm test watches while test:coverage runs once, and two coverage providers are installed side by side.
Who is it for?
webcrack fits someone holding a minified or obfuscated bundle who needs readable source rather than a working copy of the same bytes, and the API is the better surface when the output has to be fed into something else, since it returns the bundle metadata alongside the code. Three things to check first.
Can I use it commercially?
Yes. MIT 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 71 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 4, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Only even Node releases, and the reason is V8 ABI stability

The Requirements section is two sentences and a comment. It states Node.js 22 or 24, and then an HTML comment that reads as an unfinished note: add 26 on release.

The reason for skipping odd numbers is given in a note directly underneath. webcrack depends on `isolated-vm`, and that project's own documentation says it does not recommend odd-numbered Node.js releases because they frequently break ABI and API compatibility with V8. So the constraint is inherited rather than chosen, and a user who picks Node 25 is not misusing the tool, they are stepping outside what the sandboxing dependency supports.

That also explains the `patches/` directory at the root of the repository. In a pnpm workspace, a directory of that name holds patch files applied to dependencies at install time, which is what you reach for when a native or V8-adjacent dependency needs adjusting. The Node support window is therefore a moving target that changes when isolated-vm and V8 do, not when a user decides they want a newer runtime.

The root manifest is named webcrack and is private, so the published package is elsewhere

The package.json at the repository root is named `webcrack` and is marked private, which means the name in that file is not the thing you install. The tree is a pnpm workspace with `apps/` and `packages/` directories, and the published package is a workspace member inside `packages/`.

The root manifest is an orchestrator. Every script delegates: build, dev, lint, lint:fix, typecheck, format and format:check all run through turbo, which reads `turbo.json` and fans the task out across workspaces. The two exceptions are the test scripts, which call vitest directly rather than going through turbo.

The toolchain is pinned tightly. `packageManager` is set to `[email protected]`, an exact version rather than a range, and a `pnpm-lock.yaml` and `pnpm-workspace.yaml` are committed alongside it.

One detail worth flagging: `typescript` does not appear in the root devDependencies, even though the README states that all the code is written in TypeScript and a `typecheck` script exists. It must come from the workspace packages rather than from the manifest a newcomer reads first.

npm test watches, test:coverage runs once, and both coverage providers are installed

The two test scripts differ by one word. `test` is `vitest --no-isolate`, with no run subcommand, which is vitest in watch mode. `test:coverage` is `vitest run --coverage --no-isolate`, which runs once and collects coverage. So the short script a developer reaches for does not terminate, and the script that terminates is the one that also does the instrumented pass.

Both coverage backends are in the root devDependencies, `@vitest/coverage-istanbul` and `@vitest/coverage-v8`, each at 4.1.5, as is vitest itself. Which one runs is not decided in this file.

The isolation flag is the more interesting one. `--no-isolate` tells vitest not to give each test file its own environment, so the suite shares a process. For a tool that evaluates JavaScript inside isolated-vm, that keeps the sandbox from being torn down and rebuilt per file.

There are two vitest configuration files at the root, `vitest.config.js` and `vitest.workspace.json`, alongside a single `eslint.config.js` for the flat config format and a `.prettierrc` for formatting. Linting uses eslint 10 with a workspace eslint config pulled in as `workspace:*`, so the shared rules live in the monorepo rather than in the root.

The CLI gives you code on stdout; the API gives you code, bundle and a save method

Two installation lines cover the two surfaces:

bash
npm install -g webcrack@latest
bash
npm install webcrack@latest

The CLI examples show three shapes of use: a file argument, the same with a shell redirect to capture the output, and an `-o` flag pointing at a directory:

bash
webcrack input.js
webcrack input.js > output.js
webcrack bundle.js -o output-dir

The library form returns a richer object:

js
import fs from 'fs';
import { webcrack } from 'webcrack';

const input = fs.readFileSync('bundle.js', 'utf8');

const result = await webcrack(input);
console.log(result.code);
console.log(result.bundle);
await result.save('output-dir');

The difference that matters is the second console line. The API result carries the bundle as well as the deobfuscated code, and it has a `save` method that writes the unpacked output to a directory. The CLI's redirect form gives you code on standard output and nothing else, so anything that needs the bundle metadata has to go through the library.

The example is JavaScript rather than TypeScript, using a bare `fs` specifier instead of the `node:` prefixed form, in a package declared as ES modules.

Twelve weeks between two releases, then fourteen months

Three tags are visible. v2.15.0 is dated 2024-12-05, v2.15.1 is 2025-02-27, and v2.16.0 is 2026-04-25. The first gap is about twelve weeks and the second is about fourteen months, so the patch release came quickly after its minor and then the minor itself waited more than a year.

The last push to the default branch, master, is dated 2026-07-26, which is three months after the newest tag. Whatever is on the branch is therefore not in any release, and there is no nightly or prerelease channel listed to sit between the two.

For a tool people tend to pin, that shape matters more than the individual versions. The project moves in bursts, and the gap between a tag and the current state of the default branch is where unreleased behaviour lives.

A 179 word README, documentation on a Netlify subdomain, and four wallet addresses

The README is short enough to read in one pass. It states what the tool does, deobfuscating obfuscator.io output, unminifying, transpiling and unpacking webpack or browserify bundles to resemble the original source as far as possible, then gives the requirements, the two install commands, three CLI examples, one API example and a Donations section.

Documentation is not in the repository. Both the playground and the docs live on `webcrack.netlify.app`, with the docs under a path on the same subdomain, and the deployment badge points at that Netlify site. So a reader who wants the CLI reference or the API reference leaves the project, and the offline copy of what a tool does is six sentences long.

The Donations heading lists GitHub Sponsors and then four cryptocurrency addresses, for Ethereum, Bitcoin, Solana and Monero, each written out in full. Publishing receive-only addresses in a README is common practice and it does mean the file changes for reasons unrelated to the code.

One small inconsistency: the feature list claims all code is written in TypeScript, which is a claim about the implementation, while the API example shown to users is plain JavaScript.

Editorial conclusion

webcrack fits someone holding a minified or obfuscated bundle who needs readable source rather than a working copy of the same bytes, and the API is the better surface when the output has to be fed into something else, since it returns the bundle metadata alongside the code. Three things to check first. The runtime window is narrow and it is not yours to widen: Node 22 and 24 only, because the tool depends on isolated-vm and V8 ABI stability, and the README still carries a comment saying 26 will be added on release. Installing means npm in the consumer's project, since the root manifest is private and only the workspace member is published. And the test setup is unusual enough to be worth knowing before you trust a green run: both coverage providers are installed, two vitest configuration files sit at the root, and the suite runs with isolation disabled.

Frequently asked questions

What is webcrack?

A tool for reverse engineering JavaScript. It deobfuscates obfuscator.io output, unminifies, transpiles and unpacks webpack or browserify bundles to resemble the original source code as much as possible, and it is available both as a command line program and as a library.

How do I install webcrack?

For the command line, `npm install -g webcrack@latest`. To use it as a library in a project, `npm install webcrack@latest`. Either way it needs Node.js 22 or 24, and there is an online playground at webcrack.netlify.app that runs in the browser.

Which Node.js versions does webcrack support?

Node.js 22 and 24. The README explains that webcrack depends on isolated-vm, whose own documentation does not recommend odd-numbered Node releases because they frequently break ABI and API compatibility with V8. The requirements section also carries a comment saying 26 will be added on release.

Does webcrack unpack webpack bundles?

Yes. Unpacking webpack and browserify bundles is listed alongside deobfuscating obfuscator.io, unminifying and transpiling. The API example reads a bundle from disk and calls `result.save` to write the unpacked output into a directory.

Official sources

  1. j4k0xb/webcrack on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
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/j4k0xb-webcrack.svg)](https://hysenlabs.com/projects/j4k0xb-webcrack)