What is a JavaScript formatter?
JavaScript arrives in unreadable shapes from every direction: minified bundles with a whole library on one line, snippets copied out of browser consoles, code generated by other tools, a colleague's file where the indentation changes philosophy every ten lines. A JavaScript formatter (or beautifier) rewrites that code with one consistent layout — every block indented by the same step, every function and loop opened up onto its own lines — so the structure of the program is visible again and the logic can be reviewed, diffed and debugged.
A formatter is only trustworthy if it understands what it is
moving. JavaScript is full of text that looks like structure but
is not — braces inside strings, a } in a comment, a
regular expression that a naive tool reads as division — and full
of places where a line break is not merely cosmetic, because
automatic semicolon insertion gives some newlines a meaning. That
is why this tool parses your code before it formats
it, with a real ECMAScript parser: the layout is computed
from the program's actual grammar, not from counting braces.
How to use this tool
- Paste your JavaScript into the box above (or press Load sample to see a worked example). You can also upload a .js file or drop one onto the box — the file is read in your browser and never sent anywhere.
- Choose an indent — 2 spaces is the community default; 4 spaces and tabs are one click away.
- Press Format. If the code parses, you get the reformatted version and a line count. If it does not, you get the line and column of the first syntax problem — fix that one and format again.
- Tick Auto-format as I type if you would rather not press the button: the result updates as you edit (very large inputs are still formatted on demand, to keep typing smooth). While the code is mid-edit and does not yet parse, the message line says so and your last good result stays on screen.
- Use Copy result or Download result to take the formatted code with you. Your input above is never modified — the result is a separate copy, and nothing you paste is ever executed.
Syntax checked first — and why that protects your code
Before formatting, the tool parses the input twice over: once as
an ES module, so import, export and
top-level await are accepted, and once as a classic
script, so script-only constructs are accepted too. If neither
grammar accepts the text, you get the more plausible error — the
parse that got further into your code — with its exact line and
column. Only code that parses under one of the two grammars is
ever reformatted.
That gate is what makes the layout safe to apply. A parser knows
that the slashes in let rate = total / count are
division while the slashes in /^https?:\/\// delimit
a regular expression; that a template literal can contain a whole
nested expression without its braces becoming blocks; and that a
return followed by a line break is a statement with
no value, so the break must be kept. Text-level beautifiers get
these wrong in ways that silently change behaviour. This one
cannot reformat what it could not parse, and says so instead.
What formatting never changes
Layout only — that is the whole contract. Indentation follows the option you chose; statements and expressions are broken onto lines at their grammatical boundaries; spacing around operators and after keywords is made uniform. Everything else is your code, untouched: no renaming, no reordering, no added or removed semicolons, no quote-style conversion. String, template literal, regular expression and comment contents are carried across byte-for-byte. Blank lines survive, in moderation — up to two consecutive ones, as authored — so the paragraphing of your code survives the trip.
Examples
This compressed module:
export function cartTotal(items){let total=0;for(const item of items){total+=item.price*item.qty;}return total.toFixed(2);} formats into:
export function cartTotal(items) {
let total = 0;
for (const item of items) {
total += item.price * item.qty;
}
return total.toFixed(2);
} And this snippet — note the unclosed function body — is reported at the exact position where the parser runs out of input, instead of being "formatted" into something that looks plausible and runs differently:
function total(items) {
let sum = 0;
for (const item of items) {
sum += item.price; Formatting is not minifying, and not linting
Three tools, three different promises. A minifier makes code smaller for delivery — stripping whitespace, renaming variables — and leaves it less readable on purpose. A linter has opinions: it flags unused variables, inconsistent style and probable bugs, and expects you to argue with it. A formatter only rearranges whitespace so the code you already have reads consistently. This page is the third one, and it will pass code a linter would reject with flying colours — ugly logic, beautifully laid out — as long as it is syntactically valid JavaScript.