Library / SDK
bottlepy/bottle avatar
bottlepy/bottle

Bottle: A Single-File Python WSGI Micro-Framework

bottle.py is a fast and simple micro-framework for python web-applications.

8,795 stars1,511 forksPythonMIT

At a glance

What is it?
Bottle is a Python web framework that ships as one file with no dependencies beyond the standard library, making it the smallest option for serving HTTP from a Python script without a complex project setup.
Who is it for?
Bottle is the right tool for small services, internal utilities, embedded HTTP endpoints, and teaching contexts where a single-file deployment matters. It is not the right tool for applications that need built-in session management, database abstractions, form validation, or an admin interface.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 12 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One File, No Dependencies, Full HTTP

Bottle's defining constraint is that it is a single Python module: `bottle.py`. The only dependency is the Python standard library. This makes it deployable by dropping one file into a directory, which matters for embedded systems, scripts that need a quick HTTP interface, or environments where installing packages is restricted.

The framework targets Python 3.9 and above and is classified as Development Status 6 (Mature) in its PyPI metadata. It has been under active development since its initial release and reached its current API shape over many years of incremental improvement. The last push to the repository was on 2026-09-18.

Bottle covers four core concerns: request routing, response templates, HTTP utility access, and a built-in development server. It does not provide session management, database integration, authentication, or form validation out of the box.

Routing and the @route Decorator

Bottle's routing maps URL patterns to Python functions using the `@route` decorator. Dynamic URL components are written inside angle brackets:

python
from bottle import route, run, template

@route('/hello/<name>')
def index(name):
    return template('<b>Hello {{name}}</b>!', name=name)

run(host='localhost', port=8080)

This is the complete example from the README. Saving it to a file and running it starts a server on port 8080. Visiting `http://localhost:8080/hello/world` renders the template with `name` bound to `world`.

The decorator syntax is identical to Flask's `@app.route`, which means developers familiar with Flask can read Bottle code without learning new patterns. The substantive difference is that Bottle has no application object by default; routes are registered on a global default application. Multiple application objects are supported, but the default single-application model is what the documentation targets.

The framework handles clean and dynamic URLs. The README references support for both static and dynamic path segments but does not document the full URL pattern syntax inline; that is covered in the online documentation at bottlepy.org.

Templates: Built-In Engine and Third-Party Options

Bottle ships with its own template engine that uses `{{variable}}` syntax for output and `% for`, `% if` blocks for logic. This engine requires no additional packages.

For teams that already use Mako, Jinja2, or Cheetah templates, Bottle provides adapters for all three. Switching the template engine does not change the routing or request handling code. The adapter layer accepts the same `template()` call but delegates rendering to the configured engine.

This means a project can start with the built-in engine, which has zero additional dependencies, and migrate to Jinja2 later without rewriting routes or views. The trade-off is that the built-in engine is less feature-complete than Jinja2; it handles the basic use cases but lacks Jinja2's macro system, inheritance model, and filters library.

Installing Bottle for Development and Production

Installation for development:

bash
pip install bottle

For production, Bottle's built-in development server is not suitable for concurrent load. The README lists adapters for gunicorn, paste, and cheroot. A gunicorn deployment wraps the bottle application object directly. The `bottle` command-line entry point is registered in the package scripts, which allows using `bottle` directly in some contexts. The full list of WSGI-capable servers that Bottle can delegate to is documented on bottlepy.org rather than in the README.

Because Bottle is a single file, an alternative installation method is to download `bottle.py` directly into the project directory. This avoids a package manager entirely and works in environments where `pip` is not available. The README links to the raw GitHub URL for the latest development version.

Limitations and When Bottle Is the Wrong Choice

Bottle's single-file architecture is its strength and its ceiling. Everything beyond routing, templating, and basic HTTP utilities requires third-party code. There is no built-in session handling, no CSRF protection, no ORM integration, no authentication middleware, and no admin interface.

For multi-developer projects that need structure across controllers, models, and views, Bottle provides no conventions or scaffolding. Each team must impose its own layout. Flask, by contrast, has a well-established application factory pattern, blueprints for modular routing, and a plugin ecosystem with maintained packages for sessions, forms, and database integration.

Bottle's template engine, while convenient, is less capable than Jinja2. Template inheritance (the ability to define a base layout and override blocks in child templates) is not supported in the built-in engine. Teams that need more than simple variable substitution and basic loops need to integrate a third-party template engine.

The framework has a narrow scope by design. If the application grows beyond a few endpoints into something requiring middleware chains, per-endpoint authentication, or complex response pipelines, the lack of extension points in Bottle's core becomes a constraint.

Bottle Against Flask

Flask is the most common comparison. Both are Python WSGI micro-frameworks with decorator-based routing. Flask requires at least Werkzeug and Jinja2 as dependencies; Bottle requires none. Flask provides application factories, blueprints, request context locals, and a large ecosystem of official and community extensions. Bottle provides a minimal surface area with no extension framework.

The practical difference shows at scale. A two-endpoint internal API or a webhook handler fits Bottle well: one file, standard library only, no package management overhead for the dependencies. A web application that adds user accounts, email confirmation, background jobs, and an admin dashboard fits Flask better because the extension ecosystem (Flask-Login, Flask-Mail, Celery integration, Flask-Admin) handles those concerns without custom code.

Bottle's MIT license allows unrestricted use in commercial products. The logo is explicitly not covered by the MIT license, but the code and documentation are.

Editorial conclusion

Bottle is the right tool for small services, internal utilities, embedded HTTP endpoints, and teaching contexts where a single-file deployment matters. It is not the right tool for applications that need built-in session management, database abstractions, form validation, or an admin interface. Before building anything significant with it, confirm that the 0.13.x series covers your routing and template needs, since Bottle's scope is deliberately narrow.

Frequently asked questions

How does Bottle differ from Flask for small projects?

Bottle ships as a single file with no dependencies beyond the Python standard library, while Flask requires at least Werkzeug and Jinja2. For a small internal service or webhook handler, Bottle has less installation overhead. Flask gains the advantage when a project needs its extension ecosystem (sessions, forms, authentication).

Can Bottle serve a production application behind gunicorn?

Yes. Bottle includes adapters for production WSGI servers including gunicorn, paste, and cheroot. The built-in development server is not suitable for concurrent production traffic, but wrapping the Bottle application with gunicorn or another WSGI server is a supported deployment pattern.

What template engines does Bottle support?

Bottle ships with its own built-in template engine that uses `{{variable}}` syntax and `%` blocks for logic. It also provides adapters for Mako, Jinja2, and Cheetah, so teams that prefer those engines can use them without changing the routing code.

Official sources

  1. bottlepy/bottle on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/bottlepy-bottle.svg)](https://hysenlabs.com/projects/bottlepy-bottle)