Skip to main content
Why do we want to obfuscate or deobfuscate code? Imagine you are in a red team engagement and are testing a web application’s client-side logic, login flows, e.g. Developers often obfuscate JavaScript code before shipping it to the browser, hoping to slow down anyone reading it. As an attacker (or defender reviewing your own app), you’ll frequently need to reverse that process to recover hardcoded API keys, hidden endpoints, or the real logic behind a client-side check, while on the other side, obfuscation itself is a useful technique for protecting payloads or implants from quick signature-based detection.

Obfuscation

There are multiple tools online to obfuscate JavaScript code. Let’s say we want to obfuscate a simple hello world program:
After obfuscation, the code can look like any of the following, depending on the technique used:
If you open your developer tools and enter any of the code variants above, you’ll get the same result: Hello from 0-x.dev

Use cases of obfuscation

There are many reasons why developers may consider obfuscating their code. One common reason is to hide the original code and its functions to prevent it from being reused or copied without the developer’s permission, making it more difficult to reverse engineer the code’s original functionality. Another reason is to provide a security layer when dealing with authentication or encryption to prevent attacks on vulnerabilities that may be found within the code. The most common usage of obfuscation, however, is for malicious actions. It is common for attackers and malicious actors to obfuscate their malicious scripts to prevent Intrusion Detection and Prevention systems from detecting their scripts.
But it must be noted that doing authentication or encryption on the client side is not recommended, as code is more prone to attacks this way.

Deobfuscation

There are multiple tools and techniques to deobfuscate JavaScript code.

Beautify the code

Obfuscated code is intentionally unformatted and very difficult to read. Start by formatting it with tools like your browser’s debugger, click { } in the Sources panel to pretty print it or an external tool like Prettier or Beautifier to make it more readable. This alone won’t reverse any actual obfuscation technique, but it turns an unreadable single-line slop into something you can scroll through and reason about before going further.

Decode with an online unpacker

You can find many good online tools to deobfuscate JavaScript code and turn it into something we can understand. One good tool is UnPacker, let’s try to deobfuscate an obfuscated code snippet: Unpacker Example

Identify and reverse any secondary encoding

Generally, the malicious payload inside the unpacked code will itself be encoded with various techniques like Base64, HEX, Caesar cipher, ROT13, and much more. You can use a tool like Cipher Identifier to identify the encoding based on that, you can revert it. CyberChef is the practical tool for actually doing the reversal once you know (or suspect) the encoding, its “Magic” operation will even attempt to auto-detect and chain multiple decodings for you. Quick manual checks are also often enough for a single layer:
Malicious actors also write their own custom encoding schemes, or chain multiple encoding techniques together (e.g. Base64 → ROT13 → HEX) specifically to defeat single-pass automated decoders, if the first decode attempt produces garbage rather than readable text or valid JavaScript, feed that output back through Cipher Identifier / CyberChef rather than assuming the payload isn’t encoded at all.

Bypassing anti-debugging (debugger flooding)

Self-defending obfuscated code sometimes inserts a debugger; statement in a loop that fires continuously once DevTools is open, making it practically unusable to step through. In Chrome DevTools, right-click the line containing the debugger statement in the Sources panel and choose “Never pause here”, then continue stepping through normally.

Tools

ToolBest for
UnPackerQuick browser-based unpacker
de4jsLegacy packers, JSFuck, JJEncode, and AAEncode, browser-based
synchronyjavascript-obfuscator / obfuscator.io output specifically (string arrays, control-flow flattening)
webcrackSame target as synchrony, plus unpacking bundled webpack/browserify code
humanifyAI-assisted variable/function renaming - makes the result readable, not just correct
CyberChefIdentifying and reversing secondary encoding (Base64, HEX, ROT13, Caesar, chained layers) via its “Magic” operation