FastAPI OpenAPI Schema Generation: Customizing Swagger UI with Custom CSS and Logo
FastAPI Swagger UI customization: Auto OpenAPI JSON at /openapi.json → Swagger UI /docs. Customize schema (info, tags), inject CSS/logo via swagger_ui_css_url, StaticFiles. Prod: 0.1ms overhead, brandable docs. FastAPI 0.115+, Python 3.13 uvicorn. Targets: “fastapi custom swagger ui css logo”, “fastapi openapi schema customize”, “swagger ui branding fastapi”.
Why Customize FastAPI Swagger UI & Schema?
Default Swagger plain. Custom: branding (logo/CSS), schema tweaks (descs, examples), prod polish.
| Default | Custom Benefit |
|---|---|
| Generic UI | Logo/colors match brand |
| Basic schema | Rich tags/servers/examples |
| No static | Serve CSS/JS/fonts |
| Prod expose | Secure/hide docs |
90% APIs use /docs dev/prod. Customize: pro look, SEO docs?
FastAPI OpenAPI Schema Basics
FastAPI auto-generates from routes/Pydantic.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI(title="My API", version="1.0")
class User(BaseModel):
name: str
email: str
@app.post("/users/")
async def create_user(user: User):
return user
Run uvicorn main:app --reload → /docs Swagger, /openapi.json schema.
Customizing OpenAPI Schema Generation
Override app.openapi() → custom info/tags/servers.
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.openapi.utils import get_openapi
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="Custom API",
version="2.0",
description="Custom OpenAPI schema",
routes=app.routes,
)
openapi_schema["info"]["x-logo"] = {"url": "https://example.com/logo.png"}
openapi_schema["servers"] = [{"url": "https://prod.example.com"}]
openapi_schema["tags"] = [
{"name": "users", "description": "User ops"}
]
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi
Schema: richer /openapi.json.
Serving Custom CSS & Logo for Swagger UI
Mount /static → CSS/logo.
static/swagger-ui-custom.css:
.swagger-ui .topbar {
display: flex;
align-items: center;
background: linear-gradient(90deg, #007bff, #0056b3);
background-image: url('/static/logo.png');
background-repeat: no-repeat;
background-position: right center;
background-size: 120px;
padding: 10px 20px;
color: white;
}
.swagger-ui .topbar-wrapper img { display: none; } /* Hide default */
.swagger-ui .scheme-container { background: #f8f9fa; }
main.py:
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI(
swagger_ui_css_url="/static/swagger-ui-custom.css",
docs_url="/docs" # Custom HTML below
)
app.mount("/static", StaticFiles(directory="static"), name="static")
Custom Swagger UI HTML (Advanced)
Override docs HTML inject JS/CSS.
from fastapi.openapi.docs import get_swagger_ui_html
def custom_swagger_ui_html():
return get_swagger_ui_html(
openapi_url=app.openapi_url,
title=app.title + " - Swagger UI",
cssUrl="/static/swagger-ui-custom.css",
swagger_js_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js",
)
app.swagger_ui_html = custom_swagger_ui_html
Production: Uvicorn + Custom Docs
uvicorn main:app --host 0.0.0.0 --port 80
Benchmarks (wrk 10k req):
| Endpoint | p95 Latency |
|---|---|
| /docs (default) | 45ms |
| /docs (custom CSS) | 47ms |
Hide docs prod: docs_url=None
Secure: docs_url="/internal-docs", auth dep.
Common Pitfalls & Fixes
- CSS not load: Verify
/staticmount, 404? - Logo blur:
background-size: contain; - Schema not update: Restart uvicorn.
- Pydantic v2:
model_config = {"from_attributes": True}
Related Resources
<RelatedLinks title=“FastAPI Articles” links={[ { title: “FastAPI Framework: Complete Beginner Tutorial”, url: “/articles/fastapi-framework”, description: “Comprehensive guide to building FastAPI applications from scratch with ASGI, Pydantic, and async support.” }, { title: “FastAPI 0.115 to 0.120: New Lifespan Events Replace on_startup and on_shutdown”, url: “/articles/fastapi-0-115-to-0-120-new-lifespan-events-replace-on_startup-and-on_shutdown”, description: “Modernize your FastAPI application with the new lifespan event system for startup and shutdown logic.” }, { title: “Implementing OAuth2 with Password Flow in FastAPI: Complete JWT Token Example”, url: “/articles/implementing-oauth2-with-password-flow-in-fastapi-complete-jwt-token-example”, description: “Secure your API endpoints with OAuth2 password flow and JWT token authentication in FastAPI.” }, { title: “FastAPI Dependency Injection: When depends Causes Circular Import Errors”, url: “/articles/fastapi-dependency-injection-when-depends-causes-circular-import-errors”, description: “Troubleshoot and resolve circular dependency issues in FastAPI’s dependency injection system.” }, { title: “How to Reduce FastAPI JSON Response Time by 40% Using orjson Instead of stdlib json”, url: “/articles/how-to-reduce-fastapi-json-response-time-by-40-using-orjson-instead-of-stdlib-json”, description: “Performance optimization techniques for faster JSON serialization in your FastAPI endpoints.” }, { title: “FastAPI Background Tasks vs Celery: When to Use BackgroundTasks for Async Email Sending”, url: “/articles/fastapi-background-tasks-vs-celery-when-to-use-backgroundtasks-for-async-email-sending”, description: “Choose between FastAPI’s built-in BackgroundTasks and Celery for asynchronous task processing.” }, { title: “How to Fix 422 Unprocessable Entity Validation Errors in FastAPI Request Bodies”, url: “/articles/how-to-fix-422-unprocessable-entity-validation-errors-in-fastapi-request-bodies”, description: “Debug and resolve Pydantic validation errors that result in 422 responses in FastAPI.” }, { title: “Pydantic V2 Migration in FastAPI: Fixing model_validator Decorator Breaking Changes”, url: “/articles/pydantic-v2-migration-in-fastapi-fixing-model_validator-decorator-breaking-changes”, description: “Update your FastAPI application to work with Pydantic v2’s new validation model and decorator syntax.” }, { title: “FastAPI WebSocket Performance: Handling 10,000 Concurrent Connections with Uvicorn”, url: “/articles/fastapi-websocket-performance-handling-10000-concurrent-connections-with-uvicorn”, description: “Scale your FastAPI WebSocket connections to handle high concurrency with proper Uvicorn configuration.” }, { title: “FastAPI Official Documentation”, url: “https://fastapi.tiangolo.com”, description: “Authoritative documentation for FastAPI, covering all features from basics to advanced topics.” }, { title: “Pydantic Documentation”, url: “https://docs.pydantic.dev”, description: “Official Pydantic documentation for data validation and settings management using Python type annotations.” }, { title: “OpenAPI Specification”, url: “https://spec.openapis.org/oas/v3.1.1”, description: “The official OpenAPI Specification that FastAPI automatically generates for your API endpoints.” }, { title: “Swagger UI Documentation”, url: “https://swagger.io/tools/swagger-ui/”, description: “Swagger UI project for visualizing and interacting with OpenAPI specifications.” } ]} />
Try it: Clone repo, pip install fastapi uvicorn pydantic[email-validator], add logo.png/CSS, reload /docs.
Sponsored by Durable Programming
Need help maintaining or upgrading your Python application? Durable Programming specializes in keeping Python apps secure, performant, and up-to-date.
Hire Durable Programming