Skip to content

jmagly/carbonyl

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

402 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

   O    O
    \  /
   O —— Cr —— O
    /  \
   O    O

Carbonyl

Chromium-based browser that runs in a terminal — 60 FPS, 0% idle CPU, SSH-friendly

pip install carbonyl-agent && carbonyl-agent install

License: BSD-3-Clause Chromium M147 Runtime Built With AIWG

Get Started · Fork Status · Build from Source · Comparisons · Blog


What Carbonyl Is

Carbonyl is a Chromium-based browser that renders into terminal text. It supports pretty much all Web APIs — WebGL, WebGPU, audio and video playback, animations — and starts in less than a second, runs at 60 FPS, and idles at 0% CPU. It does not require a window server (works in a safe-mode console) and runs comfortably over SSH.

This repository (jmagly/carbonyl) is the maintained fork of the original fathyb/carbonyl, which has been inactive since early 2023. It tracks upstream Chromium stable (currently M147) and publishes runtime tarballs as release assets.


Looking for the automation SDK?

Most users want carbonyl-agent — the Python SDK that drives Carbonyl for scripted browsing, scraping, and agent-based testing. It handles binary discovery, session persistence, daemon reconnection, and bot-detection evasion out of the box.

pip install carbonyl-agent
carbonyl-agent install   # downloads the verified runtime binary
from carbonyl_agent import CarbonylBrowser

b = CarbonylBrowser()
b.open("https://example.com")
b.drain(8.0)
print(b.page_text())
b.close()

For multi-instance orchestration (N concurrent browsers over PTY + Unix socket, with gRPC + REST), see carbonyl-fleet.

This repo (jmagly/carbonyl) is the Chromium fork and the source of the runtime tarballs. Most users do not need to build it.


Get Started

Use the runtime (recommended)

pip install carbonyl-agent
carbonyl-agent install

The installer downloads a verified-by-SHA256 runtime tarball from the public GitHub release page, with documented manual/offline fallbacks. No compilation required.

Run Carbonyl directly

Docker (recommended)

Maintained linux/amd64 images are published to ghcr.io/jmagly/carbonyl on every v* release, built from the verified runtime tarballs (no compile).

docker run --rm -ti ghcr.io/jmagly/carbonyl https://example.com
Tag Contents
ghcr.io/jmagly/carbonyl:latest headless runtime, newest release
ghcr.io/jmagly/carbonyl:<version> headless, pinned (e.g. 0.2.0-alpha.9)
ghcr.io/jmagly/carbonyl:<version>-x11 x11 ozone, pinned (automation / trusted input)

The image runs non-root under tini via build/docker-entrypoint.sh with container-safe defaults (--no-sandbox, --disable-dev-shm-usage, --disable-gpu). Arguments after the image name are forwarded to the carbonyl CLI. Current runtimes apply an internal 1.5× zoom, so the entrypoint defaults to --zoom=67 (≈100%); override with -e CARBONYL_ZOOM=50 or --zoom=50 after the image name.

# Interactive terminal browsing (needs a TTY)
docker run --rm -ti ghcr.io/jmagly/carbonyl:latest https://example.com

# Version / help (no URL)
docker run --rm ghcr.io/jmagly/carbonyl:latest --version

# Persist cookies / profile
docker volume create carbonyl-profile
docker run --rm -ti -v carbonyl-profile:/home/carbonyl \
  ghcr.io/jmagly/carbonyl:latest https://app.example.com

# x11 variant (needs a host/sidecar X server + uinput)
docker run --rm -ti -e DISPLAY=:99 --device=/dev/uinput --group-add input \
  ghcr.io/jmagly/carbonyl:<version>-x11 --ozone-platform=x11 https://example.com
Flag Why
--rm Remove the container on exit
-ti Interactive terminal browsing (omit for --version/non-TTY use)
-v name:/home/carbonyl Persist profile / cookies
-e CARBONYL_ZOOM=N Override zoom (lower = zoom out)
-e DISPLAY=:99 --device=/dev/uinput x11 ozone / trusted input

Other ways

# Upstream image (M111-era, dated but works)
docker run --rm -ti fathyb/carbonyl https://youtube.com

# npm (upstream package — M111-era)
npm install --global carbonyl && carbonyl https://github.com

# Pre-built runtime tarball from release assets (M147, current)
# https://github.com/jmagly/carbonyl/releases

Install a native package

Releases also ship native install packages — .deb / .rpm / .AppImage (Linux x86_64) and a .pkg / .dmg (macOS arm64, not Apple-notarized):

sudo apt install ./carbonyl_<version>_amd64.deb        # Debian / Ubuntu
sudo dnf install ./carbonyl-<version>-1.x86_64.rpm     # Fedora / RHEL
./carbonyl-<version>-x86_64.AppImage https://github.com # any Linux, no install

Full instructions (incl. the macOS Gatekeeper step for the unsigned installer): docs/install.md.

Verifying releases

Every release asset ships a SHA-256 + MD5 checksum and a detached GPG signature (<asset>.asc). The checksums prove the download is intact; the signature proves it genuinely came from us. Import the Carbonyl release key once, then verify:

curl -fsSL https://magly.net/keys/carbonyl-release.asc | gpg --import
gpg --verify carbonyl-<version>-<asset>.asc carbonyl-<version>-<asset>
# → Good signature from "Carbonyl Release Signing <release@magly.net>"

Key fingerprint 96B5 DCE9 275E 218C BAB9 CB28 2DE7 DD0D 3A89 07C0 — published at https://magly.net/keys/carbonyl-release.asc. Full details, the key block, and rotation policy: docs/SIGNING.md.

Runtime modes

One binary, three deployment shapes:

Mode Invocation When to use
Terminal-only carbonyl <url> Read in a terminal; smallest surface
x11 + trusted input DISPLAY=:99 carbonyl --ozone-platform=x11 <url> Automation against bot-detecting sites (kernel uinput → Xorg → isTrusted=true events)
x11 + visual capture CARBONYL_X_MIRROR=1 DISPLAY=:99 carbonyl --ozone-platform=x11 <url> Same, plus blits compositor frames into an X window so scrot/ffmpeg/x11vnc can capture alongside the terminal render

Full operator reference, session-portability rules, and CLI/env-var matrix: docs/runtime-modes.md.

Passing Chromium flags

Carbonyl forwards any flag it does not recognize straight to the underlying Chromium, so you can set the proxy, user-agent, language, and most other Chromium command-line switches alongside Carbonyl's own options:

# Route traffic through a SOCKS proxy
carbonyl --proxy-server=socks5://127.0.0.1:9050 https://example.com

# Override the user-agent string
carbonyl --user-agent="MyAgent/1.0" https://example.com

# Set the UI / Accept-Language locale, with a Carbonyl flag in the same line
carbonyl --lang=fr-FR --zoom=80 https://example.com

Carbonyl-specific flags (--fps, --zoom, --viewport, …) are consumed by Carbonyl and still passed to Chromium, which ignores switches it doesn't know. Chromium flags Carbonyl doesn't recognize are passed through untouched — see carbonyl --help and Chromium's flag list.


Active Fork — Continued Maintenance

The original repository (fathyb/carbonyl) has been inactive since early 2023. This fork is actively maintained for use in headless browser automation and agentic pipelines.

What's different in this fork

  • Chromium M147 (147.0.7727.94) — current upstream stable. Upgraded from M111 across six phases (M111 → M120 → M132 → M135 → M140 → M147). 24 patches applied. Runtime tarballs published as release assets.
  • Python automation layer (carbonyl-agent) — extracted into a standalone installable package. CarbonylBrowser class with persistent sessions, daemon reconnect, mouse movement, click-by-text, and screen extraction.
  • Fleet server (carbonyl-fleet) — Rust server for N concurrent browsers with gRPC + REST + Python SDK.
  • Bot-detection mitigations — Firefox UA spoof, --disable-http2, AutomationControlled suppressed, organic mouse movement API.
  • Session management — named persistent profiles, fork/snapshot, SessionManager CLI.
  • CI infrastructure — automated workflows for fast checks and full Chromium runtime builds, pinned to dedicated build hosts.

--carbonyl-b64-text restored in M135: the experimental text-capture mode was temporarily disabled during the initial M135 ship and has been re-enabled via a structural refactor (Path A, issue #28). Both bitmap rendering (default) and b64 text capture are functional on M147.

Maintenance commitment: Security-relevant Chromium versions are tracked on a best-effort basis. The automation API is under active development. Issues and PRs welcome.


Project Family

Repo Purpose Build tech
carbonyl Chromium fork + runtime tarballs (this repo) Chromium, GN, ninja, Rust
carbonyl-agent Python automation SDK (single-instance) Python 3.11+, pyte, pexpect
carbonyl-fleet Fleet server (N concurrent browsers, gRPC + REST) Rust, tonic, axum

Known Issues

  • Fullscreen mode not supported yet

Comparisons

Lynx

Lynx is the original terminal web browser, and the oldest one still maintained.

Pros

  • When it understands a page, Lynx has the best layout, fully optimized for the terminal

Cons (some might sound like pluses, but Browsh and Carbonyl let you disable most of those if you'd like)

  • Does not support a lot of modern web standards
  • Cannot run JavaScript/WebAssembly
  • Cannot view or play media (audio, video, DOOM)

Browsh

Browsh is the original "normal browser in a terminal" project. It starts Firefox in headless mode and connects to it through an automation protocol.

Pros

  • Easier to update the underlying browser: just update Firefox
  • As of today, Browsh supports extensions while Carbonyl doesn't (on our roadmap)

Cons

  • Runs slower and requires more resources than Carbonyl. 50× more CPU for the same content on average, because Carbonyl does not downscale or copy the window framebuffer — it natively renders to the terminal resolution.
  • Uses custom stylesheets to fix the layout, which is less reliable than Carbonyl's changes to its HTML engine (Blink).

Operating System Support

OS Status
Linux (Debian, Ubuntu, Arch) ✅ Tested
macOS ✅ Tested (upstream; M147 fork not yet rebuilt on macOS)
Windows 11 / WSL 🟡 Reported working (upstream)

Demo

Wikipedia.mp4
Doom.mp4
YouTube.mp4

Building from Source

You almost certainly do not need to do this — use carbonyl-agent install to pull a pre-built runtime.

Carbonyl is split in two parts:

  • Core (libcarbonyl.so) — written in Rust, builds in seconds via cargo
  • Runtime (headless_shell) — a modified Chromium build with 24 patches, requires the full Chromium toolchain

If you're just changing the Rust code, build libcarbonyl and drop it into a release version of Carbonyl. You do not need to rebuild Chromium.

Core (Rust library)

cargo build

Runtime (Chromium + libcarbonyl)

⚠️ Building Chromium takes considerable wall time, disk space, and memory. Expect ~100 GB of disk and a heavy compile workload.

Notes:

  • Building the runtime is essentially the Chromium build flow with extra steps to patch and bundle the Rust library.
  • Scripts in scripts/ are thin wrappers around gn, ninja, etc.
  • Cross-compiling Chromium for arm64 on Linux requires an amd64 processor.
  • Tested on Linux and macOS.

Fetch Chromium sources

./scripts/gclient.sh sync

Apply Carbonyl patches

Any existing changes in chromium/src/ will be stashed. Save your work first.

./scripts/patches.sh apply

Configure the GN build

./scripts/gn.sh args out/Default

When prompted, enter:

import("//carbonyl/src/browser/args.gn")

# uncomment to build for arm64
# target_cpu = "arm64"

# comment to disable ccache
cc_wrapper = "env CCACHE_SLOPPINESS=time_macros ccache"

# comment for a debug build
is_debug = false
symbol_level = 0
is_official_build = true

Build binaries

./scripts/build.sh Default

Produces:

  • out/Default/headless_shell — browser binary
  • out/Default/icudtl.dat
  • out/Default/libEGL.so
  • out/Default/libGLESv2.so
  • out/Default/v8_context_snapshot.bin

Build the Docker image

./scripts/docker-build.sh Default arm64
./scripts/docker-build.sh Default amd64

Run

./scripts/run.sh Default https://wikipedia.org

See maintenance.md for detailed upgrade procedures, patch rebasing guidance, and the rebase SOP used to move M111 → M147.


Documentation


Contributing

PRs and issues welcome at github.com/jmagly/carbonyl.

Most meaningful changes to the Python automation path belong in carbonyl-agent. This repo is the Chromium side — patches, build scripts, runtime infrastructure.


Community & Support


License

BSD-3-Clause License — see LICENSE.

Carbonyl includes Chromium, which is BSD-licensed. See chromium/src/LICENSE after a checkout for upstream terms.


Sponsors

The Temporal Layer for Web3

Enterprise-grade timing infrastructure for blockchain applications.

No-Code Smart Contracts for Everyone

Making blockchain-based agreements accessible to all.

AI-Powered Automation Solutions

Custom AI and blockchain solutions for the digital age.

Interested in sponsoring? Open a GitHub Discussion.


Acknowledgments

Built on top of Carbonyl by Fathy Boundjadj, which in turn sits on Chromium and Skia. The M111→M147 rebase path was informed by CEF's blink_glue.cc pattern for the Path A structural fix. Thanks to the Chromium cppgc / Oilpan maintainers for the underlying template machinery (see issue #27).


About

Chromium-based browser that renders to terminal text — 60 FPS, 0% idle CPU, SSH-friendly. Actively-maintained fork tracking upstream Chromium stable (currently M148). Ships verified runtime tarballs. Use with carbonyl-agent for Python automation.

Topics

Resources

License

Stars

21 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages

  • Rust 40.3%
  • Shell 28.8%
  • C++ 16.2%
  • Python 9.7%
  • JavaScript 1.9%
  • HTML 1.4%
  • Other 1.7%