Python Indentation: Rules, Tabs vs Spaces and Fixing IndentationError

Python indentation is not a style choice. The spaces at the start of a line tell Python which statements belong to the same block, and getting this wrong throws an error before your code even runs. This guide covers the rules, the tabs-versus-spaces debate that trips up most newcomers, editor setup for VS Code and other tools, and every common IndentationError pattern you will run into while writing Python.

What indentation means in Python

Indentation refers to the whitespace placed before a statement to show which block it belongs to. Most languages use curly braces to group code. Python skips the braces entirely and uses the leading whitespace itself as the grouping mechanism.

This means a line’s indentation level is not cosmetic. Add or remove a space in the wrong place and Python either throws an error or silently attaches a line to the wrong block, which changes what your program does.

age = 20

if age >= 18:
    print("You can vote")
else:
    print("You cannot vote yet")

The two print() lines are indented under if and else. Remove that indentation and Python has no way to know which block those statements belong to.

Python vs other languages

Most mainstream languages treat whitespace as decoration and use braces to mark blocks instead. Python treats whitespace as the block marker itself, which changes how strict the interpreter is about formatting.

AspectPythonC, Java, JavaScript
Block markerIndentationCurly braces { }
Whitespace enforced by interpreterYesNo
Mixing tabs and spacesRaises a TabErrorHas no effect on execution
Style guide defaultPEP 8, 4 spacesVaries by team or company

This is one reason Python code from different authors tends to look similar. The interpreter enforces a baseline of formatting that brace-based languages leave entirely up to convention.

Python indentation rules

PEP 8, Python’s official style guide, recommends 4 spaces per indentation level. That convention is followed almost everywhere, but the language itself is more flexible than most guides let on:

  • Every statement in the same block must share the exact same indentation level.
  • The indent amount for one block does not have to match the indent amount for another block, as long as each one is internally consistent.
  • You cannot indent the very first line of a file or script.
  • Leaving a block empty without content raises IndentationError: expected an indented block unless you add pass.

Statements that require an indented block

Python only asks for indentation after a line ending in a colon. These are the statements you will indent under most often:

  • if, elif and else
  • for and while
  • def and class
  • try, except, finally and else
  • with
  • match and case (Python 3.10 and later)

Anything that does not end in a colon stays at the current indentation level and does not open a new block.

Tabs vs spaces in Python indentation

Python accepts both tabs and spaces for indentation, but mixing them inside the same block is where most beginners get stuck. A tab character can render as anywhere from two to eight spaces depending on the editor, so a file that looks perfectly aligned on your screen can fail on someone else’s machine or in a terminal.

Python 3 refuses to guess which one you meant when a block mixes tabs and spaces in a way that is genuinely ambiguous, and raises TabError: inconsistent use of tabs and spaces in indentation instead of silently picking one.

def greet():
    print("Hello")
	print("How are you?")

The first line uses four spaces. The second line uses a tab. They may look aligned in your editor, but Python sees two different indentation characters and raises a TabError.

PEP 8 settles the debate directly: use spaces, not tabs, and never mix the two in one file. Most editors can convert tabs to spaces automatically as you type, which removes the problem before it starts.

Why this matters more in Python

A tab and a run of spaces can look the same on screen while being different characters to the interpreter. In a brace-based language, a stray tab is just an odd-looking line. In Python, it can be the difference between working code and a TabError, since the interpreter reads the actual bytes rather than the rendered width.

Older codebases sometimes use tabs throughout, and Python still supports that as long as the file stays consistent. New projects should default to spaces, since spaces render the same width in every editor, terminal, and diff tool, while tab width varies by configuration.

Configuring your editor for Python indentation

The fastest way to avoid indentation bugs is to make your editor insert spaces instead of tabs and show whitespace characters so mismatches are visible before you run the code.

VS Code

Open the Command Palette and search for “Indent Using Spaces” to set the default for the current file. To make it permanent, open Settings and set editor.insertSpaces to true and editor.tabSize to 4. Turning on editor.renderWhitespace displays dots for spaces and arrows for tabs, so a stray tab becomes obvious immediately. The Python extension also auto-indents new lines after a colon, matching what the interpreter expects.

PyCharm and other IDEs

PyCharm defaults to 4-space indentation for Python files and flags PEP 8 indentation violations with an inspection warning as you type. Sublime Text and Atom both expose a “Indentation” setting in their status bar where you can force spaces and set the tab width to 4. Whichever editor you use, check that setting once at the start of a project rather than after a TabError shows up.

Vim and other terminal editors

Vim users typically add four lines to .vimrc to get the same behavior: set tabstop=4, set shiftwidth=4, set expandtab and set autoindent. The expandtab option is the one that actually converts tab keypresses into spaces, and skipping it is the most common reason Vim users hit TabErrors that VS Code and PyCharm users rarely see.

Common IndentationError patterns and how to fix them

Almost every IndentationError falls into one of five patterns. Recognizing which one you are looking at makes the fix much faster.

Unexpected indent

A line has more indentation than the line before it, without a colon-terminated statement to justify the new block.

x = 10
    y = 20

Remove the extra whitespace so y = 20 lines up with x = 10.

Expected an indented block

A statement ending in a colon has no indented line under it.

if x > 5:
print("big number")

Indent the print() line, or add pass if the block is meant to stay empty for now.

Unindent does not match any outer indentation level

A line’s indentation falls between two existing levels instead of matching one of them exactly.

if x > 5:
    print("big")
      print("still big")

Python cannot tell whether the second print() belongs to the if block or a new one, since its indentation matches neither. Align it with the line above it.

TabError: inconsistent use of tabs and spaces

Covered above, this shows up when a block mixes tab and space characters in a way Python cannot resolve safely. Convert everything in the file to spaces to fix it for good.

Broken indentation after copy-pasting code

Pasting Python code from a PDF, a webpage, or a chat app frequently strips or duplicates leading whitespace. The code looks right visually but fails on execution. Retype the affected block or use your editor’s “convert indentation to spaces” command to normalize it.

Indentation in conditionals, loops, functions and classes

Every major Python block type relies on indentation to define its body, and the rules stay the same across all of them.

Conditional blocks group statements based on a condition. Read the if-else guide for the full set of variants including elif chains.

score = 72

if score >= 90:
    grade = "A"
elif score >= 70:
    grade = "B"
else:
    grade = "C"

Loops indent the statements that repeat. The body of a for loop or a while loop must be indented one level deeper than the loop header itself.

total = 0
for num in range(1, 6):
    total += num
print(total)

Functions indent their entire body under the def line, and nested blocks inside a function add another indent level on top of that.

def classify(number):
    if number % 2 == 0:
        return "even"
    else:
        return "odd"

Classes follow the same pattern. Every method defined inside a class sits one indent level in from class, and each method’s own body sits one level deeper still.

Best practices for consistent Python indentation

Most indentation problems come from tooling gaps rather than misunderstanding the rules themselves. Closing those gaps once removes the issue for the rest of a project.

  • Use 4 spaces per level and configure your editor to insert spaces when you press Tab.
  • Never mix tabs and spaces in the same file, even if your editor renders them the same way.
  • Run a formatter like Black or an autoformatter built into your IDE so indentation gets normalized on save.
  • Turn on a linter such as flake8 or Pylint, since both flag inconsistent indentation before you run the file.
  • Enable “render whitespace” or “show invisibles” in your editor so tabs and trailing spaces are visible.
  • Retype pasted code rather than trusting that whitespace survived the copy.
  • Keep nesting shallow. Code that runs four or five levels in is a sign to extract a function rather than a sign to fix the indentation.

Key takeaways

  • Python uses indentation instead of braces to define code blocks.
  • PEP 8 recommends 4 spaces per indentation level.
  • Every statement in a block must share the same indentation level.
  • Mixing tabs and spaces raises a TabError in Python 3.
  • Configure your editor to insert spaces and display whitespace characters.
  • IndentationError patterns fall into a handful of recognizable causes.
  • A formatter and linter catch most indentation mistakes automatically.

Frequently asked questions

How many spaces should I use for Python indentation?

PEP 8 recommends 4 spaces per indentation level. This is the convention followed by nearly every Python codebase and style guide in active use today.

Can I use tabs instead of spaces in Python?

Yes, but mixing tabs and spaces in the same block raises a TabError. Configure your editor to insert spaces so this never becomes a problem.

Why does Python use indentation instead of braces?

Indentation forces every Python file to be visually structured the same way, which removes the option of writing dense, poorly formatted code that still runs.

What causes IndentationError: unexpected indent?

A line has more leading whitespace than the line before it without a colon-terminated statement above it to open a new block. Remove the extra whitespace to fix it.

How do I fix inconsistent tabs and spaces in VS Code?

Open the Command Palette, run “Convert Indentation to Spaces,” then save the file. Set editor.insertSpaces to true to prevent it from happening again.

Does every Python block need the same number of spaces?

Each block must be internally consistent, but different blocks in the same file can technically use different indent widths. Stick to 4 spaces everywhere for readability.

What is the pass statement used for?

pass is a placeholder for a block that intentionally does nothing yet. Use it when a colon-terminated statement needs a body but you have not written the logic yet.

Conclusion

Indentation is Python’s way of making structure impossible to ignore. Stick to 4 spaces, keep your editor configured to avoid tab and space mixing, and treat every IndentationError as a quick pattern match rather than a mystery. Once the habit is set, these errors stop showing up at all.

Aditya Gupta
Aditya Gupta

Aditya Gupta is a founding member and editor at CodeForGeek. He first found his way into tech by reading articles, and now writes approachable guides to Node.js security, authentication, AI tools, coding agents, and web scraping.

Articles: 529