Python is forgiving in many ways, but its parser is not. A SyntaxError stops your program before a single line runs, which is frustrating when the fix is usually one missing character. The good news is that the same handful of mistakes account for almost every syntax error you will ever hit, and once you can recognize them on sight you fix them in seconds.

This guide walks through the most common Python syntax errors and the closely related IndentationError, TabError, and NameError cases that trip people up for the same reasons. Each section shows a broken snippet, the error Python prints, and the corrected version. Every snippet is real and copy-pasteable, so you can reproduce the error and confirm the fix in your own interpreter.

What is a syntax error in Python?

A syntax error means your code breaks the grammar of the language, so the interpreter cannot parse it into something runnable. Because parsing happens before execution, the program never starts: nothing prints, no side effects occur, you just get a traceback that ends in SyntaxError with a caret pointing at, or just after, the offending token.

Here is the canonical example, a call with no closing parenthesis.

python
print("Hello, Python!"

Python reaches the end of the file still waiting for the ) that closes the call, so it reports the problem at the end of input.

python
SyntaxError: '(' was never closed

One thing worth fixing in your mental model early: a syntax error is not the same as a runtime error. Syntax errors are caught at parse time and stop the program from starting at all. Runtime errors, like dividing by zero or opening a file that does not exist, happen while a syntactically valid program is running. This guide is about the first kind, the ones that never let your code run in the first place.

Common Python syntax errors and how to fix them

The sections below follow roughly the order you are likely to meet these mistakes. Each one is small and self-contained, so feel free to jump to whichever error message you are staring at right now.

1. Missing or mismatched parentheses

Parentheses group expressions and call functions, and they have to balance. An unclosed opening parenthesis is one of the most common syntax errors, especially in longer conditionals where the closer is easy to drop.

python
if (x > 10:
    print("x is greater than 10")

Python expects a closing parenthesis before the colon and tells you so.

python
SyntaxError: closing parenthesis ':' does not match opening parenthesis '('

The fix is to make sure every opening bracket has a matching closer of the same kind. Close the parenthesis before the colon and the conditional parses cleanly. The same rule applies to square brackets [] and curly braces {}; editors that highlight matching brackets catch most of these for you.

python
if (x > 10):
    print("x is greater than 10")

2. Missing colon in a control statement

Every compound statement header in Python ends with a colon: if, elif, else, for, while, def, class, try, and the rest. Leaving off the colon is a classic mistake when you come from a language that uses braces instead.

python
if x > 5
    print("x is greater than 5")

Modern Python points right at the missing token.

python
SyntaxError: expected ':'

Add the colon at the end of the header line. Whenever you write a statement that starts a new indented block, your eye should automatically check for the trailing colon.

python
if x > 5:
    print("x is greater than 5")

3. Expected an indented block (IndentationError)

Python uses indentation instead of braces to mark code blocks, so the body of every if, loop, or function must be indented. Write a header with a colon and then forget to indent the next line, and the parser has no block to attach.

python
for i in range(5):
print(i)

The interpreter reports that it wanted an indented block after the loop header.

python
IndentationError: expected an indented block after 'for' statement on line 1

Indent the body by four spaces, the standard Python convention. The indentation is the syntax here, not a style preference: it is how Python knows which lines belong to the loop.

python
for i in range(5):
    print(i)

4. Unexpected indent (IndentationError)

The opposite mistake is indenting a line that should sit at the same level as its neighbors. Indentation has to be consistent within a block, so a stray extra space or two on one line breaks the parse.

python
def example():
    print("First line")
      print("Second line")

The second print is indented more than the first for no reason, and Python rejects it.

python
IndentationError: unexpected indent

Line up every statement in the same block at the same column. Pick four spaces per level and keep it uniform, and your editor's auto-indent will usually keep you honest.

python
def example():
    print("First line")
    print("Second line")

5. Mixing tabs and spaces (TabError)

A particularly sneaky indentation bug is mixing tabs and spaces in the same block. The two can look identical on screen, but Python treats them as different and raises a dedicated TabError. In the snippet below the first body line uses spaces and the second uses a tab.

python
def greet(name):
    message = "Hi " + name
	return message

Even though both lines line up visually, Python cannot tell whether they are at the same level.

python
TabError: inconsistent use of tabs and spaces in indentation

Settle on spaces, which PEP 8 recommends, and never mix. Configure your editor to insert spaces when you press Tab, and run a search-and-replace on any file that already has a mix. Re-indenting both body lines with four spaces clears the error.

Make the whitespace visible

Tab-versus-space bugs are invisible until you turn on whitespace rendering. Most editors have a "show whitespace" or "render control characters" toggle that draws tabs and spaces as distinct marks. Turn it on once and these errors stop being mysterious.

6. EOL while scanning a string literal

A string has to open and close on the same line with matching quotes. Forget the closing quote, or close it with the wrong kind, and Python hits the end of the line still inside the string.

python
name = 'John"

The string opens with a single quote but closes with a double quote, so it is never terminated.

python
SyntaxError: unterminated string literal (detected at line 1)

Use the same quote character on both ends. If your text contains a quote, wrap the string in the other kind, for example "O'Brien", or use a triple-quoted string for text that spans multiple lines. Older Python versions phrase this same error as EOL while scanning string literal, but the cause is identical.

python
name = 'John'

7. EOF while scanning (unexpected end of file)

Closely related is the end-of-file version: an opening bracket or quote that never closes before the file runs out. This is the unclosed-call case from earlier, and it is worth its own section because the error message names a different cause. A multi-line structure with a missing closer is the usual culprit.

python
numbers = [1, 2, 3
print(sum(numbers))

Because the list is never closed, Python keeps reading, treats the next line as part of the list, and runs off the end of the file.

python
SyntaxError: '[' was never closed

Close the bracket where the structure ends. When an error points at the very end of a file, the real problem is almost always an opener several lines above that was never matched, so scan upward from the caret.

python
numbers = [1, 2, 3]
print(sum(numbers))

8. Invalid assignment: = versus ==

A single = assigns a value; a double == compares two values. Use assignment where a comparison belongs, such as in an if condition, and Python rejects it because you cannot assign inside a plain conditional test.

python
if x = 10:
    print("x is 10")

Recent Python versions are explicit about what you probably meant.

python
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

Use == to compare and reserve = for assignment. If you genuinely want to assign as part of an expression, that is what the walrus operator := is for, but for an ordinary condition you almost always mean ==.

python
if x == 10:
    print("x is 10")
Crawlbase Crawling API

Once your parser runs clean, the hard part of a scraper is the fetch: rendering JavaScript pages and rotating IPs so you do not get blocked. The Crawling API handles both behind a single request and returns finished HTML, so your error-free Python keeps parsing data instead of fighting a headless browser fleet and a proxy pool.

9. Using a reserved keyword as a name

Python reserves words like for, if, class, return, and import for the language itself. Try to use one as a variable name and the parser sees a keyword where it expects an identifier.

python
for = 10

Assigning to for is invalid because for can only start a loop.

python
SyntaxError: invalid syntax

Pick a name that is not reserved, ideally one that describes the value. If you are unsure whether a name is taken, Python's own keyword module lists every reserved word; checking a name against keyword.kwlist settles it instantly.

python
import keyword

num_for = 10
print("for" in keyword.kwlist)  # True, so it is off limits

10. Misplaced or missing commas

Commas separate items in lists, tuples, dictionaries, and argument lists. Drop one between two string literals and Python tries to read them as a single expression, which is invalid.

python
items = ["apple" "banana", "cherry"]

Python points at the second string, where a comma was expected.

python
SyntaxError: invalid syntax. Perhaps you forgot a comma?

Put a comma between each item. This one bites often because Python silently concatenates two adjacent string literals, so "apple" "banana" sometimes parses without error and produces "applebanana", a confusing bug rather than a clean failure. Always comma-separate your items explicitly.

python
items = ["apple", "banana", "cherry"]

11. Improper import statements

Imports have their own grammar. Forget to name what you are importing, and the from ... import form is left incomplete.

python
from math import

The parser reaches the end of the line still expecting a name to import.

python
SyntaxError: invalid syntax

Name what you are importing, or import the whole module. Both forms below are valid: import the module and reach into it with dot notation, or pull specific names out of it.

python
import os
import sys
from math import sqrt

12. print as a statement instead of a function

In Python 2, print was a statement and you wrote it without parentheses. In Python 3 it is a regular function, so the old form is a syntax error. This still trips up anyone copying examples from old tutorials.

python
print "Hello, Python!"

Python 3 even suggests the correction in the message.

python
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?

Wrap the arguments in parentheses, the same way you call any other function. The same applies to exec, which also became a function in Python 3.

python
print("Hello, Python!")

13. NameError from a typo

This last one is not strictly a syntax error: the code parses fine, so it fails at runtime rather than at parse time. It belongs here because the cause is the same family of small slips, and because the fix is just as quick. Misspell a variable name and Python cannot find it.

python
message = "hello"
print(mesage)

The name mesage was never defined, so Python raises a NameError and helpfully guesses what you meant.

python
NameError: name 'mesage' is not defined. Did you mean: 'message'?

Fix the spelling so the name matches its definition. Because this error only appears when the line actually runs, it can hide in a branch you rarely hit, which is one more reason to test your code in small pieces rather than all at once.

python
message = "hello"
print(message)

How to avoid Python syntax errors

You will never stop making these mistakes entirely, but you can catch nearly all of them before you run anything. A few habits do most of the work.

  • Use an editor with syntax highlighting. VS Code, PyCharm, and even lightweight editors like Thonny flag unmatched brackets, bad indentation, and broken strings as you type, so most errors never reach the interpreter.
  • Pick four spaces and never mix tabs. Configure your editor to insert spaces when you press Tab. Consistent indentation alone removes the entire IndentationError and TabError family.
  • Run a linter. Tools like Pylint, Flake8, and Ruff scan your code for syntax problems, missing commas, and undefined names before you run it, and most plug straight into your editor.
  • Read the error message and the caret. Modern Python points at the exact token and often suggests the fix. The line number is where Python noticed the problem, which for unclosed brackets is usually a line or two below the real cause.
  • Test in small pieces. Run a few lines at a time rather than a whole script at once. Errors are far easier to locate when only a handful of new lines could be responsible.

These same habits keep your code clean once you move past toy snippets into real projects, including scrapers. If you want a full walkthrough that puts working Python to use, see how to scrape a website with Python, and for a tour of the tools you will reach for, the best Python web scraping libraries.

Recap

Key takeaways

  • Syntax errors stop the program before it runs. Unlike runtime errors, they are caught at parse time, so nothing executes until you fix them.
  • Most syntax errors are punctuation. A missing colon, an unclosed bracket, a mismatched quote, or a dropped comma accounts for the large majority of cases.
  • Indentation is syntax, not style. Indent block bodies consistently, use four spaces, and never mix tabs and spaces, which avoids the entire IndentationError and TabError family.
  • = assigns and == compares. Using one where the other belongs is a frequent slip that modern Python now points out directly.
  • Read the message and the caret. Recent Python versions name the exact token and often suggest the fix, and for end-of-file errors the real cause is usually an unclosed opener above.

Frequently Asked Questions (FAQs)

What is the difference between a syntax error and a runtime error in Python?

A syntax error breaks the grammar of the language, so the interpreter cannot parse your code and the program never starts. A runtime error happens while a valid program is running, when an operation fails, such as dividing by zero or opening a file that does not exist. Syntax errors are caught before execution; runtime errors are caught during it.

Why does Python care so much about indentation?

Python uses indentation instead of braces to define code blocks, which keeps code readable and uniform. Because the whitespace is the syntax, inconsistent indentation is a genuine error rather than a style nitpick. Settle on four spaces per level and let your editor enforce it, and indentation stops being a source of bugs.

How do I fix "SyntaxError: unexpected EOF while parsing"?

That message means an opening bracket, parenthesis, or quote was never closed, so Python ran off the end of the file still waiting for the closer. Start at the line the error points to and scan upward for an unmatched opener. Newer Python versions phrase the same problem more specifically, for example '(' was never closed, which tells you exactly which character to chase.

Why do I get a TabError when my code looks correctly indented?

Because tabs and spaces can look identical on screen while Python treats them as different characters. If one line in a block uses a tab and another uses spaces, the indentation is inconsistent even though it lines up visually. Turn on whitespace rendering in your editor, convert everything to spaces, and the error disappears.

How can I catch syntax errors before running my code?

Use an editor with syntax highlighting and a linter such as Pylint, Flake8, or Ruff. These flag unmatched brackets, missing commas, bad indentation, and undefined names as you type, so most mistakes never reach the interpreter. Testing small pieces of code at a time also isolates any error that does slip through.

Is print a function or a statement in Python?

In Python 3 it is a function, so you must call it with parentheses: print("text"). The bare print "text" form was valid only in Python 2 and is now a syntax error. If you see "Missing parentheses in call to print," you are reading Python 2 style code in a Python 3 interpreter.

Start Building

Crawl any site at scale, without fighting infrastructure.

Crawlbase handles proxies, fingerprints, and CAPTCHAs so your team ships data pipelines instead of maintaining crawl plumbing. 1,000 requests free, no card required.

Self-serve · No sales call required · Enterprise crawl volumes available