Skip to content
FormatKit

Free online JavaScript formatter and beautifier

JavaScript formatter that moves whitespace only

Paste a minified bundle or a wall of hand-mangled code and it comes back on lines you can read: one statement per line, blocks indented, chained .then calls split apart, callbacks kept attached to the call that owns them. Free, no account, nothing uploaded. The guarantee underneath it is narrow and worth stating — only whitespace moves, so regex literals, template contents and JSX arrive character for character and no semicolon is ever added or removed. Up to 5 MB; a 185 KB framework chunk unpacks to 11,498 lines in about 50 ms.

  • 100% free
  • No signup
  • Up to 5 MB
  • Regex-safe
  • No semicolons touched
Unpacked JavaScript

The readable version appears here.

Paste a script, drop a file, or press Ctrl+V anywhere on this page.

How to format JavaScript

Paste, pick a style, read the count.

  1. Give it the script

    Paste into the left pane — the ⌘V or Ctrl+V shortcut works without clicking into the box first — or open a .js, .mjs, .cjs or .jsx file. One line of 180,000 characters is a perfectly normal input here; so is a half-written module you are trying to see the shape of. Sample bundle loads a small mangled file if you just want to watch it work.

  2. Choose how it should look

    Indent by 2 spaces, 4 spaces or a tab. Braces on the same line as the statement head or the next line down. Quotes left alone, pushed to single, or pushed to double — a literal that contains a quote character or a backslash keeps whichever it already had, since swapping those would mean re-escaping the contents. Wrap at 80, 100 or 120 tells the printer when an argument list has earned its own lines.

  3. Check the count, then take it

    The line underneath reports tokens, functions found, comments kept and how deep the nesting goes, plus the line count in and out. Copy takes the whole file, Download writes it out as .js, and both hand over everything even though the preview stops painting after 5,000 lines.

Technical specifications

What can changeWhitespace between tokens, and quote characters if you switch the Quotes control on. Nothing else moves: no token is added, removed or reordered, and no parenthesis is inserted
Tokeniser58 punctuators, regex-versus-division resolved from the preceding token plus a stack of control-statement parens, nested template literals, private #fields, optional chaining, ??=, ||= and &&=
LayoutStatements one per line, blocks indented by 2, 4 or a tab, braces on the same line or the next, chained .then/.map calls split with continuation indent, callbacks hugged onto the call that owns them, argument lists broken when the line would pass 80, 100 or 120 columns
Never rewrittenString bodies, template literal contents including their newlines, regex patterns and flags, JSX regions, numeric literals, and every comment — kept in place, trailing ones on their own line's end
Semicolon safetyNo semicolon is inserted or removed, and the newline after return, throw, break, continue and yield is preserved, because automatic semicolon insertion makes those five lines load-bearing
Not supportedTypeScript type syntax is spaced as ordinary operators, so Array<number> comes back as Array < number >; JSX is preserved but not indented internally; expressions are not reflowed to a column width; nothing is linted, validated or executed
When it declinesAn unterminated string, template or /* comment, an unexpected character, or a bracket that never closes returns the file byte for byte with a note saying which — rearranging text the reader cannot follow is how a formatter corrupts a file
ThroughputA 185 KB minified framework bundle unpacks to 11,498 lines in about 50 ms; 58 KB of ordinary source takes around 10 ms. 5 MB per file, the preview draws the first 5,000 lines, Copy and Download hand over all of it

Frequently asked questions

Can this turn a minified bundle back into readable source?

It can give you the layout back, and no tool without a source map can give you the names. Run a 185 KB framework chunk through it and you get 11,498 indented lines in about 50 ms, with every function body, branch and chained call where you can see it — which is usually enough to answer why is this throwing. What you will still be reading is e, t, n and r, because the build step that shortened those identifiers threw the originals away and only the .map file remembers them. If your bundle ships with one, your browser devtools will do a better job than any text box; if it does not, this is what is left.

Will it mangle my regular expressions?

No, and avoiding that is the hardest single thing about reading JavaScript. A forward slash starts a regex in one position and divides in another, so a/b/c is arithmetic while the same characters after an equals sign are a pattern — the language genuinely cannot be tokenised without tracking what came before. The reader keeps that context: it looks at the previous significant token, keeps a stack of the parentheses that belong to if, while and for heads, and refuses to run a pattern scan past the end of a line. Whatever it decides is a regex is copied out character for character, flags included.

What does it do with JSX?

It carries each JSX region across untouched, on the line where the surrounding statement leaves it. Element markup is scanned as one opaque unit from the opening angle bracket to its matching close, so attributes, expression containers and text are exactly as you wrote them — but they are not re-indented internally, and a component whose render is one long tree will come back as one long line. If the reader cannot find a coherent element it falls back to treating the angle bracket as a less-than operator, which is the right guess for ordinary code and the reason plain arithmetic never gets mistaken for markup.

Does it understand TypeScript?

Not as types, and the output shows it. Annotations survive because every character survives, but the printer sees Array<number> as three tokens with two comparison operators in the middle and spaces them accordingly, which is legal TypeScript and ugly TypeScript. Decorators stay on the line with the class they decorate. If you are formatting .ts or .tsx as part of your normal workflow, an editor plugin that parses the type grammar will treat you better; this is for the moment when you have a lump of unfamiliar JavaScript and no toolchain in front of you.

Will it add or remove semicolons?

Neither — not one is inserted, and not one is deleted. That is a safety decision rather than a stylistic one, because JavaScript ends statements at newlines under rules that are easy to get wrong: a return followed by a line break returns undefined no matter what sits on the next line, and the same applies to throw, break, continue and yield. The printer keeps the newline after all five, so a value can never be dragged up onto a return that was meant to be bare. Whether you write semicolons is left exactly as you decided.

Are my strings, template literals and comments safe?

All three come through byte for byte. The inside of a template literal is content, including the newlines that a tagged template may be counting on, so nothing indented, re-wrapped or re-quoted ever happens in there — the embedded ${…} expressions are left as written too. String bodies are only ever re-quoted if you ask for it and the literal has no quote character and no backslash inside. Every comment is kept: a trailing one stays at the end of its line, a block comment keeps its internal line breaks, and the count under the tool tells you how many came through.

How is this different from Prettier?

Prettier throws your file away and prints a new one from the syntax tree; this re-spaces the tokens of the file you pasted. That difference decides everything else. Prettier can reflow a long expression across lines intelligently, normalise your parentheses and reprint JSX properly, and it needs a valid parse of the whole file to do any of it. This one cannot reflow an arbitrary expression — but it will still lay out a file with a syntax error further down, and it can promise that the only characters that moved were whitespace. Both are useful; they are useful at different moments.

About reading JavaScript you did not write

JavaScript is unusually hostile to anything that tries to read it without parsing it, and one character is responsible for most of that. A forward slash divides in one position and opens a regular expression in another, and which one it is depends on the token before it: after an identifier or a closing parenthesis it is division, after =, ( or return it is a pattern. Get it backwards and the rest of the file is read as a string, which is how a naive beautifier turns a working script into a scrambled one. The same problem shows up with the angle bracket once JSX is in play, and with the backtick, whose ${…} holes can contain another template containing another hole.

The second hazard is that line breaks carry meaning. Automatic semicolon insertion ends a statement at a newline whenever continuing would be a syntax error, and five keywords — return, throw, break, continue and yield — end their statement at a newline even when continuing would parse perfectly. A formatter that joins those lines has not restyled your function, it has changed what the function returns. Spacing can be dangerous in the other direction too: remove the space in - -a and you have written a decrement. Both cases are guarded here rather than assumed away.

What that buys you is a narrow promise instead of a broad one. This is not a code formatter in the Prettier sense — it will not reprint your expressions from a syntax tree, and it deliberately leaves JSX and TypeScript type syntax where it found them. It is the tool for the fifteen minutes when you have someone else’s bundle open, no source map, and a question. When you are done reading, the same file goes back the other way through the JavaScript minifier, and two versions of the same function line up properly in the code diff once both have been formatted the same way.

Where your script is processed

The tokeniser and the printer are JavaScript running in this tab, so your file is not uploaded and no part of it is evaluated — a script pasted here is text being re-spaced, never code being run. That matters when the bundle you are inspecting came from a client site or carries an API key someone left in it.