Last modified: Oct 02, 2026
Flake8 vs Ruff: Which Python Linter to Use
Linting keeps your Python code clean and consistent. Two tools dominate the conversation today: Flake8 and Ruff.
This guide compares them in plain terms. You will learn how each one works and when to pick one over the other.
What Is a Python Linter?
A linter reads your code and flags problems. It catches unused imports, undefined names, style issues, and more.
Catching these issues early saves time. It also keeps your team's codebase readable and easy to maintain.
Both Flake8 and Ruff do this job well. The difference lies in speed, features, and configuration.
What Is Flake8?
Flake8 is a long-standing Python linter. It wraps three tools: PyFlakes, pycodestyle, and McCabe.
PyFlakes finds logical errors. pycodestyle checks PEP 8 style. McCabe measures code complexity.
Flake8 is mature and widely used. Most Python developers have run it at least once.
What Is Ruff?
Ruff is a newer linter written in Rust. It aims to replace Flake8 and many other tools.
Ruff is extremely fast. It can lint a large codebase in milliseconds.
It also supports hundreds of rules. Many of them match Flake8's behavior out of the box.
Speed Comparison
Speed is Ruff's biggest selling point. It runs 10 to 100 times faster than Flake8 in most benchmarks.
This matters in large projects. Slow linting can break your flow and slow down CI pipelines.
Ruff's Rust core gives it a huge edge. Flake8, written in Python, cannot match that raw speed.
Here is a simple example of running each tool on a file:
# Run Flake8 on a file
flake8 app.py
# Run Ruff on the same file
ruff check app.py
The output looks similar, but the time taken is very different.
# Flake8 output
app.py:3:1: F401 'os' imported but unused
app.py:7:80: E501 line too long (85 > 79 characters)
# Ruff output
app.py:3:1: F401 [*] `os` imported but unused
app.py:7:80: E501 Line too long (85 > 79)
Ruff even marks fixable issues with a star. That is a nice touch for quick cleanup.
Rule Coverage
Flake8 covers the basics well. With plugins, you can extend it to fit your needs.
Ruff ships with a large rule set built in. It mimics popular plugins like flake8-bugbear and flake8-comprehensions.
This means fewer dependencies. You do not need to install many plugins to get broad coverage.
However, some niche Flake8 plugins have no Ruff equivalent yet. Check your needs before switching.
Configuration and Setup
Flake8 uses a setup.cfg or .flake8 file. You list rules to ignore or enable.
Ruff uses a pyproject.toml file. It also supports a ruff.toml file.
Ruff's config is clean and modern. It fits well with today's Python tooling.
Here is a small example of a Ruff config:
# pyproject.toml snippet for Ruff
[tool.ruff]
line-length = 88
select = ["E", "F", "I"]
ignore = ["E501"]
Flake8's config is simple too. But it often needs extra plugin entries.
# setup.cfg snippet for Flake8
[flake8]
max-line-length = 88
extend-ignore = E501
Both are readable. Ruff's config tends to be more compact for complex setups.
Auto-Fixing
Ruff can fix many issues automatically. Run ruff check --fix to apply safe fixes.
Flake8 does not fix code by default. You need a separate tool like autoflake or black.
This makes Ruff a stronger all-in-one option. It lints and fixes in one step.
Ecosystem and Community
Flake8 has years of history. Its plugin ecosystem is large and battle-tested.
Ruff is newer but growing fast. It is backed by Astral, the team behind uv and other tools.
Many projects now switch to Ruff for speed. Others stay with Flake8 for stability.
Both are actively maintained. You are not choosing a dead tool either way.
When to Use Flake8
Choose Flake8 if you rely on a specific plugin. Some plugins have no Ruff match.
It is also a safe pick for legacy projects. Migrating config can take time.
If your team already knows Flake8, staying put is fine. It still does the job well.
When to Use Ruff
Choose Ruff for speed and simplicity. It is great for new projects and large codebases.
It reduces tool clutter. One tool replaces Flake8, isort, and more.
If you want fast CI runs, Ruff is hard to beat. It keeps your pipeline quick and lean.
Can You Use Both?
Yes, but it is usually unnecessary. Running both adds noise and slows things down.
If you migrate, test Ruff's output against Flake8. Make sure no important rules are missed.
Start with a small project. Then roll it out to the rest of your codebase.
Quick Summary Table
Speed: Ruff wins by a large margin.
Rule coverage: Flake8 has more plugins; Ruff has more built-in rules.
Auto-fix: Ruff supports it; Flake8 does not.
Config: Ruff uses pyproject.toml; Flake8 uses setup files.
Maturity: Flake8 is older; Ruff is newer but stable.
Conclusion
Flake8 and Ruff are both solid Python linters. The right choice depends on your needs.
Pick Flake8 for its mature plugin ecosystem and legacy support. Pick Ruff for speed, simplicity, and built-in fixes.
For most new projects, Ruff is the better default today. It is fast, modern, and easy to set up.
Try both on a small file. Compare the speed and output. Then decide what fits your workflow best.