JavaScript Deobfuscator

Paste obfuscated JS and get clean, readable output instantly. AST-based transforms. No install. No account.

Input — Obfuscated JS0 chars
Output — Clean JS

Why Use JS Deobfuscator?

Built for developers who need fast, accurate JavaScript deobfuscation.

AST-Based Deobfuscation

Parses code into an Abstract Syntax Tree for deep semantic transforms — not just string replacements.

Fast Results

Typical scripts come back in about a second, files up to 1MB in a few seconds. No setup, no install.

Privacy First

Beautify and Unminify run entirely in your browser. Deobfuscation runs in an isolated sandbox, and code is never stored.

Monaco Editor

VS Code's editor engine provides full syntax highlighting for both input and output panels.

Multiple Modes

Auto-detect, deobfuscate, beautify-only, or unminify — pick what you need.

Export Result

Copy to clipboard or download the cleaned JS file with a single click.

Working with obfuscator.io output? Read how to deobfuscate obfuscator.io code, with a real before-and-after example from this tool.

What It Deobfuscates

Real input and output from this tool. Nothing is edited, except where an excerpt is marked.

obfuscator.io string arrays, including rc4

Runs the obfuscator’s own array rotation and base64/rc4 decoder in an isolated sandbox, then replaces every lookup with its real string.

Before — excerpt of 154 formatted lines
function a0_0x5c04() {
  const _0x1e9dd0 = [
    "WOFcT8k3",
    "n8k+W7Dzea",
    // … 25 more rc4-encrypted strings
  ];
  // …
}
const a0_0x4dbdcb = a0_0x41a2;
(function (_0x5322e4, _0x95473a) {
  const _0x34a4fe = a0_0x41a2,
    _0x4d2f6d = _0x5322e4();
  while (!![]) {
    try {
      const _0x26d243 =
        -parseInt(_0x34a4fe(0x175, "Bs^*")) / 0x1 +
        parseInt(_0x34a4fe(0x183, "EDJ&")) / 0x2 +
        (parseInt(_0x34a4fe(0x182, "r)UA")) / 0x3) *
          (parseInt(_0x34a4fe(0x181, "u3o2")) / 0x4) +
        (parseInt(_0x34a4fe(0x16f, "QalO")) / 0x5) *
          (-parseInt(_0x34a4fe(0x169, "&eq&")) / 0x6) +
        (-parseInt(_0x34a4fe(0x16c, "Wdop")) / 0x7) *
          (-parseInt(_0x34a4fe(0x17c, "r5kr")) / 0x8) +
        (parseInt(_0x34a4fe(0x17d, "49!a")) / 0x9) *
          (-parseInt(_0x34a4fe(0x16a, "MSSt")) / 0xa) +
        -parseInt(_0x34a4fe(0x172, "49!a")) / 0xb;
      if (_0x26d243 === _0x95473a) break;
      else _0x4d2f6d["push"](_0x4d2f6d["shift"]());
    } catch (_0x1280de) {
      _0x4d2f6d["push"](_0x4d2f6d["shift"]());
    }
  }
})(a0_0x5c04, 0xdc125);
const user = {
  name: a0_0x4dbdcb(0x16e, "mFUm"),
  role: a0_0x4dbdcb(0x174, "1P)1"),
};
// … rc4 decoder a0_0x41a2 (87 lines)
console[a0_0x4dbdcb(0x173, "u3o2")](
  a0_0x4dbdcb(0x171, "%3lD") + user[a0_0x4dbdcb(0x17f, "4l2f")],
);
After — 5 string references resolved
const user = {
  name: "Ada",
  role: "admin",
};
console.log("Welcome, " + user.name);

Hex and unicode escapes

Decodes \x and \u escape sequences into readable text.

Before
var greeting = "\x48\x65\x6c\x6c\x6f\x2c\x20\u0057\u006f\u0072\u006c\u0064";
After
var greeting = "Hello, World";

Proxy functions

Inlines the small wrapper functions obfuscators use to hide calls and operators, only where the result provably behaves the same. The unused wrappers are left in place.

Before
function _0x5c1f(_0x2a, _0x3b) { return _0x2a(_0x3b); }
function _0x1d9e(_0x4c, _0x5d) { return _0x4c + _0x5d; }
_0x5c1f(alert, _0x1d9e("Hi, ", name));
After — 2 proxy calls inlined
function _0x5c1f(_0x2a, _0x3b) {
  return _0x2a(_0x3b);
}
function _0x1d9e(_0x4c, _0x5d) {
  return _0x4c + _0x5d;
}
alert("Hi, " + name);

Constant expressions

Folds hex arithmetic, turns !0 and !1 back into true and false, and simplifies obj["prop"] to obj.prop.

Before
var timeout = 0x2 * 0x109e + -0xc * -0x16a + -0x1f40;
var enabled = !0x0, debug = !0x1;
window["config"]["retries"] = 0x3;
After
var timeout = 4852;
var enabled = true,
  debug = false;
window.config.retries = 3;

How It Works

  1. Parse. Babel parses your code into an abstract syntax tree (AST), so every change is made on real syntax, not text.
  2. Resolve string arrays. The tool finds the string array, the functions that read it and the rotation code, runs that setup in a QuickJS WebAssembly sandbox with time and memory limits, and replaces every lookup with its string.
  3. Simplify. It decodes escapes, folds constant expressions, simplifies property access and inlines proxy functions.
  4. Format. The result is formatted with Prettier in your browser.

Limits: original variable names can't be restored (they aren't in the file anymore), and control-flow flattening and eval-packing aren't undone yet. Files up to 1MB.

Frequently Asked Questions

Everything you need to know about JavaScript deobfuscation.

What is a JavaScript deobfuscator?
A JavaScript deobfuscator is a tool that reverses techniques used to make code intentionally hard to read. It transforms obfuscated or minified JS code into clean, human-readable code.
How does this JS deobfuscator work?
It parses your JavaScript into an Abstract Syntax Tree (AST) and applies transformations: it resolves string arrays (running the obfuscator's own decoding in an isolated sandbox), decodes hex and unicode escapes, folds constant expressions, simplifies obj["prop"] access, and inlines small proxy functions. The result is then formatted with Prettier in your browser.
Is it safe to paste my code here?
Yes. Beautify and Unminify run in your browser, so that code isn't uploaded (unless your browser can't run the formatter, in which case it falls back to our server). For deobfuscation, code is sent over HTTPS and processed in memory; any code the obfuscator needs to run (such as its string decoder) executes in an isolated sandbox with no access to the server. Code is never stored, logged, or shared.
Can it deobfuscate all types of obfuscation?
No tool can. It handles the most common patterns: obfuscator.io string arrays (including rotated, base64- and rc4-encoded arrays), hex and unicode escapes, constant expressions, and proxy functions. It can't restore original variable names (they aren't in the file anymore), and it doesn't undo control-flow flattening or eval-packing yet — heavily customized obfuscation may give partial results.
What is the file size limit?
Files up to 1MB are supported. For larger files, consider splitting them or using a local CLI tool like webcrack or REstringer.
Is this tool free?
Yes, JSDeobfuscator.com is completely free with no account required.