Skip to main content

Pyright Guide: Fast Static Type Checking for Python Code

Learn how to install and use Pyright for static type checking in Python. This guide covers configuration, IDE integration, troubleshooting, and when to choose Pyright over Mypy.
Jan 30, 2026  · 12 min read

Type hints make Python code easier to understand and maintain. But here's the catch: hints alone don't catch errors. You need a type checker to verify that your code actually follows the types you've declared.

I've used both Mypy and Pyright in production. Pyright's speed advantage is most apparent during development. Type errors appear as you type rather than after saving. In large codebases, this faster feedback loop makes an actual difference.

This tutorial covers everything you need to start using Pyright effectively. I'll show you how to install it, configure it for your project, and integrate it with VS Code. I'll also tease out the differences between Pyright and Mypy.

What Is Pyright?

Pyright is a static type checker for Python developed by Microsoft. It reads your code, analyzes type annotations, and reports errors when types don't match. Unlike runtime checks that catch errors when code executes, static analysis catches them before you run anything.

what is python pyright

While most Python tools are written in Python, Pyright is written in TypeScript and runs on Node.js. Odd choice for a Python tool, right? But it's the reason Pyright is so fast. The V8 JavaScript engine executes much faster than CPython would.

You'll encounter Pyright in two ways. You can run it as a command-line tool in CI/CD pipelines to catch type errors before doing merges. Or you might already be using it without knowing. It powers Pylance, Microsoft's Python extension for VS Code. Those red squiggles under type errors? That's Pyright working behind the scenes.

The tool ships with bundled type stubs for the Python standard library and common packages. You don't need to install anything extra to check code that uses os, json, or typing. For third-party packages, Pyright uses community-maintained stubs from typeshed or package-specific stubs you install separately.

How to Install Pyright

Now let's get Pyright running on your system. You have two installation options: npm (the native approach) or pip (the Python wrapper).

Installing Pyright with npm

The recommended installation uses npm because Pyright runs on Node.js. You'll need Node.js version 14.0.0 or higher.

# Global installation
npm install -g pyright

# Run without installing globally
npx pyright

# Local project installation
npm install --save-dev pyright

I use the global installation for quick checks and local installation for projects where I want to pin the version. The npx approach is useful for one-offs without adding to your global packages.

Installing Pyright via Python wrapper

If your team works exclusively in Python and doesn't want Node.js in the toolchain, a PyPI wrapper exists:

# Standard installation
pip install pyright

# Recommended: includes Node.js automatically
pip install pyright[nodejs]

The wrapper checks for Node.js on your system. If it's missing, the wrapper downloads a standalone version automatically. The [nodejs] extra uses a more reliable download method than the default.

Keep in mind there are tradeoffs. The first run takes longer while dependencies download. CI environments with restricted network access might fail. And the PyPI version sometimes lags behind npm releases by a few days.

For most Python teams, the wrapper works fine. But if you run into issues, fall back to the npm installation. It's more reliable.

Running Pyright on a Python Project

Once installed, running Pyright is simple. Navigate to your project directory and run:

pyright

That's it, really. Pyright scans for Python files, analyzes them, and reports any type errors it finds. No complex setup required.

What Pyright checks by default

What does Pyright look for? Without any configuration, it performs several checks. It validates type annotations that match actual usage. It catches undefined variables and unreachable code. It verifies imports correctly. It flags obvious type mismatches like passing a string where an integer is expected.

Here's example output from a project with errors:

/src/utils.py:12:15 - error: Argument of type "str" cannot be assigned 
   to parameter "count" of type "int" in function "process_items"
   "str" is not assignable to "int" (reportArgumentType)
/src/main.py:45:9 - error: "user" is possibly unbound (reportPossiblyUnbound)
2 errors, 0 warnings, 0 informations

Each error shows the file path, line number, column, and a description. The rule name in parentheses (like reportArgumentType) tells you exactly which check triggered the error. This matters when you want to suppress specific rules. We'll cover that shortly.

Understanding exit codes

Pyright returns different exit codes depending on the result:

Exit Code

Meaning

0

No errors found

1

Type errors found

2

Fatal error (crash, out of memory)

3

Configuration file error

4

Invalid command-line arguments

In CI pipelines, you typically want the build to fail on exit code 1. Exit codes 2-4 indicate something went wrong with the tool itself, not your code.

Configuring Pyright

While Pyright works out of the box, real projects need customization. You'll want to specify which files to check, which Python version to target, and how strict the analysis should be. Let's look at the key configuration options.

Type checking modes

Pyright offers four strictness levels. The mode you choose determines how many rules are enabled.

Mode

Behavior

off

No type checking; only syntax errors reported

basic

Fundamental checks; most lenient analysis

standard

Complete checking; the default in 2026

strict

Maximum safety; requires complete annotations

Which mode should you choose? For new projects, start with standard mode. It catches real bugs without overwhelming you with errors. Working with legacy code? Basic mode works better when you're adopting typing gradually. Save strict mode for libraries and critical infrastructure where you want maximum safety.

Fair warning: the jump from standard to strict is significant. Strict mode enables about 30 additional rules, including requirements for type annotations on all function parameters and return values. Expect a 10x increase in reported errors when switching. I learned this the hard way.

Comparison of Pyright basic mode with no errors versus strict mode showing missing type annotation errors

Strict mode requires complete type annotations. Image by Author

Configuration files

Pyright reads configuration from pyrightconfig.json or pyproject.toml. If both exist, pyrightconfig.json takes precedence.

Here's a minimal pyrightconfig.json:

{
  "include": ["src"],
  "exclude": ["**/node_modules", "**/__pycache__", "**/.venv"],
  "pythonVersion": "3.12",
  "typeCheckingMode": "standard"
}

The equivalent in pyproject.toml:

[tool.pyright]
include = ["src"]
exclude = ["**/node_modules", "**/__pycache__", "**/.venv"]
pythonVersion = "3.12"
typeCheckingMode = "standard"

VS Code showing pyrightconfig.json configuration file with include exclude and typeCheckingMode settings

Configuration file controls Pyright behavior. Image by Author.

Here's a critical detail that catches many people: if you define exclude manually, it replaces the defaults entirely. Always include node_modules, __pycache__, and your virtual environment in custom exclude patterns. Otherwise, Pyright tries to analyze your dependencies, causing massive slowdowns. Trust me, you don't want to wait 10 minutes for a type check.

Virtual environment configuration

How does Pyright find your installed packages? You need to tell it where to look. Configure this with venvPath and venv:

{
  "venvPath": ".",
  "venv": ".venv"
}

This tells Pyright to look for packages in ./.venv. If you use a different virtual environment location, adjust accordingly. Without this, Pyright can't find your installed dependencies and reports missing import errors for everything.

Suppressing diagnostics

Sometimes Pyright is technically correct but you need to silence specific errors anyway. Maybe you're working with legacy code, or you know better than the type checker in a specific case. You can suppress errors at three levels.

Configuration level suppression

Disable rules globally:

{
  "reportMissingTypeStubs": "none",
  "reportUnusedVariable": "warning"
}

File level suppression

Add a comment at the top of the file:

# pyright: basic
# pyright: reportPrivateUsage=false

Line-level suppression

Suppress a single line:

x: int = "hello"  # type: ignore
x: int = "hello"  # pyright: ignore
x: int = "hello"  # pyright: ignore[reportAssignmentType]

The specific rule syntax ([reportAssignmentType]) is useful when you want to silence one check without disabling others on the same line.

With configuration covered, let's see how Pyright integrates with your development environment.

Pyright in VS Code and IDEs

If you're like most Python developers, you'll experience Pyright through Pylance rather than the command line. Understanding this relationship helps you configure your editor correctly and avoid common pitfalls.

Pyright vs. Pylance

Pylance is Microsoft's VS Code extension that bundles Pyright's type checking engine. When you install Pylance, you get Pyright automatically. But Pylance adds features that aren't in the open-source Pyright:

  • Semantic highlighting: variables colored by their type
  • Advanced auto-import: smarter import suggestions
  • Code navigation: "Find All References" across your workspace

These features are closed-source and only available in VS Code. If you use Neovim, Emacs, or another editor, you get the core Pyright functionality but not these extras.

VS Code editor showing Pylance type error with red underline and error message in Problems panel

Pylance highlights type errors in editor. Image by Author.

Essential VS Code settings

Configure Pylance through VS Code's settings:

{
  "python.languageServer": "Pylance",
  "python.analysis.typeCheckingMode": "standard",
  "python.analysis.diagnosticMode": "openFilesOnly"
}

The diagnosticMode setting affects performance. "openFilesOnly" analyzes only files you have open. "workspace" analyzes everything but uses more memory and CPU.

Common configuration gotchas

Interpreter selection matters. Pylance uses your selected Python interpreter to find installed packages. If errors suddenly appear for packages you know are installed, check that the correct interpreter is selected in the VS Code status bar.

Interpreter selection affects package discovery paths. Image by Author.

CLI and Pylance defaults differ. Pylance defaults typeCheckingMode to "off" while the CLI defaults to "standard". Pylance also automatically adds src to search paths; the CLI doesn't. For consistent behavior between your editor and CI, explicitly set all options in pyproject.toml.

The "grayed out code" phenomenon. Pylance grays out unreachable code based on type analysis. If code appears grayed out unexpectedly, check the function called immediately before it. A function typed as returning NoReturn causes everything after it to appear unreachable.

Pyright vs. Mypy: When to Use Each

You might be wondering: should I use Pyright or stick with Mypy? Both tools are production-ready, and your choice depends on your workflow and requirements. Let me break down the key differences.

Speed and responsiveness

Pyright is approximately 3-5x faster than Mypy for full project scans and essentially instant for incremental checks. This matters most during development when you want immediate feedback.

Mypy has a daemon mode (dmypy) that improves performance, but it's still slower and occasionally has caching issues that require restarts.

Type inference differences

Here's where things get interesting. The tools infer types differently. Consider this code:

coordinates = (10, 20)

Pyright infers tuple[Literal[10], Literal[20]], preserving the exact values because tuples are immutable. Mypy infers tuple[int, int], widening to general types.

Pyright's approach catches more errors but occasionally causes friction when functions expect general types. This rarely matters in practice because Literal[10] is a valid subtype of int.

Unannotated code analysis

This is the biggest practical difference, and it's a game-changer for legacy codebases. Mypy skips unannotated functions by default. Pyright analyzes them anyway, catching obvious errors even without type hints.

For legacy codebases with sparse annotations, Pyright acts as a powerful linter that catches undefined variables and impossible method calls. Mypy treats those functions as "dynamic" and ignores them.

Plugin support

Mypy supports plugins for frameworks like Django and SQLAlchemy. These plugins understand ORM magic and provide accurate types for dynamically generated attributes.

Pyright has no plugin system. It relies entirely on type stubs. In 2026, most major libraries have high-quality stubs, so this matters less than it used to. But if you use a framework with heavy metaprogramming, check whether good stubs exist before committing to Pyright.

Aspect

Pyright

Mypy

Speed

3-5x faster

Slower

Unannotated code

Analyzed by default

Skipped by default

IDE integration

Powers VS Code/Pylance

Requires separate setup

Plugin system

None

Django, SQLAlchemy, etc.

Use Pylance (Pyright) during development for instant feedback, and consider running both Pyright and Mypy in CI if your project uses framework plugins.

Common Issues When Using Pyright

When Pyright reports unexpected errors, the cause is usually one of these issues.

Missing type stubs

Ever seen this error? Pyright complains when it can't find type information for a package:

Import "requests" could not be resolved (reportMissingImports)

VS Code showing Pyright missing import error with yellow underline on import statement

Missing stubs trigger import warning errors. Image by Author.

First, check that the package is installed in your virtual environment and that Pyright knows where to find it (using the venvPath and venv settings covered earlier).

If the package is installed but lacks type information, install community stubs:

pip install types-requests types-PyYAML types-redis

For packages without available stubs, you have two options. You can disable the warning with "reportMissingTypeStubs": "none" in your config. Or generate draft stubs yourself:

pyright --createstub some_package

This creates a skeleton .pyi file you can fill in with the methods you actually use.

Pre-commit hook failures

Does Pyright work locally but fail in pre-commit hooks? The issue is usually environment isolation. Pre-commit runs hooks in isolated environments that can't see your project's installed packages.

Fix this by pointing the hook to your virtual environment:

repos:
  - repo: https://github.com/RobertCraigie/pyright-python
    rev: v1.1.408
    hooks:
      - id: pyright
        args: ["--venvpath", ".", "--venv", ".venv"]

Unexpected strict mode errors

Enabled strict mode and suddenly seeing thousands of errors? Don't panic. This is normal. Strict mode requires complete type annotations. Start with basic or standard mode, add annotations incrementally, and only enable strict on fully typed modules.

Use per-file comments to keep legacy code on a lenient mode:

# pyright: basic

This lets you enforce strict checking on new code while gradually migrating old code.

Beyond troubleshooting, here are some strategies that will make your Pyright experience smoother from the start.

Best Practices for Using Pyright

After working with Pyright across different projects, I've learned a few things that make adoption smoother. Adopting these coding best practices ensures your type checking remains a help, not a hindrance.

Start with standard mode. As discussed earlier, it catches real bugs without requiring complete annotations. You can always tighten the rules later.

Pin your Pyright version. Pyright releases frequently, and new versions sometimes flag previously passing code. In CI, an unpinned pip install pyright can cause Monday morning build failures from weekend releases. I've been there. It's not fun.

[tool.pyright]
# In pyproject.toml
pythonVersion = "3.12"
# In requirements-dev.txt
pyright==1.1.408

Fix errors incrementally. Don't try to eliminate 10,000 errors at once. Use the strict array to enforce strict checking only on specific directories:

{
  "typeCheckingMode": "standard",
  "strict": ["src/core", "src/api"]
}

Use configuration files early. Even for small projects, explicit configuration prevents surprises. Take five minutes to document your Python version, virtual environment path, and chosen strictness level. Your future self will thank you.

Don't aim for perfection immediately. Use # pyright: ignore liberally at first. This marks technical debt visibly so you can clean it up over time rather than blocking progress. Perfect is the enemy of good, especially when adopting new tooling.

Learn Python From Scratch

Master Python for data science and gain in-demand skills.
Start Learning for Free

Conclusion

Pyright has earned its place as a practical choice for speed among Python type checkers. Its TypeScript foundation delivers real advantages, especially during the incremental checks that happen as you type.

Keep in mind, tools like Pyright work best when core Python concepts are second nature. So if parts of this tutorial felt harder than expected, or if you are still unclear on what Pyright is doing, I would recommend our Introduction to Python for Developers course.


Khalid Abdelaty's photo
Author
Khalid Abdelaty
LinkedIn

I’m a data engineer and community builder who works across data pipelines, cloud, and AI tooling while writing practical, high-impact tutorials for DataCamp and emerging developers.

Pyright FAQs

Does Pyright work with Jupyter notebooks?

Yes! Pyright supports .ipynb files through the Pylance extension in VS Code. You'll get real-time type checking as you write notebook cells. For command-line checking, use pyright --pythonpath to include your notebook's virtual environment.

Can I use Pyright with pre-commit hooks?

Absolutely. Use the pyright-python hook from the official repo. Just make sure to configure venvPath in your config file so pre-commit can find your dependencies. Otherwise, you'll get false import errors.

Will Pyright slow down my editor?

Not noticeably. Pyright runs in a separate process and only analyzes open files by default. If you have a massive monorepo, set "diagnosticMode": "openFilesOnly" in VS Code settings to keep things snappy.

Can I gradually adopt Pyright in a legacy codebase?

Yes, and it's actually easier than with Mypy. Start with "typeCheckingMode": "basic" and use the ignore array to exclude legacy folders. Add # pyright: ignore comments liberally at first, then clean them up over time.

Does Pyright support Python 2.7?

No. Pyright only supports Python 3.0 and above. If you're still on Python 2.7, you'll need to stick with Mypy or upgrade your codebase first. Python 2 reached end-of-life in 2020, so it's time to move on anyway.

How does Pyright compare to Mypy in terms of performance?

Pyright is noticeably faster, especially for incremental checks. It runs on Node.js instead of Python, which makes the analysis quicker. You'll see the difference most when typing in your editor, errors appear instantly rather than after saving. For CI pipelines, both work fine.

What are the main differences between Pyright and Pylance?

Think of it this way: Pyright is the engine, Pylance is the car. Pyright is the open-source type checker you can use anywhere. Pylance is Microsoft's VS Code extension that wraps Pyright and adds extras like semantic highlighting and smart imports. If you're not using VS Code, you're using Pyright directly.

Topics

Learn with DataCamp

Course

Introduction to Python

4 hr
6.7M
Master the basics of data analysis with Python in just four hours. This online course will introduce the Python interface and explore popular packages.
See DetailsRight Arrow
Start Course
See MoreRight Arrow
Related
Data Skills

blog

6 Python Best Practices for Better Code

Discover the Python coding best practices for writing best-in-class Python scripts.
Javier Canales Luna's photo

Javier Canales Luna

13 min

Tutorial

Type Checking in Python Tutorial

Learn about type checking, different types of the type system in various languages along with duck typing, and type hinting.

Olivia Smith

Tutorial

Setting Up VSCode For Python: A Complete Guide

Experience a simple, fun, and productive way of Python development by learning about VSCode and its extensionsn and features.
Abid Ali Awan's photo

Abid Ali Awan

Tutorial

Python REPL: A Hands-On Guide to Interactive Coding

Learn how Python’s REPL lets you run code interactively for testing, debugging, and learning. Discover essential commands, customization options, and advanced alternatives.
Allan Ouko's photo

Allan Ouko

Tutorial

Python Setup: The Definitive Guide

In this tutorial, you'll learn how to set up your computer for Python development, and explain the basics for having the best application lifecycle.

J. Andrés Pizarro

Tutorial

FastAPI Tutorial: An Introduction to Using FastAPI

Explore the FastAPI framework and discover how you can use it to create APIs in Python
Moez Ali's photo

Moez Ali

See MoreSee More