Model or dataset
e2b-dev/desktop avatar
e2b-dev/desktop

E2B Desktop Sandbox: a virtual desktop for LLM computer use

E2B Desktop Sandbox for LLMs. E2B Sandbox with desktop graphical environment that you can connect to any LLM for secure computer use.

1,499 stars186 forksPythonApache-2.0

At a glance

What is it?
E2B Desktop Sandbox gives an LLM a full graphical Linux desktop it can click, type and stream. It is built for agent builders, and it is not a remote desktop for people.
Who is it for?
Adopt E2B Desktop Sandbox if you are building a computer-use agent and want the desktop layer handled for you: install e2b-desktop, set E2B_API_KEY, and drive chrome, firefox or vscode through the SDK. Do not adopt it if you need a human remote desktop, a persistent machine, or more than one simultaneous stream per sandbox.
Can I use it commercially?
Yes. Apache-2.0 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 5 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 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What E2B Desktop Sandbox is for, and who should reach for it

The project solves one narrow problem: an LLM that can reason about a screen needs a screen to reason about. E2B Desktop Sandbox is an isolated virtual desktop, each sandbox separated from the others, that an agent can launch applications in, click, drag, scroll, type into and watch through a stream URL. The README frames it as "an open source secure virtual desktop ready for Computer Use," and the examples folder backs that up with basic-python, basic-javascript, streaming-apps-python and streaming-apps-javascript.

The audience is agent developers, not end users. If you are wiring a model to a GUI, the alternative is assembling a VM, a VNC stack, an input-injection layer and a screenshot loop yourself. Here that is a handful of SDK calls. The repository also points at two downstream projects built on it: Open Computer Use, described as computer use made with 100% open source LLMs, and Surf, an OpenAI Computer Use Agent that runs as a Next.js app. Those two are the clearest signal of intended use.

It is worth being blunt about what it is not. Nothing in the README describes a human sitting at this desktop for hours, file sync, clipboard sharing between host and sandbox, or a machine that survives being killed. The desktop is a disposable surface for an agent.

How the sandbox, the stream and the input layer fit together

The mechanism has three visible parts. Sandbox.create() provisions the isolated desktop. Methods on that object act on it: launch('google-chrome') starts an application, wait(10000) blocks for it, get_current_window_id() and get_application_windows('Firefox') locate windows, and the mouse methods (left_click, right_click, middle_click, double_click, scroll, move_mouse, drag, mouse_press, mouse_release) inject input. The stream object is the third part: stream.start() opens a view, stream.get_url() returns a URL you can open in a browser, and stream.stop() closes it.

The constraint that shapes any architecture here is stated plainly in the README: there can be only one stream at a time, and you need to stop the current stream before streaming another application. A second warning block adds that streaming a specific application raises an error if the application is not open yet, and that the stream closes once the application closes. So the agent loop cannot fan out across windows. It watches one window, acts, and switches by stopping and restarting the stream.

Authentication is a separate flag rather than a default. stream.start(require_auth=True) makes the stream require an auto-generated key, retrieved with stream.get_auth_key() and passed to stream.get_url(auth_key=auth_key). Without that, the URL is open. get_url(view_only=True) is the other lever: it disables user interaction, which is what you want when a human is only observing the agent.

The README notes that the JavaScript and Python SDK sources now live in the E2B monorepo, under packages/desktop-js and packages/desktop-python, while this repository keeps the sandbox template and the examples. That split matters when you file an issue or read a changelog: the desktop SDK you install is versioned separately from the template in template/.

Installing e2b-desktop and opening a first window

You need an E2B API key first. The README says to sign up at e2b.dev, get the key, and set the E2B_API_KEY environment variable. Then install one of the two SDKs. Python is a single package:

bash
pip install e2b-desktop

The JavaScript equivalent is:

bash
npm install @e2b/desktop

With the key exported, this Python script creates a sandbox, opens Chrome, waits ten seconds, starts a stream with authentication required, and prints the URL:

python
from e2b_desktop import Sandbox

desktop = Sandbox.create()
desktop.launch('google-chrome')
desktop.wait(10000)

desktop.stream.start(
    window_id=desktop.get_current_window_id(),
    require_auth=True
)

auth_key = desktop.stream.get_auth_key()
print('Stream URL:', desktop.stream.get_url(auth_key=auth_key))

Open the printed URL in a browser and you should see the Chrome window, with the auth key gating access. The README's own example ends with a commented-out desktop.kill() and a note to kill the sandbox after the tasks are finished. Leave that line commented while you are still watching, and uncomment it in anything that runs unattended. The JavaScript version follows the same order with camelCase names: Sandbox.create(), launch('google-chrome'), wait(10000), stream.start({ windowId, requireAuth: true }), stream.getAuthKey(), stream.getUrl({ authKey }).

One stream, no reconnects: the limits you inherit

The single-stream rule is the limitation most likely to bite. An agent that wants to check a terminal window and a browser window at the same time cannot do it through two streams. The README's answer is to stop the current stream and start a new one per application, which means your agent loop needs explicit stream lifecycle management rather than a persistent view.

The second limit is timing. wait(10000) is a fixed sleep in the README's example, not a readiness probe. A slow application launch on a cold sandbox and a fast one look identical to that call. The README does not document an event or callback for application readiness, so you are left tuning the millisecond value.

The third is that this is the wrong tool for several adjacent jobs. It is not a remote desktop for a human to work in all day; the stream is the product, not a persistent workstation. It is not a CI runner with a display, because nothing in the README describes artifact collection or a headless mode. And it is not a way to give an agent a GUI on your own machine: the desktop lives in an E2B sandbox, and the README describes customization through dependencies in that sandbox, not through mounting your host environment.

Finally, the README does not document rollback, snapshotting or resuming a killed sandbox. Once desktop.kill() runs, treat the state as gone.

E2B Desktop Sandbox versus driving a browser directly

The obvious alternative for computer-use agents is a browser automation library such as Playwright or Selenium, which drives a headless or headed browser through a DOM-level protocol. The difference in approach is the level of abstraction. A browser driver addresses elements by selector, so it is fast and deterministic when the page is well formed, and it only works inside a browser. E2B Desktop Sandbox gives the agent pixels and a mouse: launch('vscode') or launch('firefox') are equally valid, and the agent can act on anything that renders, including native applications that expose no DOM at all.

That flexibility costs you determinism. Clicking at coordinates is brittle in a way that clicking a selector is not, and the README's window helpers (get_current_window_id, get_application_windows) return identifiers, not semantic targets. There is also no built-in assertion layer; the README shows how to move the mouse and start a stream, not how to verify that a click did what you meant.

A second alternative is running a full VM or container with a VNC server yourself. That gives you more control over persistence and networking, and it puts the streaming, input injection and isolation work on you. E2B Desktop Sandbox exists to remove exactly that work, and the price is accepting its stream model and its sandbox lifecycle.

Maintenance, versions and the Apache-2.0 licence

The repository is not archived, and the last push was on 2026-09-10, ten days before this writing, so the template and example side is being touched. The versioning is split across two package lines visible in the releases: @e2b/[email protected] on 2026-07-23, @e2b/[email protected] and @e2b/[email protected] both on 2026-06-08. The Python SDK is ahead of the JavaScript one by a minor version, which is worth knowing if you maintain both bindings and expect feature parity.

Upgrade cost is concentrated in the SDK, not the template. Because the SDK sources moved to the E2B monorepo, the desktop packages are versioned and released there; this repository's README is the integration guide plus the examples. A breaking change in Sandbox.create() or in the stream API would land as a major version on those packages, and your pinned version is what protects you. The README does not document a migration guide between the 2.x releases.

The licence is Apache-2.0, which permits commercial use and modification and includes a patent grant. It also carries notice and attribution obligations when you redistribute, and it does not grant trademark rights. Whether your specific redistribution triggers those obligations is a question for your own counsel, not something the README settles. Note that the E2B service the sandbox runs on is separate from the code licence.

Editorial conclusion

Adopt E2B Desktop Sandbox if you are building a computer-use agent and want the desktop layer handled for you: install e2b-desktop, set E2B_API_KEY, and drive chrome, firefox or vscode through the SDK. Do not adopt it if you need a human remote desktop, a persistent machine, or more than one simultaneous stream per sandbox. Before committing, verify the SDK version you pin against the E2B monorepo, since the desktop SDK sources moved to packages/desktop-js and packages/desktop-python there, and confirm that require_auth=True plus desktop.stream.get_auth_key() is how you intend to gate the stream URL.

Frequently asked questions

How do I install E2B Desktop Sandbox?

Install the SDK for your language: pip install e2b-desktop for Python or npm install @e2b/desktop for JavaScript. You also need an E2B API key, which the README says to obtain by signing up at e2b.dev and to set as the E2B_API_KEY environment variable.

Can I stream more than one application at the same time with E2B Desktop Sandbox?

No. The README states that there can be only one stream at a time and that you need to stop the current stream before streaming another application. Streaming a specific application also raises an error if that application is not open yet.

How do I password-protect the E2B Desktop Sandbox stream?

Pass require_auth=True to desktop.stream.start(), then retrieve the key with desktop.stream.get_auth_key() and pass it to desktop.stream.get_url(auth_key=auth_key). In JavaScript the equivalents are requireAuth: true, getAuthKey() and getUrl({ authKey }).

How do I stop the E2B Desktop Sandbox when the agent finishes?

Call desktop.kill(), which the README's example shows commented out with a note to kill the sandbox after the tasks are finished. The README does not document rollback or resuming a killed sandbox, so treat the state as gone.

Official sources

  1. e2b-dev/desktop on GitHub
  2. License: Apache-2.0
  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/e2b-dev-desktop.svg)](https://hysenlabs.com/projects/e2b-dev-desktop)