New to Rust? Grab our free Rust for Beginners eBook Get it free →
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.
| Aspect | Python | C, Java, JavaScript |
|---|---|---|
| Block marker | Indentation | Curly braces { } |
| Whitespace enforced by interpreter | Yes | No |
| Mixing tabs and spaces | Raises a TabError | Has no effect on execution |
| Style guide default | PEP 8, 4 spaces | Varies 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 blockunless you addpass.
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,elifandelseforandwhiledefandclasstry,except,finallyandelsewithmatchandcase(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.




