# Brython: running Python 3 in the browser without a build step

> Brython is a Python 3 implementation that executes in the browser and exposes the DOM to Python code. It installs with pip or a single script tag, and its limits show up as soon as you need threading, disk access or a small payload.

**brython-dev/brython** — Brython (Browser Python) is an implementation of Python 3 running in the browser

- Repository: https://github.com/brython-dev/brython
- Stars: 6,607 · Forks: 535
- Language: Python
- License: BSD-3-Clause
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/brython-dev-brython

## What Brython solves, and who ends up using it

Brython exists so that a browser page can run Python 3 instead of JavaScript. The README describes it as "an implementation of Python 3 running in the browser, with an interface to the DOM elements and events." That second half is the part that matters. A Python-to-JavaScript compiler gives you Python syntax; Brython also gives you a module named browser whose names map onto browser objects, so document['zone'].value reads an input's contents and alert() opens a dialog.

The audience is narrower than "Python developers". It is people who already have Python and want the page itself written in it: teachers demonstrating Python in a lab with nothing installed, data people who want a chart wired to a form without learning a second language, and anyone porting a small Python utility to a static site. The README's own framing is telling: the first option it offers is "Zero install", a script tag pointing at a CDN. That is the intended on-ramp, not a fallback.

## How the engine, the stdlib bundle and the browser module fit together

The architecture is two JavaScript files plus your Python. brython.js is the core engine, and the README calls it "the core Brython engine". brython_stdlib.js is described as "a bundle of all the files in the standard distribution". The engine parses Python source found in the page and runs it; the stdlib bundle supplies the modules when your code imports them.

That split explains the README's warning. Loading brython.min.js alone "will allow you to use raw python code", but importing from the standard library requires the second file. So the payload you ship is a function of your imports, not of your line count. A page that only manipulates the DOM can skip the bundle; a page that imports json or re cannot.

The Python version is pinned to the release. The README states that since version 3.8.0, Brython implements the Python version with the same major and minor number. Release 3.14.3 therefore tracks Python 3.14. If you need a specific language feature, you are choosing a Brython release, not a Python version independently.

What is left out is deliberate. The README says Brython supports "the modules of the CPython distribution written in Python, except for the features that are not relevant in the browser context (writing on disk for instance)". Modules implemented in C in CPython are not covered by that sentence, so treat the claim as scoped to pure-Python modules rather than to the whole standard library.

## Installing Brython locally and binding a click to a Python function

The fastest path needs no install at all. The README's zero-install example loads the engine from jsDelivr, and version ranges are supported, so brython@3.14 tracks the latest 3.14.x release and brython@3 tracks the latest 3.x.y release.

```html
<script src="https://cdn.jsdelivr.net/npm/brython@3.14.3/brython.min.js">
</script>
<script src="https://cdn.jsdelivr.net/npm/brython@3.14.3/brython_stdlib.js">
</script>
```

Add the second line only when you import standard library modules; the README ties it to that condition.

For a local copy, the README gives a pip route. Run the install, then create a new directory and initialize the distribution there:

```bash
pip install brython
brython-cli install
```

The README states the result includes brython.js, brython_stdlib.js, and a page named demo.html with examples of creating elements, modifying existing ones, drawing graphics and animations, and sending Ajax requests. Open demo.html in a browser to see the engine running before you write anything.

The first real use is the README's own example: a button that reads an input and alerts its value. The Python lives in a script tag whose type is text/python, and the binding is a decorator.

```html
<html>

    <head>
        <script src="/path/to/brython.js"></script>
    </head>

    <body>

        <script type="text/python">
        from browser import bind, document, alert

        @bind(document['mybutton'], 'click')
        def echo(event):
            alert(document["zone"].value)
        </script>

        <input id="zone"><button id="mybutton">click !</button>

    </body>

</html>
```

Clicking the button should show the input's contents in an alert dialog. Note the ordering assumption: the Python looks up document['mybutton'] when the script runs, so the element must already exist in the page.

## Where Brython is the wrong tool

The stdlib bundle is the first real cost. Because the README describes brython_stdlib.js as a bundle of all the files in the standard distribution, you cannot tree-shake it down to the two modules you import. Every visitor downloads the bundle or your imports fail at runtime. For a widget on a content site, that trade is hard to justify against a few lines of JavaScript.

Browser boundaries are the second limit. The README excludes features irrelevant in the browser, and names disk writes. Anything that assumes a filesystem, a socket, or a long-lived process has no home here. If your Python reads a local file or opens a database connection, Brython is not a smaller version of that program; it is a different program.

Startup ordering is the third. The example binds to document['mybutton'] at script execution time, which means the markup has to be in place first. The README does not document a deferred initialization pattern for this, so plan your script placement around it rather than expecting the runtime to wait.

Finally, the README does not document rollback or a version-pinning policy for the CDN ranges beyond noting that jsDelivr supports them. If you ship brython@3, you have opted into whatever 3.x.y arrives next. Pin an exact version if that matters to you, because the README gives no guidance either way.

## Brython against Pyodide, PyScript and Transcrypt

The nearest alternatives differ in what they actually run. Pyodide compiles CPython to WebAssembly, so the interpreter is CPython itself rather than a Python implementation written for the browser. Brython's README describes Brython as "an implementation of Python 3 running in the browser", which is the honest distinction: Brython is a reimplementation, Pyodide is CPython ported. The practical consequence is that Pyodide carries a heavier runtime and a different startup profile, while Brython's two-file model is simpler to reason about.

PyScript sits one level up: it is a framework for running Python in the page that can use Pyodide or another runtime underneath. Choosing PyScript is choosing an orchestration layer over the same problem.

Transcrypt takes the compiler route. It translates Python to JavaScript ahead of time rather than shipping an interpreter and parsing source in the browser. That changes the debugging story and the build story; Brython's README emphasizes that there is nothing to install for the zero-install path, which is the opposite of a compile step.

None of these is strictly better. If you need C extensions, the WebAssembly route is the one that can carry them. If you need a script tag and Python source visible in the page, Brython is the shortest path among the options named here.

## Maintenance, releases and what the licence leaves open

The repository is not archived, and the last push was on 2026-09-15. Releases in the 3.14 line landed on 2026-05-02, 2026-06-13 and 2026-06-19, so the project has shipped three releases in the 3.14 series this year. The default branch is master.

Upgrade cost is tied to the version-numbering rule. Because Brython implements the Python version with the same major and minor number, moving from 3.14.x to a future 3.15 means adopting Python 3.15 semantics at the same time. That couples two upgrades, and it is the main thing to plan for. Within a minor line, the CDN range syntax lets you float or pin, and the README documents both forms.

The licence is BSD-3-Clause, per the repository's LICENCE.txt. That is a permissive licence, and the practical implication is that redistribution inside a product is normally permitted provided the licence conditions are met. This is a description of the licence identifier, not legal advice; read LICENCE.txt and get counsel if your distribution model is unusual. The README does not discuss commercial support, so plan on the mailing list and the issue tracker referenced there.

## Conclusion

Brython fits teams that want Python as the page's scripting language and can accept a sizeable JavaScript payload: load brython.min.js and brython_stdlib.js, or run pip install brython followed by brython-cli install to get brython.js, brython_stdlib.js and demo.html locally. It is the wrong tool when you need threads, filesystem writes, or a small bundle, since the README states the distribution bundles the whole standard library into one file and the supported modules exclude features irrelevant in a browser, disk writes among them. Before committing, verify three things: whether your target browsers load the stdlib bundle within your budget, whether the Python version you need matches the Brython release with the same major and minor number, and whether the modules you import appear in the Lib listing linked from the README.

## FAQ

### How does Brython work?

The page loads brython.js, the core engine, and Python code inside script tags with type="text/python". A second file, brython_stdlib.js, supplies the standard library modules when your code imports them.

### How to include Brython in an HTML file?

Add a script tag pointing at brython.min.js, then write Python inside a script tag with type="text/python". The README's example also loads brython_stdlib.js because it imports from the browser module.

### how to use brython

Load the engine, then write Python in the page. The README's first example binds a click handler with the bind decorator and reads an input's value through document, so DOM work happens with Python objects rather than JavaScript ones.

### brython vs pyodide

Brython is an implementation of Python 3 written to run in the browser, distributed as brython.js plus a stdlib bundle. Pyodide is a different approach that ports CPython itself; the README does not compare the two, so the distinction here rests on how each project describes its own runtime.

### brython vs javascript

Brython runs Python source in the page and exposes DOM elements and events through the browser module, so the same work is written in Python instead of JavaScript. The README does not present it as a replacement for JavaScript, and the stdlib bundle is a payload JavaScript would not add.

## Sources

- [brython-dev/brython on GitHub](https://github.com/brython-dev/brython)
- [Issues](https://github.com/brython-dev/brython/issues)
- [License: BSD-3-Clause](https://github.com/brython-dev/brython/blob/master/LICENSE)
- [README](https://github.com/brython-dev/brython/blob/master/README.md)
- [Releases](https://github.com/brython-dev/brython/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/brython-dev-brython
