---
title: "FastAPIのSwagger UI（/docs）の使い方｜表示・設定・本番で隠す手順【2026年版】"
url: "https://www.issoh.co.jp/tech/details/2246/"
published: 2024-05-22
updated: 2026-10-12
categories: ["Python"]
publisher: "株式会社一創"
---

# FastAPIのSwagger UI（/docs）の使い方｜表示・設定・本番で隠す手順【2026年版】

FastAPIは `FastAPI()` のインスタンスを作るだけで、`/docs` にSwagger UI、`/redoc` にReDoc、`/openapi.json` にOpenAPIスキーマを自動で公開します。設定ファイルもデコレーターの追加も要りません。

この記事では、FastAPI 0.143.0（2026年10月時点の最新版）で実際に動かした結果をもとに、Swagger UIの表示手順と画面の使い方、説明文やタグの整え方、`swagger_ui_parameters` の設定、本番環境で隠す・守る方法、表示されないときの原因までを順に説明します。

## まとめ：FastAPIのSwagger UI（/docs）の要点

- **表示**：`fastapi dev main.py` で起動すると、ターミナルに「Documentation at http://127.0.0.1:8000/docs」と出る。そのURLを開けばSwagger UIが表示される。
- **画面**：各エンドポイントの「Try it out」→「Execute」で実リクエストを送れる。認証付きAPIは右上の「Authorize」でトークンを入れて試す。
- **説明の整え方**：画面に出る文言はコード側で決まる。`tags`・`summary`・docstring・`examples` を書き、表示順は `openapi_tags` で指定する。
- **画面の挙動**：`FastAPI(swagger_ui_parameters={...})` にSwagger UIの設定キーをそのまま渡す。認証の保持は `persistAuthorization`、一覧を畳むなら `docExpansion`。
- **本番**：`docs_url=None, redoc_url=None` だけでは `/openapi.json` が200で残る。全部止めるなら `openapi_url=None`。社内にだけ見せるならBasic認証で守る。

## FastAPIでSwagger UIを表示する手順

FastAPIの最新版は0.143.0で、Python 3.10以上が必要です（[PyPIのfastapi](https://pypi.org/project/fastapi/)）。公式チュートリアルは `pip install "fastapi[standard]"` で入れ、`fastapi dev` コマンドで起動する手順に移っています。素の `pip install fastapi` でも `fastapi` コマンドの入口はできますが、実体の fastapi-cli とUvicornが入らないため、実行すると `To use the fastapi command, please install "fastapi[standard]"` と出て止まります。

```
pip install "fastapi[standard]"
```

```
# main.py
from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
    return {"item_id": item_id, "q": q}
```

```
$ fastapi dev main.py

Server started at http://127.0.0.1:8000
    Documentation at http://127.0.0.1:8000/docs
```

起動ログの「Documentation at」の行がSwagger UIのURLです。従来の `uvicorn main:app --reload` でも同じ画面が出ます。FastAPIはアプリの初期化時に、既定で次の4つのURLを登録します。

| URL                   | 中身                  | 変更・無効化する引数                         |
| --------------------- | ------------------- | ---------------------------------- |
| /docs                 | Swagger UI          | docs\_url                          |
| /redoc                | ReDoc（閲覧専用の文書）      | redoc\_url                         |
| /openapi.json         | OpenAPI 3.1.0 のスキーマ | openapi\_url                       |
| /docs/oauth2-redirect | OAuth2認可後の戻り先       | swagger\_ui\_oauth2\_redirect\_url |

Swagger UIは `/openapi.json` をブラウザから読み込んで画面を組み立てています。URLを変えたいときは `FastAPI(docs_url="/documentation")` のように渡します。Swagger UIそのものの成り立ちやSwagger Editorとの違いは[Swaggerとは：Editor・UIをDockerで動かす手順とOpenAPI 3.2対応の現況](/tech/details/17451/)、FastAPI自体の始め方は[FastAPIとは｜最短で動かす手順とasync/defの使い分け【2026年版】](/tech/details/3859/)で扱っています。

## Swagger UIの画面でのAPI実行確認

### Try it outとExecuteによるリクエスト送信

エンドポイントの行を開き、「Try it out」を押すとパラメータとリクエストボディが編集できるようになります。「Execute」で実際にサーバーへ送信され、下に次の3つが出ます。

- **Curl**：同じリクエストをターミナルで再現するコマンド。不具合の報告にそのまま貼れる。
- **Request URL**：クエリ文字列まで含めた送信先。
- **Server response**：ステータスコード・レスポンス本文・ヘッダー。

パスパラメータやリクエストボディなど入力を受け取るエンドポイントに422が載るのは、FastAPIが型ヒントとPydanticモデルで入力を検証し、違反を422 Unprocessable Entityで返すためです。`item_id` に文字列を入れて実行すると、どの項目がなぜ弾かれたかが `detail` に入って返ります。

### Authorizeボタンでの認証付きAPIの実行

依存関係に `OAuth2PasswordBearer` を使うと、OpenAPIスキーマに `securitySchemes` が追加され、Swagger UIの右上に「Authorize」ボタンが出ます。ユーザー名とパスワードを入れると `tokenUrl` にフォーム送信してトークンを受け取り、以後のリクエストに `Authorization: Bearer` ヘッダーを付けて送ります。

```
from typing import Annotated

from fastapi import Depends, FastAPI
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm

app = FastAPI(swagger_ui_parameters={"persistAuthorization": True})
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")


@app.post("/token")
def login(form: Annotated[OAuth2PasswordRequestForm, Depends()]):
    # 動作確認用：OAuth2PasswordBearerはトークンを取り出すだけで検証しない。
    # 本番では発行時にパスワードを検証して署名付きトークンを返し、受信側でも署名と期限を検証する
    return {"access_token": form.username, "token_type": "bearer"}


@app.get("/me")
def read_me(token: Annotated[str, Depends(oauth2_scheme)]):
    return {"token": token}
```

トークン無しで `/me` を叩くと401と `{"detail": "Not authenticated"}` が返ります。`persistAuthorization` を `True` にすると、ブラウザを再読み込みしても入力したトークンが消えません（Swagger UIの既定は `false`）。

## Swagger UIの説明・タグ・入力例の設定

Swagger UIに表示される文言は、すべてコード側の書き方で決まります。画面を直接編集する手段は無いので、ドキュメントの質はパス操作の引数とPydanticモデルの書き方で上げます。

```
from typing import Annotated

from fastapi import Body, FastAPI
from pydantic import BaseModel, Field

tags_metadata = [
    {"name": "users", "description": "ユーザーの登録と参照"},
    {"name": "items", "description": "商品の操作"},
]

app = FastAPI(
    title="在庫API",
    version="1.2.0",
    summary="社内向け在庫管理API",
    openapi_tags=tags_metadata,
)


class Item(BaseModel):
    name: str = Field(examples=["ボールペン"])
    price: int = Field(gt=0, description="税込価格（円）", examples=[120])


@app.post("/items", tags=["items"], summary="商品を登録する", status_code=201)
def create_item(
    item: Annotated[Item, Body(openapi_examples={
        "normal": {"summary": "通常", "value": {"name": "ノート", "price": 200}},
        "invalid": {"summary": "価格0は422", "value": {"name": "ノート", "price": 0}},
    })],
) -> Item:
    """商品を1件登録します。

    - **price** は1以上
    """
    return item


@app.get("/users/{user_id}", tags=["users"], deprecated=True)
def read_user(user_id: int):
    return {"user_id": user_id}


@app.get("/healthz", include_in_schema=False)
def healthz():
    return {"ok": True}
```

| 書き方                              | Swagger UIでの出方    |
| -------------------------------- | ----------------- |
| FastAPI(title, version, summary) | 画面最上部の見出し         |
| `tags=["items"]`                 | タグごとの折りたたみ単位      |
| openapi\_tags                    | タグの説明文と表示順        |
| summary                          | エンドポイント行の短い説明     |
| docstring                        | 展開後の説明（Markdown可） |
| Body(openapi\_examples=…)        | 例の切り替えドロップダウン     |
| deprecated=True                  | 取り消し線で非推奨表示       |
| include\_in\_schema=False        | 画面にもスキーマにも出ない     |

上のコードでは `items` のルートを先に定義していますが、画面では `openapi_tags` の並びどおり `users` が先に出ます。タグの並びを業務の流れに合わせたいときはここで決めます。`openapi_examples` は複数の例を「正常系」「422になる例」のように並べられるので、受け手が境界値をその場で試せます。ヘルスチェックのように利用者に見せる必要がないものは `include_in_schema=False` で外します。外部に渡すAPI仕様書としてどこまで書き込むかは[API設計書の書き方｜記載項目チェックリストとOpenAPIサンプル・レビュー観点](/tech/details/4068/)の観点が使えます。

## swagger\_ui\_parametersの既定値と画面設定

`swagger_ui_parameters` に渡した辞書は、Swagger UIの設定としてそのままHTMLに書き出されます。FastAPIは何も渡さなくても次の5つを既定で入れています（`fastapi/openapi/docs.py` の `swagger_ui_default_parameters`）。

```
{
    "dom_id": "#swagger-ui",
    "layout": "BaseLayout",
    "deepLinking": True,
    "showExtensions": True,
    "showCommonExtensions": True,
}
```

渡した辞書はこの既定に上書きでマージされます。よく使うキーは次のとおりです。値の意味と既定値は[Swagger UIの公式設定一覧](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)に従います。

| キー                       | Swagger UI既定 | 変えると                 |
| ------------------------ | ------------ | -------------------- |
| docExpansion             | `"list"`     | `"none"`で全部畳む        |
| defaultModelsExpandDepth | 1            | \-1で下部のSchemas欄を隠す   |
| persistAuthorization     | false        | 再読み込みでもトークン保持        |
| filter                   | false        | タグの絞り込み欄を出す          |
| tryItOutEnabled          | false        | 最初から入力欄を開く           |
| displayRequestDuration   | false        | 応答時間（ms）を表示          |
| syntaxHighlight.theme    | `"agate"`    | `"obsidian"`等の7種から選ぶ |

```
app = FastAPI(
    swagger_ui_parameters={
        "docExpansion": "none",
        "defaultModelsExpandDepth": -1,
        "filter": True,
        "syntaxHighlight.theme": "obsidian",
    }
)
```

`syntaxHighlight.theme` はキー名にドットを含む文字列のまま渡します。`"syntaxHighlight": False` にすると色付けそのものを切れるので、大きなレスポンスで画面が重いときに効きます。関数を渡す設定（リクエストを書き換える `requestInterceptor` など）はJSONにできないため、この引数では指定できません。`get_swagger_ui_html` も設定をJSONに変換して書き出すため、関数を使いたい場合は `docs_url=None` にして、JavaScriptの関数を直接書いたHTMLを自前のルートから返します。

## 本番環境でのSwagger UIの非公開化と閲覧制限

### docs\_url・redoc\_url・openapi\_urlの無効化範囲

「本番では `docs_url=None, redoc_url=None` にする」という手順が広く紹介されていますが、これで消えるのは画面だけです。FastAPI 0.143.0で各設定の応答を確かめた結果が次の表です。

| 設定                              | /docs | /redoc | /openapi.json |
| ------------------------------- | ----- | ------ | ------------- |
| 既定                              | 200   | 200    | 200           |
| docs\_url=None, redoc\_url=None | 404   | 404    | 200           |
| openapi\_url=None               | 404   | 404    | 404           |

画面を消しても、スキーマのJSONには公開対象のエンドポイント・パラメータ・モデルが残り、ネットワークや認証で制限していなければ誰でも取得できます。仕様を外に出したくないなら `openapi_url=None` を使います。FastAPIのソースでも、`openapi_url` が無いときは `/docs` と `/redoc` を登録しない作りになっています。

### 環境変数によるOpenAPI公開設定の切り替え

[公式のConditional OpenAPI](https://fastapi.tiangolo.com/how-to/conditional-openapi/)は、設定クラスに `openapi_url` を持たせ、環境変数で空にする方法を示しています。`pydantic-settings` は `fastapi[standard]` に含まれます。

```
from fastapi import FastAPI
from pydantic_settings import BaseSettings


class Settings(BaseSettings):
    openapi_url: str = "/openapi.json"


settings = Settings()
app = FastAPI(openapi_url=settings.openapi_url)
```

```
OPENAPI_URL= fastapi run main.py
```

空文字を渡すと `/openapi.json`・`/docs`・`/redoc` の3つとも404になります。同じ公式ページは、ドキュメントを隠してもAPIの安全性は上がらない（エンドポイントは残る）と明記しています。隠すのは仕様を外に出さないためであって、認可の代わりにはなりません。

### Basic認証によるドキュメントの閲覧制限

社内の開発者や連携先など、資格情報を渡した相手にだけ仕様を見せたい場合は、自動生成を止め、認証付きのルートで同じ画面とスキーマを返します。

```
import secrets
from typing import Annotated

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.openapi.utils import get_openapi
from fastapi.security import HTTPBasic, HTTPBasicCredentials

app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)
security = HTTPBasic()


def verify(cred: Annotated[HTTPBasicCredentials, Depends(security)]):
    ok_user = secrets.compare_digest(cred.username.encode(), b"admin")
    ok_pass = secrets.compare_digest(cred.password.encode(), b"change-me")
    if not (ok_user and ok_pass):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            headers={"WWW-Authenticate": "Basic"},
        )


@app.get("/docs", include_in_schema=False)
def docs(_: Annotated[None, Depends(verify)]):
    return get_swagger_ui_html(openapi_url="/openapi.json", title="API docs")


@app.get("/openapi.json", include_in_schema=False)
def openapi_schema(_: Annotated[None, Depends(verify)]):
    return get_openapi(title="API", version="1.0.0", routes=app.routes)
```

資格情報なしでは `/docs` も `/openapi.json` も401（`WWW-Authenticate: Basic` 付き）になり、ブラウザが入力ダイアログを出します。認証が通ると画面もスキーマも返り、スキーマには業務のエンドポイントだけが載ります。`secrets.compare_digest` を使うのは、文字列比較の処理時間から正解を推測される攻撃を避けるためです。実運用ではユーザー名とパスワードを環境変数から読み、TLSの内側で使ってください。

判断の目安は次のとおりです。外部の開発者に使ってもらう公開APIなら、利用者が仕様を参照できるように隠さず出します。社内・取引先限定のAPIはBasic認証かVPN内に限定します。スキーマの存在自体を知られたくない管理用APIは `openapi_url=None` にし、仕様書は別途管理します。

## Swagger UIが表示されない・読み込めないときの原因

### プロキシ配下で「Failed to load API definition」

Nginxなどで `/api` 配下にFastAPIを置くと、画面は出るのにスキーマが読めないことがあります。Swagger UIはブラウザから `/openapi.json` を取りに行くので、プレフィックスの付かないドメイン直下を叩いて404になるためです（[公式のBehind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/)）。プロキシがプレフィックスを取り除いてFastAPIへ転送する構成では、`root_path` を指定すると解消します。

```
fastapi run main.py --root-path /api
```

`FastAPI(root_path="/api")` で確かめると、Swagger UIのHTMLが読み込むURLは `/api/openapi.json` に変わり、スキーマにも `servers: [{"url": "/api"}]` が入るので、Try it outの送信先も揃います。

### Dockerコンテナ内の待ち受けアドレス

`fastapi dev` の待ち受けは既定で `127.0.0.1`、`fastapi run` は `0.0.0.0` です（`--help` の表示）。コンテナ内で `fastapi dev` を動かすとホスト側のブラウザから届かないので、`--host 0.0.0.0` を付けるか `fastapi run` を使います。Dockerfileやcomposeでの本番構成は[FastAPI×ReactのDocker本番デプロイ｜uv対応Dockerfileとcompose構成](/tech/details/2980/)、Uvicornの起動オプションは[Uvicornとは？FastAPIを動かすPython製ASGIサーバーの基礎から本番デプロイまで](/tech/details/4843/)にまとめています。

### CDN遮断時の描画不良と静的ファイルの自前配信

FastAPIが返すSwagger UIのHTMLは、本体のJavaScriptとCSSを `https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/` から読み込みます。閉域網やCDNを遮断したネットワークでは、HTMLは200で返るのに画面が描画されません。

このURLはメジャー番号の `@5` だけを指定しているため、実際に読まれるのはその時点の5系の最新版（2026年10月12日時点で5.33.1）です。FastAPIを更新していなくても、Swagger UIの版はある日変わります。画面の見え方を固定したい場合や、Content-Security-Policyで読み込み元を絞る場合は、版を固定したURLか自前の静的ファイルを指定します。

```
from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)
from fastapi.staticfiles import StaticFiles

app = FastAPI(docs_url=None)
# static/ に swagger-ui-bundle.js と swagger-ui.css を置く
app.mount("/static", StaticFiles(directory="static"), name="static")


@app.get("/docs", include_in_schema=False)
def custom_docs():
    return get_swagger_ui_html(
        openapi_url=app.openapi_url,
        title=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="/static/swagger-ui-bundle.js",
        swagger_css_url="/static/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()
```

静的ファイルは `https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.33.1/swagger-ui-bundle.js` のように版を固定したURLから取得しておきます。外部へ出られる環境で版だけ固定したいなら、`swagger_js_url` と `swagger_css_url` にこのCDNのURLを直接渡せば足ります。手順全体は[公式のCustom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/)にあります。

## サブアプリによるSwagger UIとスキーマの分割

エンドポイントが数百本になると、1枚のSwagger UIでは目的のAPIを探しにくくなります。FastAPIはアプリごとにSwagger UIを持つので、機能単位のサブアプリを `mount` すると画面が分かれます。

```
from fastapi import FastAPI

app = FastAPI(title="Base")
admin = FastAPI(title="Admin")


@admin.get("/users")
def list_users():
    return []


app.mount("/admin", admin)
```

この構成では `/admin/docs` に管理用のSwagger UIが独立して出て、読み込むスキーマは `/admin/openapi.json` になります。一方、親アプリの `/openapi.json` には `/admin/users` が含まれません。スキーマから型定義やクライアントを生成している場合、mountで分けると生成対象も分かれる点に注意してください。画面を探しやすくしたいだけなら、まずはタグと `filter` で足ります。mountは認証方式や公開範囲が機能ごとに違うときに使います。

## PythonでSwagger UIを使う方法：フレームワーク別の違い

PythonでSwagger UIを出す方法はフレームワークで異なります。FastAPIは本体に組み込まれていますが、DjangoとFlaskは追加パッケージが必要です。

| フレームワーク               | Swagger UIの出し方                             | 最新版（PyPI）        |
| --------------------- | ------------------------------------------ | ---------------- |
| FastAPI               | 標準で /docs                                  | 0.143.0          |
| Django REST framework | drf-spectacular の SpectacularSwaggerView   | 0.30.0           |
| Flask                 | flask-smorest の OPENAPI\_SWAGGER\_UI\_PATH | 0.47.0           |
| Flask系                | APIFlask は標準で /docs                        | 3.1.2            |
| Flask                 | flasgger                                   | 0.9.7.1（2023年5月） |

flasggerは安定版の最終リリースが2023年5月（開発版も2023年6月）で止まっているので、新規に採用するならflask-smorestかAPIFlaskを選びます。違いはモデルとエンドポイントの結び付け方にあります。FastAPIは関数の引数の型ヒントとPydanticモデルからそのままスキーマを作ります。APIFlaskもPydanticに対応していますが、入出力のスキーマはデコレーターで指定します。drf-spectacularはシリアライザから、flask-smorestはmarshmallowのスキーマから仕様を組み立てます。OpenAPIの仕様そのものとSwaggerとの名前の関係は[OpenAPIとは？Swaggerとの違いと仕様書(YAML/JSON)の書き方｜3.0・3.1・3.2の差分](/tech/details/10408/)で整理しています。

既存システムとの連携を前提にAPIの設計からまとめて任せたい場合は、[一想のAPI開発・システム連携](/service/system/api/)でも対応しています。

## よくある質問

### FastAPIのSwagger UIのURLはどこですか？

既定は `http://127.0.0.1:8000/docs` です。`fastapi dev` の起動ログに「Documentation at」として表示されます。`docs_url` を変えていればそのパス、`root_path` を設定したプロキシ配下ではプレフィックス付きのパスになります。

### /docsのURLを変更するにはどうしますか？

`FastAPI(docs_url="/documentation")` のように渡します。ReDocは `redoc_url`、スキーマは `openapi_url` で同じように変えられます。`openapi_url` を変えた場合も、Swagger UIは新しいURLを自動で読みに行きます。

### Swagger UIとReDocはどう違いますか？

どちらも同じ `/openapi.json` から作られます。Swagger UIは「Try it out」でその場でリクエストを送れる操作向けの画面で、ReDocは3ペインの読みやすさを優先した閲覧専用の文書です。その場で試す開発中の確認にはSwagger UI、読み物として渡す外部向けの仕様共有にはReDocが向いています。

### FastAPIが出力するOpenAPIのバージョンはいくつですか？

FastAPI 0.143.0の既定はOpenAPI 3.1.0です。3.1に対応していない古いツールに渡す必要があるときは `app.openapi_version = "3.0.2"` のように上書きできます。ただし変わるのはバージョン表記だけで、スキーマの中身は3.0形式へ変換されません。3.1で追加された書き方が混じっていれば相手側で検証エラーになるため、変更後にそのツールでスキーマを検証してください。

### swagger\_ui\_parametersで設定できないものはありますか？

JSONにできない値、つまりJavaScriptの関数を渡す設定は指定できません。`requestInterceptor` などを使いたい場合は、`docs_url=None` にして、関数を直接書いたHTMLを自前のルートから返します。

## 関連記事

- [FastAPIとは｜最短で動かす手順とasync/defの使い分け【2026年版】](/tech/details/3859/)
- [Swaggerとは：Editor・UIをDockerで動かす手順とOpenAPI 3.2対応の現況](/tech/details/17451/)
- [OpenAPIとは？Swaggerとの違いと仕様書(YAML/JSON)の書き方｜3.0・3.1・3.2の差分](/tech/details/10408/)
- [Uvicornとは？FastAPIを動かすPython製ASGIサーバーの基礎から本番デプロイまで](/tech/details/4843/)
- [FastAPI×ReactのDocker本番デプロイ｜uv対応Dockerfileとcompose構成](/tech/details/2980/)

---

出典: [FastAPIのSwagger UI（/docs）の使い方｜表示・設定・本番で隠す手順【2026年版】](<https://www.issoh.co.jp/tech/details/2246/>)（株式会社一創）
