Seamless Swagger UI integration for Python web frameworks. A unified, framework-agnostic API for adding interactive OpenAPI documentation to your Python applications with automatic framework detection.
Note: This is a maintained fork of PWZER/swagger-ui-py.
Status: Production-ready, actively maintained Python: 3.9, 3.10, 3.11, 3.12 Swagger UI: v5.25.3 Swagger Editor: v4.14.6
- Framework Agnostic - Single API works across 9+ Python frameworks
- Auto-Detection - Automatically detects your framework, zero configuration needed
- Multiple Config Sources - YAML/JSON files, remote URLs, Python dicts, or strings
- Swagger Editor - Optional inline spec editor for live documentation editing
- Static Assets - Automatic CSS, JS, images, and icons serving
- Customization - Custom CSS, Swagger UI parameters, OAuth2 configuration
- Well-Tested - 50+ test cases across all supported frameworks
Check supported frameworks:
python3 -c "from swagger_ui import supported_list; print(supported_list)"
# Output: ['flask', 'tornado', 'sanic', 'aiohttp', 'quart', 'starlette', 'falcon', 'bottle', 'chalice']pip install swagger-ui-pythonfrom flask import Flask
from swagger_ui import api_doc
app = Flask(__name__)
# Auto-detects Flask and registers routes
api_doc(app, config_path='./openapi.yaml')
if __name__ == '__main__':
app.run(debug=True)
# Visit: http://localhost:5000/api/docimport tornado.ioloop
from tornado.web import Application
from swagger_ui import api_doc
app = Application()
# Auto-detects Tornado and registers routes
api_doc(app, config_path='./openapi.yaml', url_prefix='/api/doc')
if __name__ == '__main__':
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
# Visit: http://localhost:8888/api/docOption A: YAML/JSON File
api_doc(app, config_path='./openapi.yaml')Option B: Remote URL (requires CORS)
api_doc(app, config_url='https://petstore.swagger.io/v2/swagger.json')Option C: Python Dict
config = {
"openapi": "3.0.1",
"info": {"title": "My API", "version": "1.0.0"},
"paths": { ... }
}
api_doc(app, config=config)Option D: JSON/YAML String
spec_string = '{"openapi":"3.0.1","info":{"title":"My API"},...}'
api_doc(app, config_spec=spec_string)Option E: External Endpoint
api_doc(app, config_rel_url='/swagger.json') # App provides endpointapi_doc(
app,
config_path='./openapi.yaml', # Config source
url_prefix='/api/doc', # Internal route path (default: '/api/doc')
base_url=None, # External URL for assets (defaults to url_prefix)
title='API Documentation', # HTML page title
editor=False, # Enable spec editor
custom_css='https://cdn.../style.css', # Custom CSS
host_inject=True, # Auto-inject request host
)When deploying behind a reverse proxy, you may need to separate internal route registration from external URL paths.
Common scenario: Reverse proxy routes /api/* to your backend service at root /
The Problem:
Without base_url, Swagger UI generates incorrect asset URLs:
api_doc(app, config_path='./openapi.yaml', url_prefix='/docs')- Backend registers routes at
/docs✓ - Browser requests
/api/docs→ proxy routes to backend/docs✓ - But Swagger UI generates links like
/docs/static/swagger-ui.css - Browser requests
/docs/static/swagger-ui.css→ 404 ✗ (missing/apiprefix)
The Solution:
Use base_url to include the proxy path prefix in generated URLs:
api_doc(
app,
config_path='./openapi.yaml',
url_prefix='/docs', # Backend registers routes here
base_url='/api/docs', # Browser URLs include proxy prefix
)- Backend registers routes at
/docs(unchanged) - Swagger UI generates links like
/api/docs/static/swagger-ui.css✓ - Browser requests
/api/docs/static/swagger-ui.css→ proxy routes to backend/docs/static/swagger-ui.css✓
Key distinction:
url_prefix- Where your app registers routes (backend/app-side)base_url- Path prefix for URLs in HTML (browser/client-side, defaults tourl_prefix)
parameters = {
"deepLinking": "true",
"displayRequestDuration": "true",
"layout": "\"StandaloneLayout\"",
"plugins": "[SwaggerUIBundle.plugins.DownloadUrl]",
}
api_doc(app, config_path='./openapi.yaml', parameters=parameters)See Swagger UI Parameters for all options.
oauth2_config = {
"clientId": "\"your-client-id\"",
"clientSecret": "\"your-secret\"",
"realm": "\"your-realm\"",
"appName": "\"your-app\"",
"scopeSeparator": "\" \"",
"scopes": "\"openid profile\"",
}
api_doc(app, config_path='./openapi.yaml', oauth2_config=oauth2_config)See OAuth2 Configuration for details.
Still supported for backward compatibility:
from swagger_ui import flask_api_doc, tornado_api_doc, sanic_api_doc
# Same as api_doc(app, ...) but explicit
flask_api_doc(app, config_path='./openapi.yaml')
tornado_api_doc(app, config_path='./openapi.yaml')
sanic_api_doc(app, config_path='./openapi.yaml')The library automatically creates these routes (at url_prefix=/api/doc):
GET /api/doc- Interactive Swagger UI documentationGET /api/doc/swagger.json- OpenAPI specification (JSON)GET /api/doc/editor- Swagger Editor (ifeditor=True)GET /api/doc/static/{path}- Static assets (CSS, JS, images)
For details on writing OpenAPI specifications:
- OpenAPI 3.0 Guide
- OpenAPI 3.1 Spec
- Swagger Editor - Interactive spec editor
To update to newer versions:
tox -e update
# or
python tools/update.py --ui-version=v5.25.3 --editor-version=v4.14.6To add support for a new framework:
- Create
swagger_ui/handlers/{framework}.pyfollowing the handler interface - Implement
handler(doc)andmatch(doc)functions - Add tests in
test/{framework}_test.py - Update README with framework name
- Auto-discovery will handle the rest
See Code Standards for detailed guidelines.
Pass custom parameters and OAuth2 configuration through the api_doc() function for full control over Swagger UI behavior.
Full documentation available in the ./docs directory:
- Project Overview & PDR - Vision, goals, requirements
- Codebase Summary - Module structure and responsibilities
- Code Standards - Coding conventions and patterns
- System Architecture - Design patterns and data flow
- Project Roadmap - Planned improvements and timeline
# Clone repository
git clone https://github.com/SkyTik/swagger-ui-python.git
cd swagger-ui-python
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
make pytest
# Format code
make format
# Build wheel
make whlmake pytest # Run all tests
make format-check # Check code style
make format # Auto-format codemake whl # Build wheel
make upload # Upload to PyPIFramework not detected:
- Ensure framework is installed
- Try explicit
app_typeparameter:api_doc(app, app_type='flask', ...)
Config not loading:
- Check file path exists and is readable
- Validate YAML/JSON format using Swagger Editor
- Check CORS headers if using remote URL
Routes not registered:
- Ensure
api_doc()called before app starts - Check
url_prefixdoesn't conflict with existing routes - Verify framework-specific setup (e.g.,
app.register_blueprint()for Flask)
For more help:
- Check examples/ directory for working samples
- Review GitHub Issues
- Read framework-specific documentation
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure tests pass:
make pytest - Format code:
make format - Submit a pull request
See Code Standards for contribution guidelines.
Licensed under the Apache License 2.0. See LICENSE file for details.
- Issues: GitHub Issues
- Project: SkyTik/swagger-ui-python
- PyPI: swagger-ui-python