How to pack and unpack JavaScript

Packing rewrites JavaScript into the eval(function(p,a,c,k,e,d){…}(…)) wrapper used by the classic Base62 packer: every word becomes an index into a dictionary of the sorted unique words, and the payload keeps the source text with quotes, backslashes and line breaks escaped. Unpacking evaluates such a payload in this page and prints the JavaScript it produces.

This is obfuscation, not encryption, and unpacking runs the code you paste, so keep it to scripts you trust. Both buttons work on the text in the box only — nothing is uploaded and the page sends no request while packing or unpacking.

  1. Paste the JavaScript in the box above, or paste a packed eval(function(p,a,c,k,e,d){…}) payload if you want to read one back.
  2. Press Pack JavaScript. The result box shows the single-line wrapper with the packed payload and the word dictionary in its argument list.
  3. Take the wrapper with the Copy chip, or press Clear to empty both boxes.
  4. To go the other way, paste a packed payload and press Unpack. The page evaluates it and prints the source it returns.
  5. If the input has no eval, cannot be evaluated, or does not evaluate to a string, the box shows a tooltip with the reason instead of an empty result.

What the two buttons do

The wrapper the packer writes

Every word token — letters, digits, underscore and $ — is replaced by a base-62 index (0-9, then a-z, then A-Z) and the unique words are sorted into the dictionary that travels with the payload. The payload itself is a single-quoted string, so quotes, backslashes and line breaks are escaped instead of deleted: a // comment stays a comment, and a statement without a semicolon keeps its line break.

The output is ordinary JavaScript: paste it into a page and it runs, and any unpacker that evaluates the wrapper returns the original source. Round trips verified on this build: escaped quotes, regular expressions with backslashes, template literals, block comments, files without semicolons, CJK text, $ identifiers, JSON text and dictionaries of more than 60 words all came back byte for byte.

Reading a payload back

Unpack accepts any payload that evaluates to a string, including packs written by the same wrapper elsewhere. The result box is read-only and syntax highlighted, and the copy chip copies it as text.

Unpacking evaluates the input inside this page — that is what the eval() wrapper is for — so only unpack code you trust. A payload that throws, or that returns something other than JavaScript text, is reported with a message instead of an empty box.

Sizes and timings measured

Packing collapses the source into one line and usually makes repeated code smaller: 2.7 KB of handler functions packed to 1.8 KB, 16.7 KB to 11 KB and 85 KB to 55 KB, with packing between 1 and 5 ms and unpacking between 0.3 and 3 ms in Chrome.

Because the wrapper is reversible by design, treat the result as obfuscation against casual reading, not as protection for a secret: anyone can paste it back here, or into any other unpacker, and get the source.

Recent tools: