image

MOB³ - Because browsers got too complicated

⚠ Warning: MOB³ is not a secure browser in any way. It has no sandboxing, process isolation, site isolation, CSP enforcement, certificate UI or security hardening, and it has not been audited. Page JavaScript runs in a hobby-grade engine. Do not use MOB³ to log in to accounts, enter passwords, make payments, or handle confidential data. Use it at your own risk.

MOB³ is a small terminal web browser written in Go. It fetches pages over HTTP(S), renders HTML and a practical CSS subset in 24-bit color, and shows images inline with kitty or iTerm2 graphics, falling back to half-block art.

JavaScript runs through the pure-Go goja engine; there are no other third-party modules. Requires Go 1.27 or newer. The project page is https://mob3.net.

Try it with Docker:

docker run --rm -it ghcr.io/mob3net/mob3

Run

make run

With no URL, MOB³ opens about:start, which shows the project icon, the security warning, and links for getting started.

Build

make
./bin/mob3 https://example.com

Or directly:

mkdir -p bin && CGO_ENABLED=0 go build -o bin/mob3 ./cmd/mob3

The result is a single static binary. Dependencies are vendored under vendor/, so the build needs no network access. When stdin/stdout are not a terminal, MOB³ automatically falls back to dump mode.

Versioning

Git tags such as v1.2.3 are the source of truth for releases. mob3 -version prints the embedded version. Local builds show dev unless a version is provided:

make VERSION=v1.2.3
./bin/mob3 -version

The release workflow injects the tag into both the binaries and the Docker image. For a local Docker build:

docker build --build-arg VERSION=v1.2.3 -t mob3 .

Docker

Build the image:

make docker
# or
docker build -t mob3 .

Run it interactively:

docker run --rm -it mob3 https://example.com

Without -it, stdin is not a terminal and MOB³ uses dump mode:

docker run --rm mob3 -dump -width 100 https://example.com

The image is a non-root Alpine image with CA certificates. For kitty or iTerm2 inline images, pass the terminal graphics environment variables, for example -e TERM -e TERM_PROGRAM -e KITTY_WINDOW_ID; otherwise images use half-block art.

Each release also publishes ghcr.io/mob3net/mob3 with the release tag and latest, for linux/386, linux/amd64, linux/arm64, linux/arm/v6 and linux/arm/v7:

docker run --rm -it ghcr.io/mob3net/mob3:latest https://example.com

The first published package is private by default; make it public in the repository's package settings if anonymous pulls should work.

Releases

Pushing a v* tag (for example v1.0.0) publishes one archive per platform plus a SHA256SUMS file to the GitHub release for that tag:

Assets are named mob3_<tag>_<os>_<platform>.tar.gz (or .zip on Windows), for example mob3_v1.0.0_linux_armv6.tar.gz. Extract the archive and run ./mob3 (mob3.exe on Windows). Windows and macOS binaries are code-signed when release signing is configured; otherwise they are published unsigned.

Pushing the tag is enough: if no GitHub release exists for it, the workflow creates one with generated notes, then attaches the archives. You can still create or edit the release in the web interface first.

Verify a download with the release checksums:

sha256sum -c SHA256SUMS --ignore-missing

Usage

mob3 [flags] [url|file]

  -dump          render the page to stdout and exit
  -width int     layout width (default: terminal width or 100)
  -graphics str  auto, kitty, iterm or blocks (default "auto")
  -no-js         disable page JavaScript
  -text-scale    kitty scaled text: auto or off (default "auto")
  -cpuprofile    write a CPU profile to this file
  -color         force ANSI color when dumping
  -no-color      disable ANSI colors in dump mode
  -ua string     custom User-Agent
  -search str    search URL template with %s (default DuckDuckGo; empty disables)
  -version       print the version and exit

Examples:

./bin/mob3 https://go.dev
./bin/mob3 ./page.html
./bin/mob3 -dump -width 120 -no-color page.html

-graphics=auto detects kitty, WezTerm, Ghostty and iTerm2. Other terminals, tmux/screen/zellij and -dump use half-block art.

The default User-Agent is MOB3/1.0 (+terminal). Override it with -ua.

When URL input is not URL-shaped — it contains whitespace or has no dot, so golang tutorial or golang — MOB³ opens DuckDuckGo's server-rendered search page instead of failing. Inputs such as example.com, localhost:8080, /path, about:start, file paths and full URLs still navigate normally. Use -search with a %s template to choose another engine, for example -search 'https://www.bing.com/search?q=%s', or -search '' to disable the fallback.

Keys and mouse

Key Action
j / k scroll one line
Space / b scroll one screen
Ctrl-D / Ctrl-U scroll half a screen
g / G top / bottom
Tab / Shift-Tab next / previous link
Enter follow link
h / l back / forward
r reload
o open URL (current URL selected)
u show current URL
? open the help page
! JavaScript console (mouse selection enabled)
Esc stop loading or clear selection
q / Ctrl-C quit
Mouse Action
drag over text select (highlight, auto-scroll)
click a text field focus it; type to edit, Enter submits, Esc finishes
click link follow
click URL field open URL prompt
click ← / ⟳ / ? back / reload / help
right click back
wheel scroll

Esc stops an in-flight page load or clears a selection. The top bar shows back, reload, the page title, help and a full-width URL field. ? or the toolbar help button opens the built-in about:help page, which documents keys, mouse, forms and every command-line flag. Opening the URL field prefills and selects the current URL; typing replaces it. Inside the field, Left/Right, Home/End, Backspace/Delete, Ctrl-A, Ctrl-K, Ctrl-U and Ctrl-W edit the URL; the block caret overlays text without shifting it.

What works

Renderer

MOB³ is a cell-based renderer, not a pixel browser:

Limits

Tests

go test ./...

The project uses cmd/mob3 for the executable and internal/browser for the engine; tests live next to the code.

Contributing

Contributions are welcome. Every pull request must include the broad license-grant CLA statement described in CONTRIBUTING.md; it keeps MOB³ available under both AGPL-3.0-only and a commercial license. The PR workflow checks the statement. The CI workflow runs formatting, vet and tests on pull requests and pushes to main.

License

MOB³ is licensed under the GNU Affero General Public License, version 3 only (AGPL-3.0-only). Copyright (c) 2026 Milos Stojanovic. See LICENSE.

A separate commercial license is available on request for use without the AGPL's source-disclosure requirements. Ask the copyright holder if you need one.

MOB³ is provided “as is”, without warranty of any kind. See the warning at the top: this is a hobby browser, not a security boundary.

Third-party module licenses are listed in THIRD_PARTY_NOTICES.