docs/en/docs/editor-support.md::Setup and Installation { #setup-and-installation }::L7

# Doc: docs/en/docs/editor-support.md | Page: Editor Support { #editor-support } | Section: Setup and Installation { #setup-and-installation }
## Setup and Installation { #setup-and-installation }

The **FastAPI Extension** is available for both [VS Code](https://code.visualstudio.com/) and [Cursor](https://www.cursor.com/). It can be installed directly from the Extensions panel in each editor by searching for "FastAPI" and selecting the extension published by **FastAPI Labs**. The extension also works in browser-based editors such as [vscode.dev](https://vscode.dev) and [github.dev](https://github.dev).

### Application Discovery { #application-discovery }

By default, the extension will automatically discover FastAPI applications in your workspace by scanning for files that instantiate `FastAPI()`. If auto-detection doesn't work for your project structure, you can specify an entrypoint via `[tool.fastapi]` in `pyproject.toml` or the `fastapi.entryPoint` VS Code setting using module notation (e.g. `myapp.main:app`).


docs/en/docs/editor-support.md::Features { #features }::L15

# Doc: docs/en/docs/editor-support.md | Page: Editor Support { #editor-support } | Section: Features { #features }
## Features { #features }

- **Path Operation Explorer** - A sidebar tree view of all <dfn title="routes, endpoints">*path operations*</dfn> in your application. Click to jump to any route or router definition.
- **Route Search** - Search by path, method, or name with Ctrl + Shift + E (on macOS: Cmd + Shift + E).
- **CodeLens Navigation** - Clickable links above test client calls (e.g. `client.get('/items')`) that jump to the matching *path operation* for quick navigation between tests and implementation.
- **Deploy to FastAPI Cloud** - One-click deployment of your app to [FastAPI Cloud](https://fastapicloud.com/).
- **Stream Application Logs** - Real-time log streaming from your FastAPI Cloud-deployed application with level filtering and text search.

If you'd like to familiarize yourself with the extension's features, you can check out the extension walkthrough by opening the Command Palette (Ctrl + Shift + P or on macOS: Cmd + Shift + P) and selecting "Welcome: Open walkthrough..." and then choosing the "Get started with FastAPI" walkthrough.


docs/en/docs/environment-variables.md::Environment Variables { #environment-variables }::L1

# Doc: docs/en/docs/environment-variables.md | Page: Environment Variables { #environment-variables } | Section: Environment Variables { #environment-variables }
# Environment Variables { #environment-variables }

/// tip

If you already know what "environment variables" are and how to use them, feel free to skip this.

///

An environment variable (also known as "**env var**") is a variable that lives **outside** of the Python code, in the **operating system**, and could be read by your Python code (or by other programs as well).

Environment variables could be useful for handling application **settings**, as part of the **installation** of Python, etc.


docs/en/docs/environment-variables.md::Create and Use Env Vars { #create-and-use-env-vars }::L13

# Doc: docs/en/docs/environment-variables.md | Page: Environment Variables { #environment-variables } | Section: Create and Use Env Vars { #create-and-use-env-vars }
## Create and Use Env Vars { #create-and-use-env-vars }

You can **create** and use environment variables in the **shell (terminal)**, without needing Python:

//// tab | Linux, macOS, Windows Bash

```console
// You could create an env var MY_NAME with
$ export MY_NAME="Wade Wilson"

// Then you could use it with other programs, like
$ echo "Hello $MY_NAME"

Hello Wade Wilson
```

////

//// tab | Windows PowerShell

```console
// Create an env var MY_NAME
$ $Env:MY_NAME = "Wade Wilson"

// Use it with other programs, like
$ echo "Hello $Env:MY_NAME"

Hello Wade Wilson
```

////


docs/en/docs/environment-variables.md::Read env vars in Python { #read-env-vars-in-python }::L53

# Doc: docs/en/docs/environment-variables.md | Page: Environment Variables { #environment-variables } | Section: Read env vars in Python { #read-env-vars-in-python }
## Read env vars in Python { #read-env-vars-in-python }

You could also create environment variables **outside** of Python, in the terminal (or with any other method), and then **read them in Python**.

For example you could have a file `main.py` with:

```Python hl_lines="3"
import os

name = os.getenv("MY_NAME", "World")
print(f"Hello {name} from Python")
```

/// tip

The second argument to [`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) is the default value to return.

If not provided, it's `None` by default, here we provide `"World"` as the default value to use.

///

Then you could call that Python program:

//// tab | Linux, macOS, Windows Bash

```console
// Here we don't set the env var yet
$ python main.py

// As we didn't set the env var, we get the default value

Hello World from Python

// But if we create an environment variable first
$ export MY_NAME="Wade Wilson"

// And then call the program again
$ python main.py

// Now it can read the environment variable

Hello Wade Wilson from Python
```

////

//// tab | Windows PowerShell

```console
// Here we don't set the env var yet
$ python main.py

// As we didn't set the env var, we get the default value

Hello World from Python

// But if we create an environment variable first
$ $Env:MY_NAME = "Wade Wilson"

// And then call the program again
$ python main.py

// Now it can read the environment variable

Hello Wade Wilson from Python
```

////

As environment variables can be set outside of the code, but can be read by the code, and don't have to be stored (committed to `git`) with the rest of the files, it's common to use them for configurations or **settings**.

You can also create an environment variable only for a **specific program invocation**, that is only available to that program, and only for its duration.

To do that, create it right before the program itself, on the same line:

```console
// Create an env var MY_NAME in line for this program call
$ MY_NAME="Wade Wilson" python main.py

// Now it can read the environment variable

Hello Wade Wilson from Python

// The env var no longer exists afterwards
$ python main.py

Hello World from Python
```

/// tip

You can read more about it at [The Twelve-Factor App: Config](https://12factor.net/config).

///


docs/en/docs/environment-variables.md::Types and Validation { #types-and-validation }::L160

# Doc: docs/en/docs/environment-variables.md | Page: Environment Variables { #environment-variables } | Section: Types and Validation { #types-and-validation }
## Types and Validation { #types-and-validation }

These environment variables can only handle **text strings**, as they are external to Python and have to be compatible with other programs and the rest of the system (and even with different operating systems, such as Linux, Windows, and macOS).

That means that **any value** read in Python from an environment variable **will be a `str`**, and any conversion to a different type or any validation has to be done in code.

You will learn more about using environment variables for handling **application settings** in the [Advanced User Guide - Settings and Environment Variables](./advanced/settings.md).


docs/en/docs/environment-variables.md::`PATH` Environment Variable { #path-environment-variable }::L168

# Doc: docs/en/docs/environment-variables.md | Page: Environment Variables { #environment-variables } | Section: `PATH` Environment Variable { #path-environment-variable }
## `PATH` Environment Variable { #path-environment-variable }

There is a **special** environment variable called **`PATH`** that is used by the operating systems (Linux, macOS, Windows) to find programs to run.

The value of the variable `PATH` is a long string that is made of directories separated by a colon `:` on Linux and macOS, and by a semicolon `;` on Windows.

For example, the `PATH` environment variable could look like this:

//// tab | Linux, macOS

```plaintext
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
```

This means that the system should look for programs in the directories:

* `/usr/local/bin`
* `/usr/bin`
* `/bin`
* `/usr/sbin`
* `/sbin`

////

//// tab | Windows

```plaintext
C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32
```

This means that the system should look for programs in the directories:

* `C:\Program Files\Python312\Scripts`
* `C:\Program Files\Python312`
* `C:\Windows\System32`

////

When you type a **command** in the terminal, the operating system **looks for** the program in **each of those directories** listed in the `PATH` environment variable.

For example, when you type `python` in the terminal, the operating system looks for a program called `python` in the **first directory** in that list.

If it finds it, then it will **use it**. Otherwise it keeps looking in the **other directories**.

### Installing Python and Updating the `PATH` { #installing-python-and-updating-the-path }

When you install Python, you might be asked if you want to update the `PATH` environment variable.

//// tab | Linux, macOS

Let's say you install Python and it ends up in a directory `/opt/custompython/bin`.

If you say yes to update the `PATH` environment variable, then the installer will add `/opt/custompython/bin` to the `PATH` environment variable.

It could look like this:

```plaintext
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin
```

This way, when you type `python` in the terminal, the system will find the Python program in `/opt/custompython/bin` (the last directory) and use that one.

////

//// tab | Windows

Let's say you install Python and it ends up in a directory `C:\opt\custompython\bin`.

If you say yes to update the `PATH` environment variable, then the installer will add `C:\opt\custompython\bin` to the `PATH` environment variable.

```plaintext
C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin
```

This way, when you type `python` in the terminal, the system will find the Python program in `C:\opt\custompython\bin` (the last directory) and use that one.

////

So, if you type:

```console
$ python
```

//// tab | Linux, macOS

The system will **find** the `python` program in `/opt/custompython/bin` and run it.

It would be roughly equivalent to typing:

```console
$ /opt/custompython/bin/python
```

////

//// tab | Windows

The system will **find** the `python` program in `C:\opt\custompython\bin\python` and run it.

It would be roughly equivalent to typing:

```console
$ C:\opt\custompython\bin\python
```

////

This information will be useful when learning about [Virtual Environments](virtual-environments.md).


docs/en/docs/environment-variables.md::Conclusion { #conclusion }::L290

# Doc: docs/en/docs/environment-variables.md | Page: Environment Variables { #environment-variables } | Section: Conclusion { #conclusion }
## Conclusion { #conclusion }

With this you should have a basic understanding of what **environment variables** are and how to use them in Python.

You can also read more about them in the [Wikipedia for Environment Variable](https://en.wikipedia.org/wiki/Environment_variable).

In many cases it's not very obvious how environment variables would be useful and applicable right away. But they keep showing up in many different scenarios when you are developing, so it's good to know about them.

For example, you will need this information in the next section, about [Virtual Environments](virtual-environments.md).


# Doc: docs/en/docs/external-links.md | Page: External Links | Section: External Links
---
include_yaml:
  topic_repos: data/topic_repos.yml
---

# External Links

**FastAPI** has a great community constantly growing.

There are many posts, articles, tools, and projects related to **FastAPI**.

You could easily use a search engine or video platform to find many resources related to FastAPI.

/// note

Before, this page used to list links to external articles.

But now that FastAPI is the backend framework with the most GitHub stars across languages, and the most starred and used framework in Python, it no longer makes sense to attempt to list all articles written about it.

///


# Doc: docs/en/docs/external-links.md | Page: External Links | Section: GitHub Repositories
## GitHub Repositories

Most starred [GitHub repositories with the topic `fastapi`](https://github.com/topics/fastapi):

{% for repo in topic_repos %}

★ {{repo.stars}} - {{repo.name}} by @{{repo.owner_login}}.

{% endfor %}


docs/en/docs/fastapi-cli.md::FastAPI CLI { #fastapi-cli }::L1

# Doc: docs/en/docs/fastapi-cli.md | Page: FastAPI CLI { #fastapi-cli } | Section: FastAPI CLI { #fastapi-cli }
# FastAPI CLI { #fastapi-cli }

**FastAPI CLI** is a command line program that you can use to serve your FastAPI app, manage your FastAPI project, and more.

When you install FastAPI (e.g. with `pip install "fastapi[standard]"`), it comes with a command line program you can run in the terminal.

To run your FastAPI app for development, you can use the `fastapi dev` command:

```console
$ <font color="#4E9A06">fastapi</font> dev

  <span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span>  Starting development server 🚀

             Searching for package file structure from directories with
             <font color="#3465A4">__init__.py</font> files
             Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>

   <span style="background-color:#007166"><font color="#D3D7CF"> module </font></span>  🐍 main.py

     <span style="background-color:#007166"><font color="#D3D7CF"> code </font></span>  Importing the FastAPI app object from the module with the
             following code:

             <u style="text-decoration-style:solid">from </u><u style="text-decoration-style:solid"><b>main</b></u><u style="text-decoration-style:solid"> import </u><u style="text-decoration-style:solid"><b>app</b></u>

      <span style="background-color:#007166"><font color="#D3D7CF"> app </font></span>  Using import string: <font color="#3465A4">main:app</font>

   <span style="background-color:#007166"><font color="#D3D7CF"> server </font></span>  Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
   <span style="background-color:#007166"><font color="#D3D7CF"> server </font></span>  Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>

      <span style="background-color:#007166"><font color="#D3D7CF"> tip </font></span>  Running in development mode, for production use:
             <b>fastapi run</b>

             Logs:

     <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span>  Will watch for changes in these directories:
             <b>[</b><font color="#4E9A06">'/home/user/code/awesomeapp'</font><b>]</b>
     <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span>  Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font> <b>(</b>Press CTRL+C to
             quit<b>)</b>
     <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span>  Started reloader process <b>[</b><font color="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
     <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span>  Started server process <b>[</b><font color="#34E2E2"><b>383153</b></font><b>]</b>
     <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span>  Waiting for application startup.
     <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span>  Application startup complete.
```

/// tip

For production you would use `fastapi run` instead of `fastapi dev`. 🚀

///

Internally, **FastAPI CLI** uses [Uvicorn](https://www.uvicorn.dev), a high-performance, production-ready, ASGI server. 😎

The `fastapi` CLI will try to detect automatically the FastAPI app to run, assuming it's an object called `app` in a file `main.py` (or a couple other variants).

But you can configure explicitly the app to use.


docs/en/docs/fastapi-cli.md::Configure the app `entrypoint` in `pyproject.toml` { #configure-the-app-entrypoint-in-pyproject-toml }::L61

# Doc: docs/en/docs/fastapi-cli.md | Page: FastAPI CLI { #fastapi-cli } | Section: Configure the app `entrypoint` in `pyproject.toml` { #configure-the-app-entrypoint-in-pyproject-toml }
## Configure the app `entrypoint` in `pyproject.toml` { #configure-the-app-entrypoint-in-pyproject-toml }

You can configure where your app is located in a `pyproject.toml` file like:

```toml
[tool.fastapi]
entrypoint = "main:app"
```

That `entrypoint` will tell the `fastapi` command that it should import the app like:

```python
from main import app
```

If your code was structured like:

```
.
├── backend
│   ├── main.py
│   ├── __init__.py
```

Then you would set the `entrypoint` as:

```toml
[tool.fastapi]
entrypoint = "backend.main:app"
```

which would be equivalent to:

```python
from backend.main import app
```

### `fastapi dev` with path or with `--entrypoint` CLI option { #fastapi-dev-with-path-or-with-entrypoint-cli-option }

You can also pass the file path to the `fastapi dev` command, and it will guess the FastAPI app object to use:

```console
$ fastapi dev main.py
```

Or, you can also pass the `--entrypoint` option to the `fastapi dev` command:

```console
$ fastapi dev --entrypoint main:app
```

But you would have to remember to pass the correct path\entrypoint every time you call the `fastapi` command.

Additionally, other tools might not be able to find it, for example the [VS Code Extension](editor-support.md) or [FastAPI Cloud](https://fastapicloud.com), so it is recommended to use the `entrypoint` in `pyproject.toml`.


docs/en/docs/fastapi-cli.md::`fastapi dev` { #fastapi-dev }::L116

# Doc: docs/en/docs/fastapi-cli.md | Page: FastAPI CLI { #fastapi-cli } | Section: `fastapi dev` { #fastapi-dev }
## `fastapi dev` { #fastapi-dev }

Running `fastapi dev` initiates development mode.

By default, **auto-reload** is enabled, automatically reloading the server when you make changes to your code. This is resource-intensive and could be less stable than when it's disabled. You should only use it for development. It also listens on the IP address `127.0.0.1`, which is the IP for your machine to communicate with itself alone (`localhost`).


docs/en/docs/fastapi-cli.md::`fastapi run` { #fastapi-run }::L122

# Doc: docs/en/docs/fastapi-cli.md | Page: FastAPI CLI { #fastapi-cli } | Section: `fastapi run` { #fastapi-run }
## `fastapi run` { #fastapi-run }

Executing `fastapi run` starts FastAPI in production mode.

By default, **auto-reload** is disabled. It also listens on the IP address `0.0.0.0`, which means all the available IP addresses, this way it will be publicly accessible to anyone that can communicate with the machine. This is how you would normally run it in production, for example, in a container.

In most cases you would (and should) have a "termination proxy" handling HTTPS for you on top, this will depend on how you deploy your application, your provider might do this for you, or you might need to set it up yourself.

/// tip

You can learn more about it in the [deployment documentation](deployment/index.md).

///


# Doc: docs/en/docs/fastapi-people.md | Page: FastAPI People | Section: FastAPI People
---
hide:
  - navigation

include_yaml:
  github_sponsors: data/github_sponsors.yml
  people: data/people.yml
  contributors: data/contributors.yml
  translation_reviewers: data/translation_reviewers.yml
  skip_users: data/skip_users.yml
  members: data/members.yml
  sponsors_badge: data/sponsors_badge.yml
  sponsors: data/sponsors.yml
---

# FastAPI People

FastAPI has an amazing community that welcomes people from all backgrounds.


# Doc: docs/en/docs/fastapi-people.md | Page: FastAPI People | Section: Creator
## Creator

Hey! 👋

This is me:

{% for user in people.maintainers %}

@{{ contributors.tiangolo.login }}

Answers: {{ user.answers }}

Pull Requests: {{ contributors.tiangolo.count }}

{% endfor %}

I'm the creator of **FastAPI**. You can read more about that in [Help FastAPI - Follow the author](help-fastapi.md#follow-the-author).

...But here I want to show you the community.

---

**FastAPI** receives a lot of support from the community. And I want to highlight their contributions.

These are the people that:

* [Help others with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github).
* Create or review Pull Requests.
* Help [manage the repository](https://tiangolo.com/open-source/management-tasks/) (team members).

All these tasks help maintain the repository.

A round of applause to them. 👏 🙇


# Doc: docs/en/docs/fastapi-people.md | Page: FastAPI People | Section: Team
## Team

This is the current list of team members. 😎

They have different levels of involvement and permissions, they can perform [repository management tasks](https://tiangolo.com/open-source/management-tasks/) and together we [manage the FastAPI repository](./management.md).

{% for user in members["members"] %}

@{{ user.login }}

{% endfor %}

Although the team members have the permissions to perform privileged tasks, all the help from others maintaining FastAPI is very much appreciated! 🙇♂


# Doc: docs/en/docs/fastapi-people.md | Page: FastAPI People | Section: FastAPI Experts
## FastAPI Experts

These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github). 🙇

They have proven to be **FastAPI Experts** by helping many others. ✨

/// tip

You could become an official FastAPI Expert too!

Just [help others with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github). 🤓

///

You can see the **FastAPI Experts** for:

* [Last Month](#fastapi-experts-last-month) 🤓
* [3 Months](#fastapi-experts-3-months) 😎
* [6 Months](#fastapi-experts-6-months) 🧐
* [1 Year](#fastapi-experts-1-year) 🧑🔬
* [**All Time**](#fastapi-experts-all-time) 🧙

### FastAPI Experts - Last Month

These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) during the last month. 🤓

{% for user in people.last_month_experts[:10] %}

{% if user.login not in skip_users %}

@{{ user.login }}

Questions replied: {{ user.count }}

{% endif %}

{% endfor %}

### FastAPI Experts - 3 Months

These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) during the last 3 months. 😎

{% for user in people.three_months_experts[:10] %}

{% if user.login not in skip_users %}

@{{ user.login }}

Questions replied: {{ user.count }}

{% endif %}

{% endfor %}

### FastAPI Experts - 6 Months

These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) during the last 6 months. 🧐

{% for user in people.six_months_experts[:10] %}

{% if user.login not in skip_users %}

@{{ user.login }}

Questions replied: {{ user.count }}

{% endif %}

{% endfor %}

### FastAPI Experts - 1 Year

These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) during the last year. 🧑🔬

{% for user in people.one_year_experts[:20] %}

{% if user.login not in skip_users %}

@{{ user.login }}

Questions replied: {{ user.count }}

{% endif %}

{% endfor %}

### FastAPI Experts - All Time

Here are the all time **FastAPI Experts**. 🤓🤯

These are the users that have [helped others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) through *all time*. 🧙

{% for user in people.experts[:50] %}

{% if user.login not in skip_users %}

@{{ user.login }}

Questions replied: {{ user.count }}

{% endif %}

{% endfor %}


# Doc: docs/en/docs/fastapi-people.md | Page: FastAPI People | Section: Top Contributors
## Top Contributors

Here are the **Top Contributors**. 👷

These users have created the most Pull Requests that have been *merged*.

They have contributed source code, documentation, etc. 📦

{% for user in (contributors.values() | list)[:50] %}

{% if user.login not in skip_users %}

@{{ user.login }}

Pull Requests: {{ user.count }}

{% endif %}

{% endfor %}

There are hundreds of other contributors, you can see them all in the [FastAPI GitHub Contributors page](https://github.com/fastapi/fastapi/graphs/contributors). 👷


# Doc: docs/en/docs/fastapi-people.md | Page: FastAPI People | Section: Top Translation Reviewers
## Top Translation Reviewers

These users are the **Top Translation Reviewers**. 🕵

Translation reviewers have the **power to approve translations** of the documentation. Without them, there wouldn't be documentation in several other languages.

{% for user in (translation_reviewers.values() | list)[:50] %}

{% if user.login not in skip_users %}

@{{ user.login }}

Reviews: {{ user.count }}

{% endif %}

{% endfor %}


# Doc: docs/en/docs/fastapi-people.md | Page: FastAPI People | Section: Sponsors
## Sponsors

These are the **Sponsors**. 😎

They are supporting my work with **FastAPI** (and others), mainly through [GitHub Sponsors](https://github.com/sponsors/tiangolo).

{% if sponsors %}

{% if sponsors.gold %}

### Gold Sponsors

{% for sponsor in sponsors.gold -%}

{% endfor %}
{% endif %}

{% if sponsors.silver %}

### Silver Sponsors

{% for sponsor in sponsors.silver -%}

{% endfor %}
{% endif %}

{% if sponsors.bronze %}

### Bronze Sponsors

{% for sponsor in sponsors.bronze -%}

{% endfor %}
{% endif %}

{% endif %}

### Individual Sponsors

{% if github_sponsors %}
{% for group in github_sponsors.sponsors %}

{% for user in group %}
{% if user.login not in sponsors_badge.logins %}

@{{ user.login }}

{% endif %}
{% endfor %}

{% endfor %}
{% endif %}


docs/en/docs/fastapi-people.md::About the data - technical details::L284

# Doc: docs/en/docs/fastapi-people.md | Page: FastAPI People | Section: About the data - technical details
## About the data - technical details

The main intention of this page is to highlight the effort of the community to help others.

Especially including efforts that are normally less visible, and in many cases more arduous, like helping others with questions and reviewing Pull Requests with translations.

The data is calculated each month, you can read the [source code here](https://github.com/fastapi/fastapi/blob/master/scripts/).

Here I'm also highlighting contributions from sponsors.

I also reserve the right to update the algorithm, sections, thresholds, etc (just in case 🤷).


docs/en/docs/features.md::FastAPI features { #fastapi-features }::L3

# Doc: docs/en/docs/features.md | Page: Features { #features } | Section: FastAPI features { #fastapi-features }
## FastAPI features { #fastapi-features }

**FastAPI** gives you the following:

### Based on open standards { #based-on-open-standards }

* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) for API creation, including declarations of <dfn title="also known as: endpoints, routes">path</dfn> <dfn title="also known as HTTP methods, as POST, GET, PUT, DELETE">operations</dfn>, parameters, request bodies, security, etc.
* Automatic data model documentation with [**JSON Schema**](https://json-schema.org/) (as OpenAPI itself is based on JSON Schema).
* Designed around these standards, after a meticulous study. Instead of an afterthought layer on top.
* This also allows using automatic **client code generation** in many languages.

### Automatic docs { #automatic-docs }

Interactive API documentation and exploration web user interfaces. As the framework is based on OpenAPI, there are multiple options, 2 included by default.

* [**Swagger UI**](https://github.com/swagger-api/swagger-ui), with interactive exploration, call and test your API directly from the browser.

![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)

* Alternative API documentation with [**ReDoc**](https://github.com/Rebilly/ReDoc).

![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)

### Just Modern Python { #just-modern-python }

It's all based on standard **Python type** declarations (thanks to Pydantic). No new syntax to learn. Just standard modern Python.

If you need a 2 minute refresher of how to use Python types (even if you don't use FastAPI), check the short tutorial: [Python Types](python-types.md).

You write standard Python with types:

```Python
from datetime import date

from pydantic import BaseModel

# Declare a variable as a str
# and get editor support inside the function
def main(user_id: str):
    return user_id

# A Pydantic model
class User(BaseModel):
    id: int
    name: str
    joined: date
```

That can then be used like:

```Python
my_user: User = User(id=3, name="John Doe", joined="2018-07-19")

second_user_data = {
    "id": 4,
    "name": "Mary",
    "joined": "2018-11-30",
}

my_second_user: User = User(**second_user_data)
```

/// note

`**second_user_data` means:

Pass the keys and values of the `second_user_data` dict directly as key-value arguments, equivalent to: `User(id=4, name="Mary", joined="2018-11-30")`

///

### Editor support { #editor-support }

The whole framework was designed to be easy and intuitive to use, all the decisions were tested on multiple editors even before starting development, to ensure the best development experience.

In the Python developer surveys, it's clear [that one of the most used features is "autocompletion"](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features).

The whole **FastAPI** framework is designed to satisfy that. Autocompletion works everywhere.

You will rarely need to come back to the docs.

Here's how your editor might help you:

* in [Visual Studio Code](https://code.visualstudio.com/):

![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)

* in [PyCharm](https://www.jetbrains.com/pycharm/):

![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png)

You will get completion in code you might even consider impossible before. As for example, the `price` key inside a JSON body (that could have been nested) that comes from a request.

No more typing the wrong key names, coming back and forth between docs, or scrolling up and down to find if you finally used `username` or `user_name`.

### Short { #short }

It has sensible **defaults** for everything, with optional configurations everywhere. All the parameters can be fine-tuned to do what you need and to define the API you need.

But by default, it all **"just works"**.

### Validation { #validation }

* Validation for most (or all?) Python **data types**, including:
    * JSON objects (`dict`).
    * JSON array (`list`) defining item types.
    * String (`str`) fields, defining min and max lengths.
    * Numbers (`int`, `float`) with min and max values, etc.

* Validation for more exotic types, like:
    * URL.
    * Email.
    * UUID.
    * ...and others.

All the validation is handled by the well-established and robust **Pydantic**.

### Security and authentication { #security-and-authentication }

Security and authentication integrated. Without any compromise with databases or data models.

All the security schemes defined in OpenAPI, including:

* HTTP Basic.
* **OAuth2** (also with **JWT tokens**). Check the tutorial on [OAuth2 with JWT](tutorial/security/oauth2-jwt.md).
* API keys in:
    * Headers.
    * Query parameters.
    * Cookies, etc.

Plus all the security features from Starlette (including **session cookies**).

All built as reusable tools and components that are easy to integrate with your systems, data stores, relational and NoSQL databases, etc.

### Dependency Injection { #dependency-injection }

FastAPI includes an extremely easy to use, but extremely powerful <dfn title='also known as "components", "resources", "services", "providers"'>Dependency Injection</dfn> system.

* Even dependencies can have dependencies, creating a hierarchy or **"graph" of dependencies**.
* All **automatically handled** by the framework.
* All the dependencies can require data from requests and **augment the path operation** constraints and automatic documentation.
* **Automatic validation** even for *path operation* parameters defined in dependencies.
* Support for complex user authentication systems, **database connections**, etc.
* **No compromise** with databases, frontends, etc. But easy integration with all of them.

### Unlimited "plug-ins" { #unlimited-plug-ins }

Or, in other words, no need for them, import and use the code you need.

Any integration is designed to be so simple to use (with dependencies) that you can create a "plug-in" for your application in 2 lines of code using the same structure and syntax used for your *path operations*.

### Tested { #tested }

* 100% <dfn title="The amount of code that is automatically tested">test coverage</dfn>.
* 100% <dfn title="Python type annotations, with this your editor and external tools can give you better support">type annotated</dfn> code base.
* Used in production applications.


docs/en/docs/features.md::Starlette features { #starlette-features }::L160

# Doc: docs/en/docs/features.md | Page: Features { #features } | Section: Starlette features { #starlette-features }
## Starlette features { #starlette-features }

**FastAPI** is fully compatible with (and based on) [**Starlette**](https://www.starlette.dev/). So, any additional Starlette code you have, will also work.

`FastAPI` is actually a sub-class of `Starlette`. So, if you already know or use Starlette, most of the functionality will work the same way.

With **FastAPI** you get all of **Starlette**'s features (as FastAPI is just Starlette on steroids):

* Seriously impressive performance. It is [one of the fastest Python frameworks available, on par with **NodeJS** and **Go**](https://github.com/encode/starlette#performance).
* **WebSocket** support.
* In-process background tasks.
* Startup and shutdown events.
* Test client built on HTTPX.
* **CORS**, GZip, Static Files, Streaming responses.
* **Session and Cookie** support.
* 100% test coverage.
* 100% type annotated codebase.


docs/en/docs/features.md::Pydantic features { #pydantic-features }::L178

# Doc: docs/en/docs/features.md | Page: Features { #features } | Section: Pydantic features { #pydantic-features }
## Pydantic features { #pydantic-features }

**FastAPI** is fully compatible with (and based on) [**Pydantic**](https://docs.pydantic.dev/). So, any additional Pydantic code you have, will also work.

Including external libraries also based on Pydantic, such as ORMs and ODMs for databases.

This also means that in many cases you can pass the same object you get from a request **directly to the database**, as everything is validated automatically.

The same applies the other way around, in many cases you can just pass the object you get from the database **directly to the client**.

With **FastAPI** you get all of **Pydantic**'s features (as FastAPI is based on Pydantic for all the data handling):

* **No brainfuck**:
    * No new schema definition micro-language to learn.
    * If you know Python types you know how to use Pydantic.
* Plays nicely with your **IDE/<dfn title="A program that checks for code errors">linter</dfn>/brain**:
    * Because pydantic data structures are just instances of classes you define; auto-completion, linting, mypy and your intuition should all work properly with your validated data.
* Validate **complex structures**:
    * Use of hierarchical Pydantic models, Python `typing`’s `List` and `Dict`, etc.
    * And validators allow complex data schemas to be clearly and easily defined, checked and documented as JSON Schema.
    * You can have deeply **nested JSON** objects and have them all validated and annotated.
* **Extensible**:
    * Pydantic allows custom data types to be defined or you can extend validation with methods on a model decorated with the validator decorator.
* 100% test coverage.


docs/en/docs/help-fastapi.md::Help { #help }::L1

# Doc: docs/en/docs/help-fastapi.md | Page: Help { #help } | Section: Help { #help }
# Help { #help }

Would you like to help FastAPI or get help about FastAPI?

There are very simple ways to help and get help.


docs/en/docs/help-fastapi.md::Subscribe to the newsletter { #subscribe-to-the-newsletter }::L7

# Doc: docs/en/docs/help-fastapi.md | Page: Help { #help } | Section: Subscribe to the newsletter { #subscribe-to-the-newsletter }
## Subscribe to the newsletter { #subscribe-to-the-newsletter }

You can subscribe to the (infrequent) [**FastAPI and friends** newsletter](newsletter.md) to stay updated about:

* News about FastAPI and friends 🚀
* Guides 📝
* Features ✨
* Breaking changes 🚨
* Tips and tricks ✅


docs/en/docs/help-fastapi.md::Follow FastAPI online { #follow-fastapi-online }::L17

# Doc: docs/en/docs/help-fastapi.md | Page: Help { #help } | Section: Follow FastAPI online { #follow-fastapi-online }
## Follow FastAPI online { #follow-fastapi-online }

You can follow **FastAPI** online in several places:

* [@fastapi on **X / Twitter**](https://x.com/fastapi)
* [@fastapi.tiangolo.com on **Bluesky**](https://bsky.app/profile/fastapi.tiangolo.com)
* [FastAPI on **LinkedIn**](https://www.linkedin.com/company/fastapi/)


docs/en/docs/help-fastapi.md::Star **FastAPI** in GitHub { #star-fastapi-in-github }::L25

# Doc: docs/en/docs/help-fastapi.md | Page: Help { #help } | Section: Star **FastAPI** in GitHub { #star-fastapi-in-github }
## Star **FastAPI** in GitHub { #star-fastapi-in-github }

You can "star" FastAPI in GitHub (clicking the star button at the top right): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi). ⭐

By adding a star, other users will be able to find it more easily and see that it has already been useful for others.


docs/en/docs/help-fastapi.md::Watch the GitHub repository for releases { #watch-the-github-repository-for-releases }::L31

# Doc: docs/en/docs/help-fastapi.md | Page: Help { #help } | Section: Watch the GitHub repository for releases { #watch-the-github-repository-for-releases }
## Watch the GitHub repository for releases { #watch-the-github-repository-for-releases }

You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi). 👀

There you can select "Releases only".

By doing it, you will receive notifications (in your email) whenever there's a new release (a new version) of **FastAPI** with bug fixes and new features.


docs/en/docs/help-fastapi.md::Follow the author { #follow-the-author }::L39

# Doc: docs/en/docs/help-fastapi.md | Page: Help { #help } | Section: Follow the author { #follow-the-author }
## Follow the author { #follow-the-author }

You can follow [me (Sebastián Ramírez / `tiangolo`)](https://tiangolo.com), the author in a few places, to hear when I have news to share about FastAPI and friends:

* [@tiangolo on **GitHub**](https://github.com/tiangolo).
* [@tiangolo on **X (Twitter)**](https://x.com/tiangolo)
* [@tiangolo.com on **Bluesky**](https://bsky.app/profile/tiangolo.com)
* [@tiangolo on **LinkedIn**](https://www.linkedin.com/in/tiangolo/).


docs/en/docs/help-fastapi.md::Help others with questions in GitHub { #help-others-with-questions-in-github }::L48

# Doc: docs/en/docs/help-fastapi.md | Page: Help { #help } | Section: Help others with questions in GitHub { #help-others-with-questions-in-github }
## Help others with questions in GitHub { #help-others-with-questions-in-github }

You can try and help others with their questions in [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered).

In many cases you might already know the answer for those questions. 🤓

If you are helping a lot of people with their questions, you will become an official [FastAPI Expert](fastapi-people.md#fastapi-experts). 🎉

Just remember, the most important point is: try to be kind. 🤗

### How to Help { #how-to-help }

Follow the [guide on how to help](https://tiangolo.com/open-source/help/#help-others-with-questions-in-github) here.


docs/en/docs/help-fastapi.md::Ask Questions { #ask-questions }::L62

# Doc: docs/en/docs/help-fastapi.md | Page: Help { #help } | Section: Ask Questions { #ask-questions }
## Ask Questions { #ask-questions }

You can [create a new question](https://github.com/fastapi/fastapi/discussions/new?category=questions) in the GitHub repository, for example to:

* Ask a **question** or ask about a **problem**.
* Suggest a new **feature**.


docs/en/docs/help-fastapi.md::Join the Chat { #join-the-chat }::L69

# Doc: docs/en/docs/help-fastapi.md | Page: Help { #help } | Section: Join the Chat { #join-the-chat }
## Join the Chat { #join-the-chat }

Join the 👥 [Discord chat server](https://discord.gg/VQjSZaeJmf) 👥 and hang out with others in the FastAPI community.

/// tip

For questions, ask them in GitHub Discussions, there's a much better chance you will receive help.

Use the chat only for other general conversations.

///

### Don't use the Chat for Questions { #dont-use-the-chat-for-questions }

Keep in mind that as chats allow more "free conversation", it's easy to ask questions that are too general and more difficult to answer, so, you might not receive answers.

In GitHub, the template will guide you to write the right question so that you can more easily get a good answer, or even solve the problem yourself even before asking.

Conversations in the chat systems are also not as easily searchable as in GitHub, they get lost.


docs/en/docs/history-design-future.md::History, Design and Future { #history-design-and-future }::L1

# Doc: docs/en/docs/history-design-future.md | Page: History, Design and Future { #history-design-and-future } | Section: History, Design and Future { #history-design-and-future }
# History, Design and Future { #history-design-and-future }

Some time ago, [a **FastAPI** user asked](https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920):

> What’s the history of this project? It seems to have come from nowhere to awesome in a few weeks [...]

Here's a little bit of that history.


docs/en/docs/history-design-future.md::Alternatives { #alternatives }::L9

# Doc: docs/en/docs/history-design-future.md | Page: History, Design and Future { #history-design-and-future } | Section: Alternatives { #alternatives }
## Alternatives { #alternatives }

I have been creating APIs with complex requirements for several years (Machine Learning, distributed systems, asynchronous jobs, NoSQL databases, etc), leading several teams of developers.

As part of that, I needed to investigate, test and use many alternatives.

The history of **FastAPI** is in great part the history of its predecessors.

As said in the section [Alternatives](alternatives.md):

<blockquote markdown="1">

**FastAPI** wouldn't exist if not for the previous work of others.

There have been many tools created before that have helped inspire its creation.

I have been avoiding the creation of a new framework for several years. First I tried to solve all the features covered by **FastAPI** using many different frameworks, plug-ins, and tools.

But at some point, there was no other option than creating something that provided all these features, taking the best ideas from previous tools, and combining them in the best way possible, using language features that weren't even available before (Python 3.6+ type hints).

</blockquote>


docs/en/docs/history-design-future.md::Investigation { #investigation }::L31

# Doc: docs/en/docs/history-design-future.md | Page: History, Design and Future { #history-design-and-future } | Section: Investigation { #investigation }
## Investigation { #investigation }

By using all the previous alternatives I had the chance to learn from all of them, take ideas, and combine them in the best way I could find for myself and the teams of developers I have worked with.

For example, it was clear that ideally it should be based on standard Python type hints.

Also, the best approach was to use already existing standards.

So, before even starting to code **FastAPI**, I spent several months studying the specs for OpenAPI, JSON Schema, OAuth2, etc. Understanding their relationship, overlap, and differences.


docs/en/docs/history-design-future.md::Design { #design }::L41

# Doc: docs/en/docs/history-design-future.md | Page: History, Design and Future { #history-design-and-future } | Section: Design { #design }
## Design { #design }

Then I spent some time designing the developer "API" I wanted to have as a user (as a developer using FastAPI).

I tested several ideas in the most popular Python editors: PyCharm, VS Code, Jedi based editors.

By the last [Python Developer Survey](https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools), that covers about 80% of the users.

It means that **FastAPI** was specifically tested with the editors used by 80% of the Python developers. And as most of the other editors tend to work similarly, all its benefits should work for virtually all editors.

That way I could find the best ways to reduce code duplication as much as possible, to have completion everywhere, type and error checks, etc.

All in a way that provided the best development experience for all the developers.


docs/en/docs/history-design-future.md::Requirements { #requirements }::L55

# Doc: docs/en/docs/history-design-future.md | Page: History, Design and Future { #history-design-and-future } | Section: Requirements { #requirements }
## Requirements { #requirements }

After testing several alternatives, I decided that I was going to use [**Pydantic**](https://docs.pydantic.dev/) for its advantages.

Then I contributed to it, to make it fully compliant with JSON Schema, to support different ways to define constraint declarations, and to improve editor support (type checks, autocompletion) based on the tests in several editors.

During the development, I also contributed to [**Starlette**](https://www.starlette.dev/), the other key requirement.


docs/en/docs/history-design-future.md::Development { #development }::L63

# Doc: docs/en/docs/history-design-future.md | Page: History, Design and Future { #history-design-and-future } | Section: Development { #development }
## Development { #development }

By the time I started creating **FastAPI** itself, most of the pieces were already in place, the design was defined, the requirements and tools were ready, and the knowledge about the standards and specifications was clear and fresh.


docs/en/docs/history-design-future.md::Future { #future }::L67

# Doc: docs/en/docs/history-design-future.md | Page: History, Design and Future { #history-design-and-future } | Section: Future { #future }
## Future { #future }

By this point, it's already clear that **FastAPI** with its ideas is being useful for many people.

It is being chosen over previous alternatives for suiting many use cases better.

Many developers and teams already depend on **FastAPI** for their projects (including me and my team).

But still, there are many improvements and features to come.

**FastAPI** has a great future ahead.

And [your help](help-fastapi.md) is greatly appreciated.


docs/en/docs/how-to/authentication-error-status-code.md::Use Old 403 Authentication Error Status Codes { #use-old-403-authentication-error-status-codes }::L1

# Doc: docs/en/docs/how-to/authentication-error-status-code.md | Page: Use Old 403 Authentication Error Status Codes { #use-old-403-authentication-error-status-codes } | Section: Use Old 403 Authentication Error Status Codes { #use-old-403-authentication-error-status-codes }
# Use Old 403 Authentication Error Status Codes { #use-old-403-authentication-error-status-codes }

Before FastAPI version `0.122.0`, when the integrated security utilities returned an error to the client after a failed authentication, they used the HTTP status code `403 Forbidden`.

Starting with FastAPI version `0.122.0`, they use the more appropriate HTTP status code `401 Unauthorized`, and return a sensible `WWW-Authenticate` header in the response, following the HTTP specifications, [RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-3.1), [RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized).

But if for some reason your clients depend on the old behavior, you can revert to it by overriding the method `make_not_authenticated_error` in your security classes.

For example, you can create a subclass of `HTTPBearer` that returns a `403 Forbidden` error instead of the default `401 Unauthorized` error:

{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *}

/// tip

Notice that the function returns the exception instance, it doesn't raise it. The raising is done in the rest of the internal code.

///


docs/en/docs/how-to/conditional-openapi.md::Conditional OpenAPI { #conditional-openapi }::L1

# Doc: docs/en/docs/how-to/conditional-openapi.md | Page: Conditional OpenAPI { #conditional-openapi } | Section: Conditional OpenAPI { #conditional-openapi }
# Conditional OpenAPI { #conditional-openapi }

If you needed to, you could use settings and environment variables to configure OpenAPI conditionally depending on the environment, and even disable it entirely.


docs/en/docs/how-to/conditional-openapi.md::About security, APIs, and docs { #about-security-apis-and-docs }::L5

# Doc: docs/en/docs/how-to/conditional-openapi.md | Page: Conditional OpenAPI { #conditional-openapi } | Section: About security, APIs, and docs { #about-security-apis-and-docs }
## About security, APIs, and docs { #about-security-apis-and-docs }

Hiding your documentation user interfaces in production *shouldn't* be the way to protect your API.

That doesn't add any extra security to your API, the *path operations* will still be available where they are.

If there's a security flaw in your code, it will still exist.

Hiding the documentation just makes it more difficult to understand how to interact with your API, and could make it more difficult for you to debug it in production. It could be considered simply a form of [Security through obscurity](https://en.wikipedia.org/wiki/Security_through_obscurity).

If you want to secure your API, there are several better things you can do, for example:

* Make sure you have well defined Pydantic models for your request bodies and responses.
* Configure any required permissions and roles using dependencies.
* Never store plaintext passwords, only password hashes.
* Implement and use well-known cryptographic tools, like pwdlib and JWT tokens, etc.
* Add more granular permission controls with OAuth2 scopes where needed.
* ...etc.

Nevertheless, you might have a very specific use case where you really need to disable the API docs for some environment (e.g. for production) or depending on configurations from environment variables.


docs/en/docs/how-to/conditional-openapi.md::Conditional OpenAPI from settings and env vars { #conditional-openapi-from-settings-and-env-vars }::L26

# Doc: docs/en/docs/how-to/conditional-openapi.md | Page: Conditional OpenAPI { #conditional-openapi } | Section: Conditional OpenAPI from settings and env vars { #conditional-openapi-from-settings-and-env-vars }
## Conditional OpenAPI from settings and env vars { #conditional-openapi-from-settings-and-env-vars }

You can easily use the same Pydantic settings to configure your generated OpenAPI and the docs UIs.

For example:

{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *}

Here we declare the setting `openapi_url` with the same default of `"/openapi.json"`.

And then we use it when creating the `FastAPI` app.

Then you could disable OpenAPI (including the UI docs) by setting the environment variable `OPENAPI_URL` to the empty string, like:

<div class="termy">

```console
$ OPENAPI_URL= uvicorn main:app

<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```

</div>

Then if you go to the URLs at `/openapi.json`, `/docs`, or `/redoc` you will just get a `404 Not Found` error like:

```JSON
{
    "detail": "Not Found"
}
```


docs/en/docs/how-to/configure-swagger-ui.md::Configure Swagger UI { #configure-swagger-ui }::L1

# Doc: docs/en/docs/how-to/configure-swagger-ui.md | Page: Configure Swagger UI { #configure-swagger-ui } | Section: Configure Swagger UI { #configure-swagger-ui }
# Configure Swagger UI { #configure-swagger-ui }

You can configure some extra [Swagger UI parameters](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/).

To configure them, pass the `swagger_ui_parameters` argument when creating the `FastAPI()` app object or to the `get_swagger_ui_html()` function.

`swagger_ui_parameters` receives a dictionary with the configurations passed to Swagger UI directly.

FastAPI converts the configurations to **JSON** to make them compatible with JavaScript, as that's what Swagger UI needs.


docs/en/docs/how-to/configure-swagger-ui.md::Disable Syntax Highlighting { #disable-syntax-highlighting }::L11

# Doc: docs/en/docs/how-to/configure-swagger-ui.md | Page: Configure Swagger UI { #configure-swagger-ui } | Section: Disable Syntax Highlighting { #disable-syntax-highlighting }
## Disable Syntax Highlighting { #disable-syntax-highlighting }

For example, you could disable syntax highlighting in Swagger UI.

Without changing the settings, syntax highlighting is enabled by default:

But you can disable it by setting `syntaxHighlight` to `False`:

{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *}

...and then Swagger UI won't show the syntax highlighting anymore:


docs/en/docs/how-to/configure-swagger-ui.md::Change the Theme { #change-the-theme }::L27

# Doc: docs/en/docs/how-to/configure-swagger-ui.md | Page: Configure Swagger UI { #configure-swagger-ui } | Section: Change the Theme { #change-the-theme }
## Change the Theme { #change-the-theme }

The same way you could set the syntax highlighting theme with the key `"syntaxHighlight.theme"` (notice that it has a dot in the middle):

{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *}

That configuration would change the syntax highlighting color theme:

<img src="/img/tutorial/extending-openapi/image04.png">


docs/en/docs/how-to/configure-swagger-ui.md::Change Default Swagger UI Parameters { #change-default-swagger-ui-parameters }::L37

# Doc: docs/en/docs/how-to/configure-swagger-ui.md | Page: Configure Swagger UI { #configure-swagger-ui } | Section: Change Default Swagger UI Parameters { #change-default-swagger-ui-parameters }
## Change Default Swagger UI Parameters { #change-default-swagger-ui-parameters }

FastAPI includes some default configuration parameters appropriate for most of the use cases.

It includes these default configurations:

{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *}

You can override any of them by setting a different value in the argument `swagger_ui_parameters`.

For example, to disable `deepLinking` you could pass these settings to `swagger_ui_parameters`:

{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *}


docs/en/docs/how-to/configure-swagger-ui.md::Other Swagger UI Parameters { #other-swagger-ui-parameters }::L51

# Doc: docs/en/docs/how-to/configure-swagger-ui.md | Page: Configure Swagger UI { #configure-swagger-ui } | Section: Other Swagger UI Parameters { #other-swagger-ui-parameters }
## Other Swagger UI Parameters { #other-swagger-ui-parameters }

To see all the other possible configurations you can use, read the official [docs for Swagger UI parameters](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/).


docs/en/docs/how-to/configure-swagger-ui.md::JavaScript-only settings { #javascript-only-settings }::L55

# Doc: docs/en/docs/how-to/configure-swagger-ui.md | Page: Configure Swagger UI { #configure-swagger-ui } | Section: JavaScript-only settings { #javascript-only-settings }
## JavaScript-only settings { #javascript-only-settings }

Swagger UI also allows other configurations to be **JavaScript-only** objects (for example, JavaScript functions).

FastAPI also includes these JavaScript-only `presets` settings:

```JavaScript
presets: [
    SwaggerUIBundle.presets.apis,
    SwaggerUIBundle.SwaggerUIStandalonePreset
]
```

These are **JavaScript** objects, not strings, so you can't pass them from Python code directly.

If you need to use JavaScript-only configurations like those, you can use one of the methods above. Override the whole Swagger UI *path operation* and manually write any JavaScript you need.


docs/en/docs/how-to/custom-docs-ui-assets.md::Custom Docs UI Static Assets (Self-Hosting) { #custom-docs-ui-static-assets-self-hosting }::L1

# Doc: docs/en/docs/how-to/custom-docs-ui-assets.md | Page: Custom Docs UI Static Assets (Self-Hosting) { #custom-docs-ui-static-assets-self-hosting } | Section: Custom Docs UI Static Assets (Self-Hosting) { #custom-docs-ui-static-assets-self-hosting }
# Custom Docs UI Static Assets (Self-Hosting) { #custom-docs-ui-static-assets-self-hosting }

The API docs use **Swagger UI** and **ReDoc**, and each of those need some JavaScript and CSS files.

By default, those files are served from a <abbr title="Content Delivery Network: A service, normally composed of several servers, that provides static files, like JavaScript and CSS. It's commonly used to serve those files from the server closer to the client, improving performance.">CDN</abbr>.

But it's possible to customize it, you can set a specific CDN, or serve the files yourself.


docs/en/docs/how-to/custom-docs-ui-assets.md::Custom CDN for JavaScript and CSS { #custom-cdn-for-javascript-and-css }::L9

# Doc: docs/en/docs/how-to/custom-docs-ui-assets.md | Page: Custom Docs UI Static Assets (Self-Hosting) { #custom-docs-ui-static-assets-self-hosting } | Section: Custom CDN for JavaScript and CSS { #custom-cdn-for-javascript-and-css }
## Custom CDN for JavaScript and CSS { #custom-cdn-for-javascript-and-css }

Let's say that you want to use a different <abbr title="Content Delivery Network">CDN</abbr>, for example you want to use `https://unpkg.com/`.

This could be useful if for example you live in a country that restricts some URLs.

### Disable the automatic docs { #disable-the-automatic-docs }

The first step is to disable the automatic docs, as by default, those use the default CDN.

To disable them, set their URLs to `None` when creating your `FastAPI` app:

{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *}

### Include the custom docs { #include-the-custom-docs }

Now you can create the *path operations* for the custom docs.

You can reuse FastAPI's internal functions to create the HTML pages for the docs, and pass them the needed arguments:

* `openapi_url`: the URL where the HTML page for the docs can get the OpenAPI schema for your API. You can use here the attribute `app.openapi_url`.
* `title`: the title of your API.
* `oauth2_redirect_url`: you can use `app.swagger_ui_oauth2_redirect_url` here to use the default.
* `swagger_js_url`: the URL where the HTML for your Swagger UI docs can get the **JavaScript** file. This is the custom CDN URL.
* `swagger_css_url`: the URL where the HTML for your Swagger UI docs can get the **CSS** file. This is the custom CDN URL.

And similarly for ReDoc...

{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *}

/// tip

The *path operation* for `swagger_ui_redirect` is a helper for when you use OAuth2.

If you integrate your API with an OAuth2 provider, you will be able to authenticate and come back to the API docs with the acquired credentials. And interact with it using the real OAuth2 authentication.

Swagger UI will handle it behind the scenes for you, but it needs this "redirect" helper.

///

### Create a *path operation* to test it { #create-a-path-operation-to-test-it }

Now, to be able to test that everything works, create a *path operation*:

{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *}

### Test it { #test-it }

Now, you should be able to go to your docs at [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs), and reload the page, it will load those assets from the new CDN.


docs/en/docs/how-to/custom-docs-ui-assets.md::Self-hosting JavaScript and CSS for docs { #self-hosting-javascript-and-css-for-docs }::L59

# Doc: docs/en/docs/how-to/custom-docs-ui-assets.md | Page: Custom Docs UI Static Assets (Self-Hosting) { #custom-docs-ui-static-assets-self-hosting } | Section: Self-hosting JavaScript and CSS for docs { #self-hosting-javascript-and-css-for-docs }
## Self-hosting JavaScript and CSS for docs { #self-hosting-javascript-and-css-for-docs }

Self-hosting the JavaScript and CSS could be useful if, for example, you need your app to keep working even while offline, without open Internet access, or in a local network.

Here you'll see how to serve those files yourself, in the same FastAPI app, and configure the docs to use them.

### Project file structure { #project-file-structure }

Let's say your project file structure looks like this:

```
.
├── app
│   ├── __init__.py
│   ├── main.py
```

Now create a directory to store those static files.

Your new file structure could look like this:

```
.
├── app
│   ├── __init__.py
│   ├── main.py
└── static/
```

### Download the files { #download-the-files }

Download the static files needed for the docs and put them on that `static/` directory.

You can probably right-click each link and select an option similar to "Save link as...".

**Swagger UI** uses the files:

* [`swagger-ui-bundle.js`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js)
* [`swagger-ui.css`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css)

And **ReDoc** uses the file:

* [`redoc.standalone.js`](https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js)

After that, your file structure could look like:

```
.
├── app
│   ├── __init__.py
│   ├── main.py
└── static
    ├── redoc.standalone.js
    ├── swagger-ui-bundle.js
    └── swagger-ui.css
```

### Serve the static files { #serve-the-static-files }

* Import `StaticFiles`.
* "Mount" a `StaticFiles()` instance in a specific path.

{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *}

### Test the static files { #test-the-static-files }

Start your application and go to [http://127.0.0.1:8000/static/redoc.standalone.js](http://127.0.0.1:8000/static/redoc.standalone.js).

You should see a very long JavaScript file for **ReDoc**.

It could start with something like:

```JavaScript
/*! For license information please see redoc.standalone.js.LICENSE.txt */
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")):
...
```

That confirms that you are being able to serve static files from your app, and that you placed the static files for the docs in the correct place.

Now we can configure the app to use those static files for the docs.

### Disable the automatic docs for static files { #disable-the-automatic-docs-for-static-files }

The same as when using a custom CDN, the first step is to disable the automatic docs, as those use the CDN by default.

To disable them, set their URLs to `None` when creating your `FastAPI` app:

{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *}

### Include the custom docs for static files { #include-the-custom-docs-for-static-files }

And the same way as with a custom CDN, now you can create the *path operations* for the custom docs.

Again, you can reuse FastAPI's internal functions to create the HTML pages for the docs, and pass them the needed arguments:

* `openapi_url`: the URL where the HTML page for the docs can get the OpenAPI schema for your API. You can use here the attribute `app.openapi_url`.
* `title`: the title of your API.
* `oauth2_redirect_url`: you can use `app.swagger_ui_oauth2_redirect_url` here to use the default.
* `swagger_js_url`: the URL where the HTML for your Swagger UI docs can get the **JavaScript** file. **This is the one that your own app is now serving**.
* `swagger_css_url`: the URL where the HTML for your Swagger UI docs can get the **CSS** file. **This is the one that your own app is now serving**.

And similarly for ReDoc...

{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *}

/// tip

The *path operation* for `swagger_ui_redirect` is a helper for when you use OAuth2.

If you integrate your API with an OAuth2 provider, you will be able to authenticate and come back to the API docs with the acquired credentials. And interact with it using the real OAuth2 authentication.

Swagger UI will handle it behind the scenes for you, but it needs this "redirect" helper.

///

### Create a *path operation* to test static files { #create-a-path-operation-to-test-static-files }

Now, to be able to test that everything works, create a *path operation*:

{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *}

### Test Static Files UI { #test-static-files-ui }

Now, you should be able to disconnect your WiFi, go to your docs at [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs), and reload the page.

And even without Internet, you would be able to see the docs for your API and interact with it.


docs/en/docs/how-to/custom-request-and-route.md::Custom Request and APIRoute class { #custom-request-and-apiroute-class }::L1

# Doc: docs/en/docs/how-to/custom-request-and-route.md | Page: Custom Request and APIRoute class { #custom-request-and-apiroute-class } | Section: Custom Request and APIRoute class { #custom-request-and-apiroute-class }
# Custom Request and APIRoute class { #custom-request-and-apiroute-class }

In some cases, you may want to override the logic used by the `Request` and `APIRoute` classes.

In particular, this may be a good alternative to logic in a middleware.

For example, if you want to read or manipulate the request body before it is processed by your application.

/// danger

This is an "advanced" feature.

If you are just starting with **FastAPI** you might want to skip this section.

///


docs/en/docs/how-to/custom-request-and-route.md::Use cases { #use-cases }::L17

# Doc: docs/en/docs/how-to/custom-request-and-route.md | Page: Custom Request and APIRoute class { #custom-request-and-apiroute-class } | Section: Use cases { #use-cases }
## Use cases { #use-cases }

Some use cases include:

* Converting non-JSON request bodies to JSON (e.g. [`msgpack`](https://msgpack.org/index.html)).
* Decompressing gzip-compressed request bodies.
* Automatically logging all request bodies.


docs/en/docs/how-to/custom-request-and-route.md::Handling custom request body encodings { #handling-custom-request-body-encodings }::L25

# Doc: docs/en/docs/how-to/custom-request-and-route.md | Page: Custom Request and APIRoute class { #custom-request-and-apiroute-class } | Section: Handling custom request body encodings { #handling-custom-request-body-encodings }
## Handling custom request body encodings { #handling-custom-request-body-encodings }

Let's see how to make use of a custom `Request` subclass to decompress gzip requests.

And an `APIRoute` subclass to use that custom request class.

### Create a custom `GzipRequest` class { #create-a-custom-gziprequest-class }

/// tip

This is a toy example to demonstrate how it works, if you need Gzip support, you can use the provided [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware).

///

First, we create a `GzipRequest` class, which will overwrite the `Request.body()` method to decompress the body in the presence of an appropriate header.

If there's no `gzip` in the header, it will not try to decompress the body.

That way, the same route class can handle gzip compressed or uncompressed requests.

{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *}

### Create a custom `GzipRoute` class { #create-a-custom-gziproute-class }

Next, we create a custom subclass of `fastapi.routing.APIRoute` that will make use of the `GzipRequest`.

This time, it will overwrite the method `APIRoute.get_route_handler()`.

This method returns a function. And that function is what will receive a request and return a response.

Here we use it to create a `GzipRequest` from the original request.

{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *}

/// note | Technical Details

A `Request` has a `request.scope` attribute, that's just a Python `dict` containing the metadata related to the request.

A `Request` also has a `request.receive`, that's a function to "receive" the body of the request.

The `scope` `dict` and `receive` function are both part of the ASGI specification.

And those two things, `scope` and `receive`, are what is needed to create a new `Request` instance.

To learn more about the `Request` check [Starlette's docs about Requests](https://www.starlette.dev/requests/).

///

The only thing the function returned by `GzipRequest.get_route_handler` does differently is convert the `Request` to a `GzipRequest`.

Doing this, our `GzipRequest` will take care of decompressing the data (if necessary) before passing it to our *path operations*.

After that, all of the processing logic is the same.

But because of our changes in `GzipRequest.body`, the request body will be automatically decompressed when it is loaded by **FastAPI** when needed.


docs/en/docs/how-to/custom-request-and-route.md::Accessing the request body in an exception handler { #accessing-the-request-body-in-an-exception-handler }::L81

# Doc: docs/en/docs/how-to/custom-request-and-route.md | Page: Custom Request and APIRoute class { #custom-request-and-apiroute-class } | Section: Accessing the request body in an exception handler { #accessing-the-request-body-in-an-exception-handler }
## Accessing the request body in an exception handler { #accessing-the-request-body-in-an-exception-handler }

/// tip

To solve this same problem, it's probably a lot easier to use the `body` in a custom handler for `RequestValidationError` ([Handling Errors](../tutorial/handling-errors.md#use-the-requestvalidationerror-body)).

But this example is still valid and it shows how to interact with the internal components.

///

We can also use this same approach to access the request body in an exception handler.

All we need to do is handle the request inside a `try`/`except` block:

{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *}

If an exception occurs, the `Request` instance will still be in scope, so we can read and make use of the request body when handling the error:

{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *}


docs/en/docs/how-to/custom-request-and-route.md::Custom `APIRoute` class in a router { #custom-apiroute-class-in-a-router }::L101

# Doc: docs/en/docs/how-to/custom-request-and-route.md | Page: Custom Request and APIRoute class { #custom-request-and-apiroute-class } | Section: Custom `APIRoute` class in a router { #custom-apiroute-class-in-a-router }
## Custom `APIRoute` class in a router { #custom-apiroute-class-in-a-router }

You can also set the `route_class` parameter of an `APIRouter`:

{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *}

In this example, the *path operations* under the `router` will use the custom `TimedRoute` class, and will have an extra `X-Response-Time` header in the response with the time it took to generate the response:

{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *}


docs/en/docs/how-to/extending-openapi.md::Extending OpenAPI { #extending-openapi }::L1

# Doc: docs/en/docs/how-to/extending-openapi.md | Page: Extending OpenAPI { #extending-openapi } | Section: Extending OpenAPI { #extending-openapi }
# Extending OpenAPI { #extending-openapi }

There are some cases where you might need to modify the generated OpenAPI schema.

In this section you will see how.


docs/en/docs/how-to/extending-openapi.md::The normal process { #the-normal-process }::L7

# Doc: docs/en/docs/how-to/extending-openapi.md | Page: Extending OpenAPI { #extending-openapi } | Section: The normal process { #the-normal-process }
## The normal process { #the-normal-process }

The normal (default) process, is as follows.

A `FastAPI` application (instance) has an `.openapi()` method that is expected to return the OpenAPI schema.

As part of the application object creation, a *path operation* for `/openapi.json` (or for whatever you set your `openapi_url`) is registered.

It just returns a JSON response with the result of the application's `.openapi()` method.

By default, what the method `.openapi()` does is check the property `.openapi_schema` to see if it has contents and return them.

If it doesn't, it generates them using the utility function at `fastapi.openapi.utils.get_openapi`.

And that function `get_openapi()` receives as parameters:

* `title`: The OpenAPI title, shown in the docs.
* `version`: The version of your API, e.g. `2.5.0`.
* `openapi_version`: The version of the OpenAPI specification used. By default, the latest: `3.1.0`.
* `summary`: A short summary of the API.
* `description`: The description of your API, this can include markdown and will be shown in the docs.
* `routes`: The routes from the application, taken from `app.routes`. FastAPI uses them to collect the registered *path operations*, including those from included routers.

/// tip | Technical Details

`app.routes` is a lower-level route tree. It can include route candidates that FastAPI uses internally for included routers, not only final `APIRoute` objects.

You can still pass `app.routes` to `get_openapi()`. FastAPI will traverse that route tree to collect the effective path operations.

///

/// note

The parameter `summary` is available in OpenAPI 3.1.0 and above, supported by FastAPI 0.99.0 and above.

///


docs/en/docs/how-to/extending-openapi.md::Overriding the defaults { #overriding-the-defaults }::L44

# Doc: docs/en/docs/how-to/extending-openapi.md | Page: Extending OpenAPI { #extending-openapi } | Section: Overriding the defaults { #overriding-the-defaults }
## Overriding the defaults { #overriding-the-defaults }

Using the information above, you can use the same utility function to generate the OpenAPI schema and override each part that you need.

For example, let's add [ReDoc's OpenAPI extension to include a custom logo](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo).

### Normal **FastAPI** { #normal-fastapi }

First, write all your **FastAPI** application as normally:

{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *}

### Generate the OpenAPI schema { #generate-the-openapi-schema }

Then, use the same utility function to generate the OpenAPI schema, inside a `custom_openapi()` function:

{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *}

### Modify the OpenAPI schema { #modify-the-openapi-schema }

Now you can add the ReDoc extension, adding a custom `x-logo` to the `info` "object" in the OpenAPI schema:

{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *}

### Cache the OpenAPI schema { #cache-the-openapi-schema }

You can use the property `.openapi_schema` as a "cache", to store your generated schema.

That way, your application won't have to generate the schema every time a user opens your API docs.

It will be generated only once, and then the same cached schema will be used for the next requests.

{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *}

### Override the method { #override-the-method }

Now you can replace the `.openapi()` method with your new function.

{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *}

### Check it { #check-it }

Once you go to [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) you will see that you are using your custom logo (in this example, **FastAPI**'s logo):

<img src="/img/tutorial/extending-openapi/image01.png">


docs/en/docs/how-to/general.md::General - How To - Recipes { #general-how-to-recipes }::L1

# Doc: docs/en/docs/how-to/general.md | Page: General - How To - Recipes { #general-how-to-recipes } | Section: General - How To - Recipes { #general-how-to-recipes }
# General - How To - Recipes { #general-how-to-recipes }

Here are several pointers to other places in the docs, for general or frequent questions.


docs/en/docs/how-to/general.md::Filter Data - Security { #filter-data-security }::L5

# Doc: docs/en/docs/how-to/general.md | Page: General - How To - Recipes { #general-how-to-recipes } | Section: Filter Data - Security { #filter-data-security }
## Filter Data - Security { #filter-data-security }

To ensure that you don't return more data than you should, read the docs for [Tutorial - Response Model - Return Type](../tutorial/response-model.md).


docs/en/docs/how-to/general.md::Optimize Response Performance - Response Model - Return Type { #optimize-response-performance-response-model-return-type }::L9

# Doc: docs/en/docs/how-to/general.md | Page: General - How To - Recipes { #general-how-to-recipes } | Section: Optimize Response Performance - Response Model - Return Type { #optimize-response-performance-response-model-return-type }
## Optimize Response Performance - Response Model - Return Type { #optimize-response-performance-response-model-return-type }

To optimize performance when returning JSON data, use a return type or response model, that way Pydantic will handle the serialization to JSON on the Rust side, without going through Python. Read more in the docs for [Tutorial - Response Model - Return Type](../tutorial/response-model.md).


docs/en/docs/how-to/general.md::Documentation Tags - OpenAPI { #documentation-tags-openapi }::L13

# Doc: docs/en/docs/how-to/general.md | Page: General - How To - Recipes { #general-how-to-recipes } | Section: Documentation Tags - OpenAPI { #documentation-tags-openapi }
## Documentation Tags - OpenAPI { #documentation-tags-openapi }

To add tags to your *path operations*, and group them in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Tags](../tutorial/path-operation-configuration.md#tags).


docs/en/docs/how-to/general.md::Documentation Summary and Description - OpenAPI { #documentation-summary-and-description-openapi }::L17

# Doc: docs/en/docs/how-to/general.md | Page: General - How To - Recipes { #general-how-to-recipes } | Section: Documentation Summary and Description - OpenAPI { #documentation-summary-and-description-openapi }
## Documentation Summary and Description - OpenAPI { #documentation-summary-and-description-openapi }

To add a summary and description to your *path operations*, and show them in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Summary and Description](../tutorial/path-operation-configuration.md#summary-and-description).


docs/en/docs/how-to/general.md::Documentation Response description - OpenAPI { #documentation-response-description-openapi }::L21

# Doc: docs/en/docs/how-to/general.md | Page: General - How To - Recipes { #general-how-to-recipes } | Section: Documentation Response description - OpenAPI { #documentation-response-description-openapi }
## Documentation Response description - OpenAPI { #documentation-response-description-openapi }

To define the description of the response, shown in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Response description](../tutorial/path-operation-configuration.md#response-description).


docs/en/docs/how-to/general.md::Documentation Deprecate a *Path Operation* - OpenAPI { #documentation-deprecate-a-path-operation-openapi }::L25

# Doc: docs/en/docs/how-to/general.md | Page: General - How To - Recipes { #general-how-to-recipes } | Section: Documentation Deprecate a *Path Operation* - OpenAPI { #documentation-deprecate-a-path-operation-openapi }
## Documentation Deprecate a *Path Operation* - OpenAPI { #documentation-deprecate-a-path-operation-openapi }

To deprecate a *path operation*, and show it in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Deprecation](../tutorial/path-operation-configuration.md#deprecate-a-path-operation).


docs/en/docs/how-to/general.md::Convert any Data to JSON-compatible { #convert-any-data-to-json-compatible }::L29

# Doc: docs/en/docs/how-to/general.md | Page: General - How To - Recipes { #general-how-to-recipes } | Section: Convert any Data to JSON-compatible { #convert-any-data-to-json-compatible }
## Convert any Data to JSON-compatible { #convert-any-data-to-json-compatible }

To convert any data to JSON-compatible, read the docs for [Tutorial - JSON Compatible Encoder](../tutorial/encoder.md).


docs/en/docs/how-to/general.md::OpenAPI Metadata - Docs { #openapi-metadata-docs }::L33

# Doc: docs/en/docs/how-to/general.md | Page: General - How To - Recipes { #general-how-to-recipes } | Section: OpenAPI Metadata - Docs { #openapi-metadata-docs }
## OpenAPI Metadata - Docs { #openapi-metadata-docs }

To add metadata to your OpenAPI schema, including a license, version, contact, etc, read the docs for [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md).


docs/en/docs/how-to/general.md::OpenAPI Custom URL { #openapi-custom-url }::L37

# Doc: docs/en/docs/how-to/general.md | Page: General - How To - Recipes { #general-how-to-recipes } | Section: OpenAPI Custom URL { #openapi-custom-url }
## OpenAPI Custom URL { #openapi-custom-url }

To customize the OpenAPI URL (or remove it), read the docs for [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#openapi-url).


docs/en/docs/how-to/general.md::OpenAPI Docs URLs { #openapi-docs-urls }::L41

# Doc: docs/en/docs/how-to/general.md | Page: General - How To - Recipes { #general-how-to-recipes } | Section: OpenAPI Docs URLs { #openapi-docs-urls }
## OpenAPI Docs URLs { #openapi-docs-urls }

To update the URLs used for the automatically generated docs user interfaces, read the docs for [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#docs-urls).


docs/en/docs/how-to/graphql.md::GraphQL { #graphql }::L1

# Doc: docs/en/docs/how-to/graphql.md | Page: GraphQL { #graphql } | Section: GraphQL { #graphql }
# GraphQL { #graphql }

As **FastAPI** is based on the **ASGI** standard, it's very easy to integrate any **GraphQL** library also compatible with ASGI.

You can combine normal FastAPI *path operations* with GraphQL on the same application.

/// tip

**GraphQL** solves some very specific use cases.

It has **advantages** and **disadvantages** when compared to common **web APIs**.

Make sure you evaluate if the **benefits** for your use case compensate the **drawbacks**. 🤓

///


docs/en/docs/how-to/graphql.md::GraphQL Libraries { #graphql-libraries }::L17

# Doc: docs/en/docs/how-to/graphql.md | Page: GraphQL { #graphql } | Section: GraphQL Libraries { #graphql-libraries }
## GraphQL Libraries { #graphql-libraries }

Here are some of the **GraphQL** libraries that have **ASGI** support. You could use them with **FastAPI**:

* [Strawberry](https://strawberry.rocks/) 🍓
    * With [docs for FastAPI](https://strawberry.rocks/docs/integrations/fastapi)
* [Ariadne](https://ariadnegraphql.org/)
    * With [docs for FastAPI](https://ariadnegraphql.org/docs/fastapi-integration)
* [Tartiflette](https://tartiflette.io/)
    * With [Tartiflette ASGI](https://tartiflette.github.io/tartiflette-asgi/) to provide ASGI integration
* [Graphene](https://graphene-python.org/)
    * With [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3)


docs/en/docs/how-to/graphql.md::GraphQL with Strawberry { #graphql-with-strawberry }::L30

# Doc: docs/en/docs/how-to/graphql.md | Page: GraphQL { #graphql } | Section: GraphQL with Strawberry { #graphql-with-strawberry }
## GraphQL with Strawberry { #graphql-with-strawberry }

If you need or want to work with **GraphQL**, [**Strawberry**](https://strawberry.rocks/) is the **recommended** library as it has the design closest to **FastAPI's** design, it's all based on **type annotations**.

Depending on your use case, you might prefer to use a different library, but if you asked me, I would probably suggest you try **Strawberry**.

Here's a small preview of how you could integrate Strawberry with FastAPI:

{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *}

You can learn more about Strawberry in the [Strawberry documentation](https://strawberry.rocks/).

And also the docs about [Strawberry with FastAPI](https://strawberry.rocks/docs/integrations/fastapi).


docs/en/docs/how-to/graphql.md::Older `GraphQLApp` from Starlette { #older-graphqlapp-from-starlette }::L44

# Doc: docs/en/docs/how-to/graphql.md | Page: GraphQL { #graphql } | Section: Older `GraphQLApp` from Starlette { #older-graphqlapp-from-starlette }
## Older `GraphQLApp` from Starlette { #older-graphqlapp-from-starlette }

Previous versions of Starlette included a `GraphQLApp` class to integrate with [Graphene](https://graphene-python.org/).

It was deprecated from Starlette, but if you have code that used it, you can easily **migrate** to [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3), that covers the same use case and has an **almost identical interface**.

/// tip

If you need GraphQL, I still would recommend you check out [Strawberry](https://strawberry.rocks/), as it's based on type annotations instead of custom classes and types.

///


docs/en/docs/how-to/graphql.md::Learn More { #learn-more }::L56

# Doc: docs/en/docs/how-to/graphql.md | Page: GraphQL { #graphql } | Section: Learn More { #learn-more }
## Learn More { #learn-more }

You can learn more about **GraphQL** in the [official GraphQL documentation](https://graphql.org/).

You can also read more about each of those libraries described above in their links.


docs/en/docs/how-to/index.md::How To - Recipes { #how-to-recipes }::L1

# Doc: docs/en/docs/how-to/index.md | Page: How To - Recipes { #how-to-recipes } | Section: How To - Recipes { #how-to-recipes }
# How To - Recipes { #how-to-recipes }

Here you will see different recipes or "how to" guides for **several topics**.

Most of these ideas would be more or less **independent**, and in most cases you should only need to study them if they apply directly to **your project**.

If something seems interesting and useful to your project, go ahead and check it, but otherwise, you might probably just skip them.

/// tip

If you want to **learn FastAPI** in a structured way (recommended), go and read the [Tutorial - User Guide](../tutorial/index.md) chapter by chapter instead.

///


docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md::Migrate from Pydantic v1 to Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 }::L1

# Doc: docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md | Page: Migrate from Pydantic v1 to Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 } | Section: Migrate from Pydantic v1 to Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 }
# Migrate from Pydantic v1 to Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 }

If you have an old FastAPI app, you might be using Pydantic version 1.

FastAPI version 0.100.0 had support for either Pydantic v1 or v2. It would use whichever you had installed.

FastAPI version 0.119.0 introduced partial support for Pydantic v1 from inside of Pydantic v2 (as `pydantic.v1`), to facilitate the migration to v2.

FastAPI 0.126.0 dropped support for Pydantic v1, while still supporting `pydantic.v1` for a little while.

FastAPI 0.128.0 dropped support for `pydantic.v1` as well, so the latest versions of FastAPI require Pydantic v2.

/// warning

The Pydantic team stopped support for Pydantic v1 for the latest versions of Python, starting with **Python 3.14**.

This includes `pydantic.v1`, which is no longer supported in Python 3.14 and above.

If you want to use the latest features of Python, you will need to make sure you use Pydantic v2.

///

If you have an old FastAPI app with Pydantic v1, here I'll show you how to migrate it to Pydantic v2, and the **features in FastAPI 0.119.0** to help you with a gradual migration.


docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md::Official Guide { #official-guide }::L25

# Doc: docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md | Page: Migrate from Pydantic v1 to Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 } | Section: Official Guide { #official-guide }
## Official Guide { #official-guide }

Pydantic has an official [Migration Guide](https://docs.pydantic.dev/latest/migration/) from v1 to v2.

It also includes what has changed, how validations are now more correct and strict, possible caveats, etc.

You can read it to understand better what has changed.


docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md::Tests { #tests }::L33

# Doc: docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md | Page: Migrate from Pydantic v1 to Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 } | Section: Tests { #tests }
## Tests { #tests }

Make sure you have [tests](../tutorial/testing.md) for your app and you run them on continuous integration (CI).

This way, you can do the upgrade and make sure everything is still working as expected.


docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md::`bump-pydantic` { #bump-pydantic }::L39

# Doc: docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md | Page: Migrate from Pydantic v1 to Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 } | Section: `bump-pydantic` { #bump-pydantic }
## `bump-pydantic` { #bump-pydantic }

In many cases, when you use regular Pydantic models without customizations, you will be able to automate most of the process of migrating from Pydantic v1 to Pydantic v2.

You can use [`bump-pydantic`](https://github.com/pydantic/bump-pydantic) from the same Pydantic team.

This tool will help you to automatically change most of the code that needs to be changed.

After this, you can run the tests and check if everything works. If it does, you are done. 😎


docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md::Pydantic v1 in v2 { #pydantic-v1-in-v2 }::L49

# Doc: docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md | Page: Migrate from Pydantic v1 to Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 } | Section: Pydantic v1 in v2 { #pydantic-v1-in-v2 }
## Pydantic v1 in v2 { #pydantic-v1-in-v2 }

Pydantic v2 includes everything from Pydantic v1 as a submodule `pydantic.v1`. But this is no longer supported in versions above Python 3.13.

This means that you can install the latest version of Pydantic v2 and import and use the old Pydantic v1 components from this submodule, as if you had the old Pydantic v1 installed.

{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *}

### FastAPI support for Pydantic v1 in v2 { #fastapi-support-for-pydantic-v1-in-v2 }

/// warning

This FastAPI support for `pydantic.v1` models was added in **FastAPI 0.119.0** and removed in **FastAPI 0.128.0**. It was meant to be a temporary aid for the migration to Pydantic v2.

In current versions of FastAPI, using a `pydantic.v1` model in your app will raise an error.

The rest of this section describes the temporary support available only in those older versions.

///

Since FastAPI 0.119.0, there's also partial support for Pydantic v1 from inside of Pydantic v2, to facilitate the migration to v2.

So, you could upgrade Pydantic to the latest version 2, and change the imports to use the `pydantic.v1` submodule, and in many cases it would just work.

{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *}

/// warning

Have in mind that as the Pydantic team no longer supports Pydantic v1 in recent versions of Python, starting from Python 3.14, using `pydantic.v1` is also not supported in Python 3.14 and above.

///

### Pydantic v1 and v2 on the same app { #pydantic-v1-and-v2-on-the-same-app }

It's **not supported** by Pydantic to have a model of Pydantic v2 with its own fields defined as Pydantic v1 models or vice versa.

```mermaid
graph TB
    subgraph "❌ Not Supported"
        direction TB
        subgraph V2["Pydantic v2 Model"]
            V1Field["Pydantic v1 Model"]
        end
        subgraph V1["Pydantic v1 Model"]
            V2Field["Pydantic v2 Model"]
        end
    end

    style V2 fill:#f9fff3
    style V1 fill:#fff6f0
    style V1Field fill:#fff6f0
    style V2Field fill:#f9fff3
```

...but you can have separate models, some using Pydantic v1 and others using Pydantic v2, in the same app.

```mermaid
graph TB
    subgraph "✅ Supported"
        direction TB
        subgraph V2["Pydantic v2 Model"]
            V2Field["Pydantic v2 Model"]
        end
        subgraph V1["Pydantic v1 Model"]
            V1Field["Pydantic v1 Model"]
        end
    end

    style V2 fill:#f9fff3
    style V1 fill:#fff6f0
    style V1Field fill:#fff6f0
    style V2Field fill:#f9fff3
```

In some cases, it's even possible to have both Pydantic v1 and v2 models in the same **path operation** in your FastAPI app:

{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *}

In this example above, the input model is a Pydantic v1 model, and the output model (defined in `response_model=ItemV2`) is a Pydantic v2 model.

### Pydantic v1 parameters { #pydantic-v1-parameters }

If you need to use some of the FastAPI-specific tools for parameters like `Body`, `Query`, `Form`, etc. with Pydantic v1 models, you can import them from `fastapi.temp_pydantic_v1_params` while you finish the migration to Pydantic v2:

{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *}

### Migrate in steps { #migrate-in-steps }

/// warning

The gradual migration using both Pydantic v1 and v2 models in the same app described below only works in **FastAPI 0.119.0 to 0.127.x**. It was removed in **FastAPI 0.128.0**, the latest versions require **Pydantic v2** models.

///

/// tip

First try with `bump-pydantic`, if your tests pass and that works, then you're done in one command. ✨

///

If `bump-pydantic` doesn't work for your use case, you can use the support for both Pydantic v1 and v2 models in the same app to do the migration to Pydantic v2 gradually.

You could first upgrade Pydantic to use the latest version 2, and change the imports to use `pydantic.v1` for all your models.

Then, you can start migrating your models from Pydantic v1 to v2 in groups, in gradual steps. 🚶


docs/en/docs/how-to/separate-openapi-schemas.md::Separate OpenAPI Schemas for Input and Output or Not { #separate-openapi-schemas-for-input-and-output-or-not }::L1

# Doc: docs/en/docs/how-to/separate-openapi-schemas.md | Page: Separate OpenAPI Schemas for Input and Output or Not { #separate-openapi-schemas-for-input-and-output-or-not } | Section: Separate OpenAPI Schemas for Input and Output or Not { #separate-openapi-schemas-for-input-and-output-or-not }
# Separate OpenAPI Schemas for Input and Output or Not { #separate-openapi-schemas-for-input-and-output-or-not }

Since **Pydantic v2** was released, the generated OpenAPI is a bit more exact and **correct** than before. 😎

In fact, in some cases, it will even have **two JSON Schemas** in OpenAPI for the same Pydantic model, for input and output, depending on if they have **default values**.

Let's see how that works and how to change it if you need to do that.


docs/en/docs/how-to/separate-openapi-schemas.md::Pydantic Models for Input and Output { #pydantic-models-for-input-and-output }::L9

# Doc: docs/en/docs/how-to/separate-openapi-schemas.md | Page: Separate OpenAPI Schemas for Input and Output or Not { #separate-openapi-schemas-for-input-and-output-or-not } | Section: Pydantic Models for Input and Output { #pydantic-models-for-input-and-output }
## Pydantic Models for Input and Output { #pydantic-models-for-input-and-output }

Let's say you have a Pydantic model with default values, like this one:

{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *}

### Model for Input { #model-for-input }

If you use this model as an input like here:

{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *}

...then the `description` field will **not be required**. Because it has a default value of `None`.

### Input Model in Docs { #input-model-in-docs }

You can confirm that in the docs, the `description` field doesn't have a **red asterisk**, it's not marked as required:

### Model for Output { #model-for-output }

But if you use the same model as an output, like here:

{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *}

...then because `description` has a default value, if you **don't return anything** for that field, it will still have that **default value**.

### Model for Output Response Data { #model-for-output-response-data }

If you interact with the docs and check the response, even though the code didn't add anything in one of the `description` fields, the JSON response contains the default value (`null`):

This means that it will **always have a value**, it's just that sometimes the value could be `None` (or `null` in JSON).

That means that clients using your API don't have to check if the value exists or not, they can **assume the field will always be there**, but just that in some cases it will have the default value of `None`.

The way to describe this in OpenAPI, is to mark that field as **required**, because it will always be there.

Because of that, the JSON Schema for a model can be different depending on if it's used for **input or output**:

* for **input** the `description` will **not be required**
* for **output** it will be **required** (and possibly `None`, or in JSON terms, `null`)

### Model for Output in Docs { #model-for-output-in-docs }

You can check the output model in the docs too, **both** `name` and `description` are marked as **required** with a **red asterisk**:

### Model for Input and Output in Docs { #model-for-input-and-output-in-docs }

And if you check all the available Schemas (JSON Schemas) in OpenAPI, you will see that there are two, one `Item-Input` and one `Item-Output`.

For `Item-Input`, `description` is **not required**, it doesn't have a red asterisk.

But for `Item-Output`, `description` is **required**, it has a red asterisk.

With this feature from **Pydantic v2**, your API documentation is more **precise**, and if you have autogenerated clients and SDKs, they will be more precise too, with a better **developer experience** and consistency. 🎉