The go-to resource for upgrading Python, Django, Flask, and your dependencies.

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.

DefaultCustom Benefit
Generic UILogo/colors match brand
Basic schemaRich tags/servers/examples
No staticServe CSS/JS/fonts
Prod exposeSecure/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):

Endpointp95 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 /static mount, 404?
  • Logo blur: background-size: contain;
  • Schema not update: Restart uvicorn.
  • Pydantic v2: model_config = {"from_attributes": True}

<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