Skip to main content
Skip to content

Documentation

Orbis developer guide

Run the engine, connect your tools, and drive pages by action ID. Everything here matches Orbis 1.0.0 — commands, method names and output formats are taken from the engine itself.

Overview

Orbis is a headless browser engine for AI agents and automation. It fetches pages, builds a standards-based DOM and runs the page’s JavaScript in a V8 sandbox — but it never lays out or paints anything. Instead of pixels it produces three things an agent can use directly:

  • An action map — every visible link, button and form field, numbered @1, @2, @3, with its role, label and resolved CSS selector.
  • Markdown — the readable content of the page, without scripts and styles.
  • Structured data — OpenGraph, Twitter card, canonical URL, meta tags and JSON-LD.

You reach the engine four ways: the Chrome DevTools Protocol (Playwright, Puppeteer), W3C WebDriver (Selenium), HTTP endpoints, or the Model Context Protocol (Claude Code, Cursor, Windsurf). The npm package installs three equivalent commands: memora-orbis, orbis and the deprecated memora-browser.

Install

Orbis runs on Node.js and is tested on Node 20 and 22. Run it without installing, or add it to a project:

Terminal
# run directly
npx memora-orbis --port 9222

# or add to a project
npm install memora-orbis

The Python client talks to a running Orbis server over HTTP:

Terminal
pip install memora-orbis
The packages are being prepared for public release. If npx memora-orbis reports that the package can’t be found, contact enterprise@memora.company for early access.

Quickstart

1. Start the server

Terminal
npx memora-orbis --port 9222
Startup banner (abridged)
╔════════════════════════════════════════════════════════════════╗
║                      🪐 ORBIS BY MEMORA                        ║
║        An Agentic Browser • Built for Autonomous AI            ║
║              Powered by Memora Browser Engine                  ║
╚════════════════════════════════════════════════════════════════╝
  ▶ CDP WebSocket:      ws://127.0.0.1:9222/devtools/browser/memora-root
  ▶ Discovery Endpoint: http://127.0.0.1:9222/json/version
  ▶ Agent Snapshot:     http://127.0.0.1:9222/orbis/snapshot (or /memora/snapshot)
  ▶ Stealth Mode:       🛡️  ACTIVE (Anti-Detect On)
  ▶ License / Tier:     ⚡ COMMUNITY EVALUATION (Free For Devs)
  ▶ Status:             READY FOR PLAYWRIGHT / PUPPETEER / AGENTS

Stealth is on by default; there is no --stealth flag, only --no-stealth. Check the server with curl http://127.0.0.1:9222/json/version — it reports a Chrome 130 compatible browser and product: "Orbis/1.0.0".

2. Distill one page

Terminal
npx memora-orbis --eval https://app.example.com/login
Output
🔍 [Orbis] Fetching & Distilling: https://app.example.com/login ...

✨ Successfully distilled in 35.6ms!
📌 Title: Enterprise Cloud - Sign In to Workspace
🎯 Interactive Elements: 15
🧠 Estimated Prompt Tokens: 630

=== INTERACTIVE ACTION MAP (15 elements) ===
[@3] [select] "Language Selector" type="select" (selector: #locale-picker)
[@4] [input] "alex@memora.company" type="email" placeholder="alex@memora.company" (selector: #username)
[@9] [button] "Sign In with Credentials" type="submit" (selector: #btn-submit)
…

3. Dump a page in the format you need

Terminal
npx memora-orbis fetch https://example.com --dump markdown
npx memora-orbis fetch https://example.com --dump action_map
npx memora-orbis fetch https://example.com --dump structured_data

Playwright & Puppeteer

Start Orbis (CDP is the default protocol), then connect instead of launching a browser. The rest of your script is unchanged.

playwright.ts
import { chromium } from 'playwright';

// Before: const browser = await chromium.launch();
const browser = await chromium.connectOverCDP('http://127.0.0.1:9222');
const context = browser.contexts()[0];
const page = context.pages()[0] || await context.newPage();

await page.goto('https://example.com');
console.log(await page.title());
puppeteer.js
import puppeteer from 'puppeteer-core';

// Before: const browser = await puppeteer.launch();
const browser = await puppeteer.connect({ browserURL: 'http://127.0.0.1:9222' });
const page = await browser.newPage();

await page.goto('https://example.com');
console.log(await page.title());
Orbis doesn’t render, so screenshots and PDFs aren’t available, element boxes come from a synthetic layout, and file uploads aren’t supported. See Limitations.

Selenium (WebDriver)

Start a WebDriver server — no chromedriver binary needed — and point webdriver.Remote at it.

Terminal
npx memora-orbis --protocol webdriver --port 9222
test_example.py
# npx memora-orbis --protocol webdriver --port 9222
from selenium import webdriver

driver = webdriver.Remote(
    command_executor="http://127.0.0.1:9222",
    options=webdriver.ChromeOptions(),
)

driver.get("https://example.com")
print(driver.title)
driver.quit()
selenium.ts
import { Builder, Browser } from 'selenium-webdriver';

const driver = await new Builder()
  .forBrowser(Browser.CHROME)
  .usingServer('http://127.0.0.1:9222')
  .build();

await driver.get('https://example.com');
await driver.quit();

Up to 16 sessions run concurrently by default (--max-sessions). One process serves one protocol; run a second process on another port if you need CDP and WebDriver at once.

MCP server

Add Orbis to any MCP client that supports stdio servers — Claude Code, Claude Desktop, Cursor, Windsurf or Antigravity:

mcp.json / claude_desktop_config.json
{
  "mcpServers": {
    "orbis": {
      "command": "npx",
      "args": ["-y", "memora-orbis", "--mcp"]
    }
  }
}

The server lists 15 tools. Each memora_* tool also answers to an orbis_* alias (for example orbis_browse).

ToolWhat it does
memora_browseLoad a URL; return Markdown, the action map and a token estimate
memora_actClick or type using an action ID or CSS selector
memora_fill_formFill several fields at once and optionally submit
memora_diffSummarise what changed since the previous turn
memora_forkCopy the current page to explore another path
memora_sessionSave or load cookies and web storage
memora_inspectList the title and current interactive elements
memora_extractPull text or attributes from matching elements
memora_metadataRead OpenGraph, Twitter card, canonical and JSON-LD
memora_consoleRead console logs, warnings and errors
memora_storageRead or write localStorage and sessionStorage
memora_cookiesList, set or clear cookies
memora_evalRun JavaScript in the page
memora_htmlGet raw HTML for the page or one element
memora_reloadReload the page and refresh the action map
In MCP mode the default --engine auto uses a system Chrome or Edge when it finds one. Add "--engine", "native" to the args to always use the Orbis engine, or chrome for pages that need a full renderer.

OrbisAgent (TypeScript)

OrbisAgent is the high-level controller for LLM loops. OrbisAgent.launch() starts an in-process engine and a CDP server on cdpPort.

agent.ts
import { OrbisAgent } from 'memora-orbis';

const agent = await OrbisAgent.launch({ cdpPort: 9222 });

// Navigate and read the page
const snapshot = await agent.goto('https://app.example.com/login');
snapshot.actionMapText;     // numbered actions
snapshot.markdown;          // readable content
snapshot.tokenEstimate;     // characters ÷ 4

// Act by ID (or CSS selector)
agent.act('@4', 'agent@example.com');   // type
agent.act('@8');                        // click

// Fill a whole form, then submit
await agent.fillForm({ '@4': 'agent@example.com', '@6': process.env.APP_PASSWORD }, true);

// What changed?
console.log(agent.diff().summary);

// Branch, persist, clean up
const branch = agent.fork();
agent.saveSession('./sessions/app.json');
await agent.close();
MethodReturnsNotes
goto(url, options?)Promise<snapshot>options: focusSelector, excludeSelectors
snapshot() · markdown()snapshot · stringRe-read the current page
act(target, text?)booleanTypes when text is given, otherwise dispatches a click
fillForm(fields, submit = true)PromiseText, textarea, select, checkbox, radio, contenteditable
diff()PageDiffCompared with the previous snapshot
fork()OrbisAgentCopy of the page with cookies and storage
saveSession(path) · loadSession(path)voidJSON: url, cookies, localStorage, sessionStorage
close()PromiseStops the engine and server
act() dispatches the click event, which runs the page’s handlers. To follow a link or submit a form the way a user’s click would, call await agent.page.activate(target). For multi-step wizards use agent.page.fillForm({ steps: [...] }), where each step has fields and a submitActionId.

Python client

The Python package is a small HTTP client for a running Orbis server. Import it from memora or orbis.

agent.py
from memora import OrbisAgent

# Talks to a running server: npx memora-orbis --port 9222
agent = OrbisAgent.connect("http://127.0.0.1:9222")

snap = agent.goto("https://example.com")
print(snap.title, snap.token_estimate)
print(snap.action_map_text)

agent.act("@1")
agent.fill_form({"#username": "agent", "#password": "..."}, submit=True)
MethodCalls
OrbisAgent.connect(base_url, api_key=None)Checks /json/version
goto(url)GET /orbis/goto
snapshot(focus_selector, exclude_selectors)GET /orbis/snapshot
markdown()GET /orbis/snapshot?format=markdown
act(action_id, text=None)POST /orbis/act
fill_form(fields, submit=True)POST /orbis/fill-form
diff()GET /orbis/diff (returns a dict)
save_session(path) · load_session(path)/orbis/session
to_browser_use() · to_langchain_tools()Helpers for Browser-Use and LangChain

Framework adapters

The npm package exports small helpers that produce the configuration each framework expects:

ExportReturns
getBrowserUseConfig(agentOrPort = 9222){ cdpUrl, disableSecurity, extraChromiumArgs }
getStagehandConfig(agentOrPort = 9222){ env: 'LOCAL', localBrowserUrl }
createOrbisLangChainTools(agent)Tool objects: navigate, snapshot, act, diff, fill_form

CLI

memora-orbis [options] and memora-orbis serve [options] start the automation server.

OptionDefaultDescription
-p, --port <number>9222Port for CDP / WebDriver / HTTP.
-h, --host <string>127.0.0.1Interface to bind. Use 0.0.0.0 inside containers.
--protocol <cdp|webdriver>cdpcdp for Playwright and Puppeteer, webdriver for Selenium. One protocol per process.
--engine <native|chrome|auto>autoEngine for --mcp mode. auto uses a system Chrome or Edge when one is found, otherwise the native engine.
--max-sessions <number>16Maximum concurrent WebDriver sessions.
--no-stealth—Disable the stealth profile (it is on by default).
--eval <url>—Fetch a URL, print the snapshot and exit.
--mcp—Run as a Model Context Protocol server over stdio.

fetch

memora-orbis fetch [options] <url> prints a page in an LLM-ready format and exits.

OptionDefaultDescription
-d, --dump <format>markdownmarkdown, html, structured_data, semantic_tree or action_map (semantic_tree and action_map are the same output).
--dump-selector <selector>—Restrict output to elements matching a CSS selector.
--dump-max-bytes <bytes>—Cap the output size.
--wait-ms <ms>—Wait after loading, for content that appears a moment later.
--no-stealth—Disable the stealth profile.

Every command also accepts the network options.

Snapshot & action map

A snapshot has these fields:

FieldDescription
url · titleCurrent page
actionMapTextThe numbered action map as text
actions[]actionId, role, text, type, value, placeholder, href, selector, disabled, checked, expanded, selected…
markdownReadable content
interactiveCountNumber of actions
tokenEstimateCharacters ÷ 4 across title, action map and Markdown

Each line of the action map has the same shape:

Format
[@ID] [role] "label" type="…" placeholder="…" href="…" [CHECKED] (selector: …)

[@4] [input] "alex@memora.company" type="email" placeholder="alex@memora.company" (selector: #username)
[@8] [input] "[Untitled input]" type="checkbox" (selector: #remember)
[@9] [button] "Sign In with Credentials" type="submit" (selector: #btn-submit)
  • Role is the ARIA role when present, otherwise link, button or the tag name.
  • Label comes from aria-label, then placeholder, title, value and text content (up to 80 characters). With none of these it reads [Untitled input].
  • Selector prefers an id, then test attributes (data-testid, data-cy…), name, aria-label, placeholder, a unique class, and finally an nth-of-type path.
  • Hidden elements — hidden, aria-hidden, type=hidden or inline display/visibility hidden, including on an ancestor — are left out.
  • IDs are positional. They are assigned in page order on every snapshot; take a fresh snapshot after the page changes.

Diff

diff() compares the page with the previous snapshot, matching elements by selector. It returns urlChanged, titleChanged, addedActions, removedActions, mutatedActions (changes to text, value, disabled, checked, expanded, selected) and a text summary:

summary
=== PAGE STATE DELTA ===

Added (2 elements):
  + [@6] [input] "Card Number" (selector: #card)
  + [@7] [button] "Pay Now" (selector: #btn-pay)

The first call on a page returns a one-line description of the initial load instead.

CDP methods & REST

Alongside the standard Page, Runtime, DOM, Network, Target and Input domains, Orbis adds agent methods. They are available under the Orbis and Memora domains.

MethodParamsReturns
Orbis.getSemanticSnapshot{ focusSelector?, excludeSelectors? }Snapshot: action map, actions, Markdown, token estimate.
Orbis.getMarkdown{ focusSelector?, excludeSelectors? }Distilled Markdown for the current page.
Orbis.getStructuredData—OpenGraph, Twitter card, canonical, meta and JSON-LD.
Orbis.diff—Changes since the previous snapshot, plus the current snapshot.
Orbis.act{ actionId, type?: "click" | "type", text? }Click or type by action ID or selector.
Orbis.fillForm{ fields, submit?, steps? }Fill several fields, optionally submit; multi-step wizards via steps.
Orbis.saveSession / loadSession{ filePath }Write or restore cookies and web storage.

The same server answers HTTP requests. Every route is also available under /memora/….

MethodPathInputDescription
GET/orbis/snapshot?focus=&exclude=&format=markdown&id=Snapshot as JSON, or Markdown with format=markdown.
GET/orbis/goto?url=Navigate the default page and return the result with a snapshot.
POST/orbis/act{ actionId, type?, text?, id? }Click or type; returns success and a fresh snapshot.
POST/orbis/fill-form{ fields, submit? }Fill fields; submit defaults to true.
GET · POST/orbis/diff—State comparison against the previous call.
GET · POST/orbis/session—Export or restore session state.
POST/orbis/session/save{ filePath }Save session state to a file.
Terminal
curl "http://127.0.0.1:9222/orbis/goto?url=https://example.com"
curl "http://127.0.0.1:9222/orbis/snapshot?format=markdown"
curl -X POST http://127.0.0.1:9222/orbis/act \
  -H "Content-Type: application/json" -d '{"actionId":"@1"}'

WebDriver coverage

Implemented W3C WebDriver Classic commands:

  • Sessions & navigation — status, new/delete session, timeouts, URL, back, forward, refresh, title, page source.
  • Elements — find element(s) and nested finds by CSS selector, tag name, link text, partial link text and XPath; active element.
  • Element state & actions — selected, attribute, property, CSS value (inline styles), text, name, rect, enabled, displayed, computed role and label, click, clear, send keys.
  • Scripts, cookies, input — execute sync and async, cookies, actions.

Frames, alerts, shadow roots and printing are not supported, and screenshots return a blank image.

Stealth profile

Every request carries Chrome 130 on Windows headers: User-Agent, Accept, Accept-Language, Sec-Ch-Ua* client hints and Sec-Fetch-*. With stealth on (the default), Orbis also sets page-visible values to match before any page script runs: navigator.webdriver = false, platform, languages, hardware concurrency and device memory, plugins and MIME types, screen, media devices, battery, window.chrome and the Permissions API.

Stealth mode does not spoof canvas or WebGL, does not change the TLS fingerprint and does not solve CAPTCHAs. Use it only where automated access is allowed. Turn it off with --no-stealth when testing your own sites.

robots.txt

Terminal
npx memora-orbis --obey-robots
npx memora-orbis fetch https://example.com --obey-robots --robots-agent MyCrawler
  • robots.txt is fetched once per origin and cached for 24 hours.
  • The main navigation, every redirect hop, sub-resources and page fetch() calls are checked.
  • A 4xx robots.txt allows everything; a 5xx or network error disallows everything.
  • Blocked navigations fail with net::ERR_BLOCKED_BY_CLIENT over CDP.

Network options

These options work on the server and on fetch:

OptionDescription
--http-header "Name: Value"Add a header to every request. Repeatable.
--user-agent <ua>Override the User-Agent header.
--http-timeout <ms>Navigation request timeout.
--use-env-proxyUse HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY from the environment.
--proxy-bypass <hosts>Comma-separated hosts that skip the proxy, e.g. localhost,.internal.corp.
--insecure-disable-tls-host-verificationAccept self-signed or intercepting-proxy certificates.
--obey-robotsFetch robots.txt per origin and block disallowed requests (RFC 9309).
--robots-agent <token>Product token matched against robots.txt User-agent lines. Default MemoraBrowser.
--http-proxy, --proxy-bearer-tokenReserved for the managed proxy network in Orbis Cloud (coming soon).

When embedding the engine as a library, HTTP, HTTPS and SOCKS5 proxies (with credentials and bypass lists) can be set through the proxy network option.

Version check

When the server starts it asks orbis.memora.company whether a newer version is available. Set ORBIS_NO_TELEMETRY=1 to skip the check. It is also skipped when NODE_ENV=test.

Limitations

Orbis trades rendering for speed and agent-ready output. Know the trade-offs before you migrate a suite:

  • No pixels. No screenshots, PDFs or visual comparison. CDP Page.captureScreenshot returns a 1×1 placeholder.
  • Synthetic layout. Element boxes come from a simple grid, not real CSS layout.
  • No file uploads, frames or alerts over CDP or WebDriver.
  • Runtime APIs. Page scripts get fetch, timers and web storage. XMLHttpRequest is not available and MutationObserver is a no-op.
  • Cookies are kept in one jar per page and are not scoped by domain.
  • fork() rebuilds the copy from HTML and storage, so in-memory JavaScript state is not carried over.

For pages that need a full browser, MCP users can switch to --engine chrome.

License

Orbis is distributed under the Orbis Commercial & Community Evaluation License v1.0. You may install and run it for personal development, learning, testing and evaluation, including with local agents built on frameworks such as LangChain, Browser-Use, CrewAI or Stagehand in non-production environments.

Production or commercial use requires a commercial subscription or written agreement. Reverse-engineering the distributed build, reselling it, or hosting it as a competing multi-tenant service is not permitted.

Contact enterprise@memora.company