Skip to main content

Python Code Formatter

Clean up Python source: normalize existing indentation to a consistent width, tidy comma/operator spacing, collapse long blank-line runs, and trim trailing whitespace — without touching triple-quoted strings, f-strings, or comments.

Input

Drop a file or browse
One file · text
Or

Formatting Options

Output

Formatted Code
 
Was this helpful?

Guides

Paste messy Python and get back cleaner, more consistent source — instantly, in your browser. The Python Code Formatter normalizes indentation to a consistent width, tidies spacing around commas and operators, collapses long runs of blank lines, and trims trailing whitespace, without touching the content of strings, f-strings, or comments.

An important honesty note

This tool is a whitespace/style normalizer, not a full PEP 8 or Black-equivalent formatter. In a brace-based language (Java, PHP, JavaScript...), a formatter can safely re-derive indentation from scratch by counting {/} pairs — brace depth is block structure. Python has no braces: indentation itself is the block structure. Rebuilding it correctly from nothing needs a real parser — get it wrong and you don't just misalign a line, you can change which lines belong to which block.

So instead of guessing new block structure, this tool takes the indentation you already wrote and remaps it onto a consistent depth, the same "INDENT/DEDENT" technique CPython's own tokenizer uses: it walks your existing indentation as a stack of levels and re-emits each level at your chosen width, even if the file mixes 2-space, 4-space, and tab indentation, or grows each nested level unevenly. It never invents an indent level that wasn't already present.

How to use it

  1. Paste your Python source, or upload a .py file.
  2. Pick your Indent width (2, 4, or 8 spaces, or tabs — 4 spaces is the PEP 8 default).
  3. Toggle Normalize comma & operator spacing and Normalize blank lines to taste.
  4. Copy the result, or download it as formatted.py.

Formatting runs automatically as you type or change an option.

What it normalizes

  • Indentation, remapped as described above. Lines inside an open (/[/{ or after a trailing \ continuation are left exactly as authored — that's your own alignment choice, not a block boundary.
  • Comma spacing — no space before, exactly one space after.
  • Operator spacing — an unambiguous set gets forced single-space padding: ==, !=, <=, >=, ->, :=, and the augmented-assignment operators (+=, -=, *=, /=, //=, %=, **=, &=, |=, ^=, >>=, <<=).
  • Blank lines — runs of 3+ collapse to 2.
  • Trailing whitespace — stripped from every code line.

What it deliberately leaves alone

  • A bare =. Telling an assignment (x = 1, wants spaces) from a keyword argument or default (f(x=1), must stay tight) requires knowing whether you're inside a call or def signature — exactly the parsing this tool avoids. Your = spacing passes through unchanged.
  • Quote style, import sorting, and line wrapping — all three need real semantic understanding to do without risking corrupting meaning.
  • Anything inside a string. Triple-quoted strings ('''...'''/"""...""") are preserved byte-for-byte — including internal indentation, blank lines, and trailing spaces — since they're often used for exact-format text like docstring examples. F-string {expr} interpolation is treated as opaque and never reformatted.
  • Comment text itself — only the whitespace before a # is touched; everything from # onward is copied through verbatim.

Is it the same as Black or autopep8?

No. Black and autopep8 parse Python into a real syntax tree, so they can safely rewrap lines, normalize quotes, and rebuild indentation from nothing. This tool works on text and existing whitespace — a fast, dependency-free cleanup for pasted snippets or generated code with inconsistent indentation, not a replacement for your project's formatter in CI.

Is my code private?

Completely. All formatting happens locally in your browser. Your source is never sent to a server, logged, or stored.

Does it handle f-strings and decorators?

Yes. F-strings (any prefix combination, like rf or Fr) are tokenized as whole strings, so their content — including {expr} interpolation — is never touched. Decorators (@decorator) and block-opening colons (if x:, def f():) need no special handling: they're ordinary code whose indentation is carried by the same depth-remapping as everything else.

pythoncode formatterbeautifyindentpep8whitespace

Love the tools? Lose the ads.

One payment clears every ad from your account, for good. No subscription, no tracking.