FastAPI publishes Swagger UI at /docs, ReDoc at /redoc and the OpenAPI schema at /openapi.json by default. Pass openapi_url=None when you create the app to disable the schema and both interfaces. Pass docs_url=None or redoc_url=None to remove just one interface.
What each setting does
| Resource | Default URL | Parameter | Disable with |
|---|---|---|---|
| OpenAPI schema | /openapi.json | openapi_url | None |
| Swagger UI | /docs | docs_url | None |
| ReDoc | /redoc | redoc_url | None |
The FastAPI documentation notes that setting openapi_url to None also disables the interfaces that read it. That makes it the single switch for a clean production build.
import os
from fastapi import FastAPI
is_prod = os.getenv("APP_ENV") == "prod"
app = FastAPI(openapi_url=None if is_prod else "/openapi.json")
Options short of full removal
You can rename the schema path, for example to a versioned location, or keep the schema and drop an interface:
app = FastAPI(docs_url="/documentation", redoc_url=None)
Renaming is not security. It only stops the laziest guesses. If partners need the docs, serve them behind your normal authentication instead.
Steps
- Decide which environments need the docs. Development usually does, production often does not.
- Drive the setting from an environment variable, as above, so no code changes between stages.
- Deploy, then request /docs, /redoc and /openapi.json from outside the network.
- Confirm each returns 404.
- If you expose docs to partners, check how the Authorize button works. In FastAPI, OAuth2PasswordBearer only reads the Authorization header and returns 401 if a bearer token is missing, and tokenUrl only declares where to get a token, it does not create the endpoint.
- Add a CI test that fetches the three paths against the production configuration.
A note on staging
Staging often has real looking data and an internet facing address. If you disable the docs in production but leave them on in staging, you have only moved the exposure. Apply the same environment variable logic to both, and keep a private way for your own team to read the schema, such as the exported file from CI.
What a scanner loses
If you disable the schema, an API scanner has no spec to import and must discover routes by crawling or from a spec you supply separately. For scheduled scans, keep a spec file in your repository and feed it to the scanner in the pipeline. That way the production app stays quiet and your testing stays complete. More on that in what an API scanner needs before the first run.
Try it yourself
Click through it at your own pace, or open it full screen. Look at what the scan needs as input and where it gets it.
Safeguard's SBOM and dependency scanning inventories FastAPI and its Python dependencies, and a free scan is available.
Quick check
Does openapi_url=None break my API?
No. It only removes the documentation endpoints. Your routes keep working.
Is /docs a vulnerability?
It is an exposure of your route map, not a flaw in itself. Weak authorization on listed routes is the real risk.
Sources
Last reviewed: 19 October 2026.