Beautify — Manual

Complete reference for Beautify: flow, language detection, every option and its default, unpacking without eval, the toolbar, and what the browser stores.

Back to the overview: Beautify · Open the tool live: www.jpkc.com/tools/beautify/

This manual describes Beautify in full: what happens when you format, what each option does, how unpacking works, and what limits apply. The tool's interface is in English, so the option and button labels below are simply the real ones you'll see in the tool.

Input and flow

Beautify is a single-field tool: options on the left, the code editor on the right. You always work in the same editor — the formatted output replaces your input in place. The flow:

  1. Paste code — type/paste directly into the editor, or load a file via Upload. While the editor is empty, it shows the hint "Paste your code here (JavaScript, JSON, CSS or HTML), then click Beautify or press Ctrl+Enter."
  2. Optionally pick a language and options — by default the tool detects the language automatically.
  3. Click Beautify (toolbar or footer) or press Ctrl+Enter.
  4. Take the result — Copy to the clipboard or Download as a file.

In the code editor, formatting is an undo step of its own: press Ctrl+Z right afterward and exactly the unformatted code is back — even if you pasted it a moment before.

One thing to note: as soon as you change one of the five dropdowns in the Formatting card, the tool reformats automatically. That doesn't apply to the checkboxes in the Options card or to the language choice — after changing those, click Beautify once (or press Ctrl+Enter).

All formatting and unpacking runs client-side in the browser (see Architecture and privacy). It's powered by the js-beautify library (JavaScript, CSS, HTML) by Einar Lielmanis and contributors; the editor is ACE with the Dracula color scheme.

Choosing or detecting the language

The language dropdown in the toolbar sets which language the code is formatted as:

  • Auto-detect (default) — the tool guesses the language from the start of the content (leading whitespace and a byte order mark don't count). The checks run in this order:
    1. If the text starts with < (but not with the HTML comment <!--), it's treated as HTML — which covers XML and SVG too.
    2. If it starts with { or [ and is valid JSON, it goes to the JavaScript formatter.
    3. Unambiguous JavaScript openings mean JavaScript: a // comment, a comment such as /* eslint …, /* global …, or /* jshint …, keywords like function, var, let, const, if, for, class, import, export, async, or return, an opening parenthesis, $( or jQuery, and a name followed by an assignment or a call (x = …, init(…) — which also catches JSONP such as callback({…})).
    4. A CSS at-rule at the start means CSS: @import, @media, @charset, @font-face, @keyframes, @supports, @layer, @page, @namespace, @container, @property, or @tailwind.
    5. It's also CSS if the text starts with a selector followed by a block of property: value declarations. Parentheses or = in the selector rule CSS out (except inside pseudo-classes such as :not(…) and attribute selectors […]), as does a selector ending in : (a JavaScript label).
    6. Everything else is treated as JavaScript.
  • JavaScript — forces the JS formatter (also suitable for JSON/JSONP).
  • CSS — forces the CSS formatter.
  • HTML — forces the HTML formatter.

If detection gets it wrong (for instance because a CSS fragment starts in the middle of a rule block, or an HTML snippet starts with <!--), set the language by hand. The choice also drives the editor's syntax highlighting and the file extension on download. The tool remembers a language picked in the dropdown across reloads, so a fixed choice also applies to the next code you paste — until you switch back to Auto-detect. On Upload, the tool fixes the language based on the file extension. That choice only lasts until a reload: it isn't stored unless you change an option afterward.

The formatting options

These five dropdowns in the Formatting card control the basic layout. Every change reformats the editor content immediately. The defaults follow common conventions: 4 spaces, Allow 2 for blank lines (in JavaScript and CSS that keeps at most one blank line in a row), no automatic wrapping of long lines, opening brace on the line of the control statement. Once you've changed the options, your stored values take precedence (see Code and options are remembered).

Indentation

Determines what indentation uses:

  • Tab character — one real tab character per level.
  • 2 spaces, 3 spaces, 4 spaces (default), 8 spaces — that many spaces per level.

Newlines

Controls how many consecutive line breaks from the input are kept. The value counts line breaks, not blank lines, and its effect depends on the language:

  • Remove all extra — keeps no blank lines from the input.
  • Allow 1, Allow 2 (default), Allow 5, Allow 10 — at most that many line breaks in a row. In JavaScript and CSS this leaves at most N−1 blank lines: Allow 1 removes all blank lines (just like Remove all extra), Allow 2 keeps one, Allow 5 keeps four. In HTML the value equals the number of blank lines: Allow 2 keeps two there.
  • Unlimited — uncapped only in JavaScript. In CSS and HTML this setting instead removes all blank lines from the input.

Between two CSS rules the formatter always puts at least one blank line, regardless of this setting.

Line Wrap

Sets the maximum line length at which wrapping happens:

  • No wrap (default) — no automatic line breaks.
  • 40 chars, 70 chars, 80 chars, 110 chars, 120 chars, 160 chars — wraps lines at the chosen character count (where the language allows it).

Brace Style

Determines where curly braces go (mostly relevant for JavaScript):

  • With control statement (default) — opening brace on the same line as the control statement (if (x) {).
  • Inline or with control — blocks that are already on one line in the input keep their braces on that line; all others as above. Only blocks with a single statement (if (a) { b() }) and object literals ({ a: 1, b: 2 }) stay entirely on one line. If a block holds several statements, the formatter moves each further statement to its own line. With Line Wrap set, it also wraps long inline blocks.
  • On own line — opening brace on its own line.
  • End on own line — the opening brace stays on the statement line as with With control statement, but the closing brace sits on its own line, so else, catch, and finally start a new line (} with else { below it).
  • Keep as-is — the existing brace style is left untouched.

This choice works together with the Preserve inline braces checkbox (see below).

HTML Scripts

Controls the indentation of <script> contents inside HTML:

  • Keep tag indent (default) — script contents keep the surrounding tag's indentation.
  • Add one level — one extra indentation level.
  • Separate — script contents start at column 0, regardless of how deeply the <script> tag is indented.

The additional options

The Options card holds eleven checkboxes for finer details. Out of the box, only Space before conditional is checked; all the others are off. A changed checkbox is saved, but it doesn't reformat on its own — click Beautify afterward.

Detect packers

Enables unpacking/deobfuscation before formatting — applies to JavaScript only. When checked, the code first runs through an unpacker chain and is then formatted. Details and limits in Unpacking and deobfuscation.

End with newline

Appends a trailing newline at the end of the output.

Support e4x/jsx

Lets the JS formatter recognize E4X / JSX syntax (XML literals in JavaScript) as such. Without the option the formatter doesn't stop; it silently tears JSX apart: <div class="a"> becomes < div class = "a" >. The option is off by default. Turn it on before you load a .jsx or .tsx file via Upload, because the upload formats right away.

Comma-first style

Places commas at the start of the line instead of the end (comma-first style).

Preserve inline braces

Augments the chosen Brace Style so brace blocks that are already inline are allowed to stay inline — with the same limits as Inline or with control.

Keep array indent

Preserves the existing indentation inside array literals instead of re-aligning it.

Break chained methods

Breaks chained method calls (a.b().c().d()) onto multiple lines.

Space before conditional

Inserts a space before a conditional's parenthesis (if ( instead of if(). The only checkbox that's on by default.

Unescape strings

Converts escaped characters in strings (such as \x41 sequences) back into readable characters — handy when cleaning up obfuscated strings.

JSLint-happy

Formats according to JSLint's stricter conventions (e.g. function spacing).

Indent head/body

In HTML, indents the contents of <head> and <body> an extra level.

Unpacking and deobfuscation

With Detect packers enabled, JavaScript runs through an unpacker chain before formatting. The tool first strips leading comments (/* … */ and // …) and puts them back in front of the result later, then tests the code against the known packing schemes and unpacks recursively as long as something keeps changing. Two unpackers are active:

  • P.A.C.K.E.R. — the widespread eval(function(p,a,c,k,e,d){…}) format (Dean Edwards' Packer). The unpacker reads the payload, radix, word count, and the |-separated symbol table from the packed call and substitutes the words back in. Radixes 2 to 36, 37 to 62, and 95 are supported; several packed blocks in one file are decoded one by one.
  • URL-encoded — code obscured via URL encoding (%xx). It's detected when the text contains not a single space and either %2 or more than three % characters occur.

The packed code is never executed in the process. The P.A.C.K.E.R. unpacker only decodes the arguments of the call — unlike classic unpackers, which run the code through eval and capture the result. So you can safely unpack even suspicious code.

To set expectations honestly:

  • Unpacking is pattern-based, not AI-powered. It reverses known, reversible packing schemes — nothing more.
  • "Real" obfuscators that rename symbols, scramble control flow, or build string arrays cannot be turned back into the original code. Such code is merely formatted cleanly (and made more legible with Unescape strings where applicable), but not logically reconstructed.
  • Without the box checked, no unpacking takes place — the code is only formatted.

Editor toolbar

The toolbar at the top right of the editor block offers these actions.

Beautify

Starts formatting. The button exists twice (toolbar with a wand icon, and a large Beautify (Ctrl+Enter) button in the footer) — both do the same thing. Below the large button, a hint points to the Compiler tool in case you want to minify or compile SCSS.

Upload

Opens a file dialog and loads a file into the editor. The dialog offers .js, .css, .html, .htm, .json, .jsx, .ts, and .tsx. The file is read locally (no server upload), the language is fixed from the file extension, and the contents are formatted automatically; a "Loaded: …" message confirms it. Extensions like .jsx, .ts, .tsx, and .json are treated as JavaScript, .scss/.less as CSS, .htm/.xml as HTML. The dialog only shows .scss, .less, and .xml files once you switch its file filter to all files, though. For any other extension, the language choice stays as it was. Because the file is formatted right away with the current options, turn on Support e4x/jsx before loading .jsx/.tsx. In the code editor, the first Ctrl+Z undoes the formatting (leaving the file content as it was), and a second Ctrl+Z restores the state before loading.

Download

Saves the current editor content as a file — Ctrl+S in the editor works too. The filename follows the selected or detected language (beautified.js, beautified.css, or beautified.html); JSON therefore ends up as beautified.js, and you adjust the name when saving. If the editor is empty, "Nothing to download." appears.

Copy

Copies the entire editor content to the clipboard (not just a selection). If the editor is empty, a notice appears.

Clear

Empties the editor and resets the language to Auto-detect. If there's code in the editor, the tool asks first ("Clear the editor? (Ctrl+Z undoes it.)"). In the code editor, clearing is an undo step of its own — Ctrl+Z brings the code back. Clearing the editor also clears the code stored in the browser.

Toggle editor

A button switches between the ACE code editor (syntax highlighting, line numbers, soft wrap) and a plain text field ("Switch to simple textarea" or "Switch to code editor"). You can also reach the text-field variant directly via the URL parameter ?without-editor; the older parameter ?without-codemirror still works. Handy for very large files or when the editor gets in the way. The stored code and options are available in both variants.

Keyboard shortcuts

  • Ctrl+Enter — formats the current editor content exactly once (same as clicking Beautify). In the ACE editor on a Mac, Cmd+Enter works too.
  • Ctrl+S — downloads the editor content (like Download); Cmd+S on a Mac. ACE editor only, not in the plain text field.
  • Ctrl+Z — undoes the last step in the ACE editor. Formatting, loading a file, and Clear are each a step of their own, so you get back to exactly the previous state.

Code and options are remembered

Beautify keeps two things in your browser's local storage (localStorage):

  • the editor content — saved shortly after every change,
  • all options — the five dropdowns, the eleven checkboxes, and the language choice.

After a reload, both are back. The restored code doesn't count as an edit: Ctrl+Z won't empty the editor. Stored options take precedence over the defaults. There's no history of several versions, only the latest one. If the browser doesn't allow storage (in some private windows, for example), the tool works as usual but forgets everything on reload.

Architecture and privacy

Beautify is a purely client-side tool. The PHP page only serves the markup; the actual work — formatting, unpacking, language detection, file reading, copying, downloading, saving — is done by JavaScript libraries in your browser. There's no proxy, no API, and no requests to a server:

  • js-beautify (modules for JavaScript, CSS, and HTML) handles formatting.
  • The unpackers (P.A.C.K.E.R., URL-encoded) also run locally and don't execute the packed code.
  • ACE provides the editor.

This gives the privacy benefit: your code is not sent to any server. Uploaded files are read locally too. The tool is therefore safe for proprietary, internal, or confidential source code. Just keep in mind that the latest editor content stays stored in the browser (see Code and options are remembered) — on a shared or someone else's computer, empty the editor with Clear when you're done.

Limits

  • Three languages. It formats JavaScript, CSS, and HTML. JSON/JSONP ride along through the JavaScript formatter (valid JSON is valid JS) — there is no dedicated JSON validation here.
  • TypeScript isn't TypeScript-specific. .ts/.tsx are treated as JavaScript; TS-specific syntax isn't understood specially and may format imperfectly. JSX in .jsx/.tsx only survives formatting with Support e4x/jsx turned on.
  • Unpacking is JavaScript-only and limited to two known schemes (P.A.C.K.E.R. and URL encoding) — see Unpacking and deobfuscation. Other formats such as MyObfuscate or JavaScript Obfuscator aren't unpacked, and symbol-renaming obfuscators are not reconstructed.
  • One editor for input and output. The result replaces the input; there's no side-by-side before/after view — use Ctrl+Z for that, or the Compiler tool with its separate fields.
  • No AI involved. There's no model or LLM component; "deobfuscate" here means the pattern-based unpacking exclusively.

For the intro and the target audiences, see the overview page. Concrete workflows are in the examples, strategy and pitfalls in the tips & tricks. You can try it all directly in the tool.