Orbe Docs Tiếng Việt Get started

Automation & SDK

Drive an Orbe profile from your own code — or from an AI assistant — through an internal control channel inside the Chromium core. Clicks, keys and scrolling travel the same event path as a real user's, and pages are read on the browser side rather than by running scripts in them.

Python SDK Any language MCP for AI assistants

Because there is no automation layer bolted on top, the page sees:

  • no navigator.webdriver,
  • no CDP (Chrome DevTools Protocol) session,
  • no open debug port,
  • no injected script and no isolated world.
Every action is driven inside the browser core the way a mouse and keyboard reach it. Opening a profile with the SDK gives the same fingerprint result as opening it by hand — the control layer does not undo the work of the fingerprint layer.

What makes it different

The usual way to drive a browser for automation is over CDP, replaying instant, mechanical input. Orbe takes a different route by owning the browser engine underneath: input is delivered through the real event path, and the page is read on the browser side.

No automation trace

The signals a page can read to tell automation from a person — navigator.webdriver, the --enable-automation flag, a CDP session — are simply not present, because Orbe never turns them on. A clean fingerprint stays clean while you script it.

Human, per-profile behaviour

Movement and typing are humanized from each profile's own seed: curved mouse paths, think-pauses, typing rhythm, scroll inertia. The same profile behaves like the same person every day; different profiles behave like different people.

Discipline, on by default

Every command passes through a proxy check before opening, account-safety pacing, and a checkpoint detector that stops instead of pushing on — and a one-time warning when a profile works outside its usual hours.

One behaviour engine

Python, the line protocol for other languages and the MCP server all share a single humanization engine, so behaviour never drifts between clients; nothing is re-implemented.

Quickstart

The SDK is a small Python package that comes with the installer. You need Python 3.9 or newer on the Windows machine that runs Orbe. Install the package once from your Orbe folder (PowerShell):

python -m pip install --force-reinstall (Get-ChildItem "$env:LOCALAPPDATA\Programs\Orbe\app\current\sdk\orbe-*.whl").FullName

The package uses only the standard library and finds Orbe on its own. If you installed Orbe in a different folder, use that folder in place of %LOCALAPPDATA%\Programs\Orbe in the command, and set ORBE_EXE to the full path of Orbe.exe in its app\current. After an Orbe update, run the same command again to pick up the new package.

Then import it as orbe:

import orbe

# Opens the profile, connects the channel and checks the proxy —
# all on enter. Closes cleanly on exit.
with orbe.Trinh("my-profile") as t:
    t.goto("https://example.com/login")
    t.wait_for("Sign in")            # wait until the text appears
    t.click("Sign in")               # click the element carrying that text
    t.type("my-username", enter=True)  # type with human timing, then Enter
    t.scroll(600)                    # one human scroll gesture, downward
    print(t.read()[:200])            # read the visible page text
    t.screenshot("after-login.png")  # capture through the compositor
The session is opened with a context manager (with … as t:). Entering opens the browser and runs the safety checks; leaving closes the browser and the channel, even if your code raises.

Prefer to run from an AI assistant such as Claude instead of writing code? Jump to MCP.

The Trinh session Python

orbe.Trinh is the public SDK session. It is safe by default: the proxy check and the checkpoint stop are always on, with no switch to turn them off — that is deliberate, because the first thing an undisciplined run costs you is an account. Only account-safety pacing can be turned off, per session.

orbe.Trinh(profile_id, *, headless=False, timeout=30.0,
           platform=None, pacing="on", on_rest=None, rotate=None, open_on_rotate_fail=False)

The only required argument is the profile id; the rest are keyword-only options:

profile_id str
The Orbe profile id to open. Required.
headless bool
Run the browser hidden. Default False.
timeout float
Per-command timeout in seconds. Default 30.0.
platform str
Platform hint (the site you are working) — picks that platform's checkpoint phrases and the usual-hours window used for the out-of-hours warning. Usually inferred from the URL.
pacing "on" | "off"
Account-safety pacing for this session. Default "on"; "off" removes the human-like rests (see the warning under pacing).
on_rest callable
Optional; called with the number of seconds each time pacing starts a rest.
rotate bool | None
For a profile on a rented proxy port: True gets a new IP before the browser starts, False skips it for this open, None (default) follows the profile's Rotate IP on open setting. Ignored for your own proxy or no proxy.
open_on_rotate_fail bool
If getting a new IP fails, open on the current IP instead of raising. Default False.
The behaviour identity of a profile — its seeded "person" — comes from the profile itself, so there is no seed argument. The verbs below are the orbe package's stable, official surface. An option that your installed version does not support raises orbe.NotSupported; every SDK error is an orbe.OrbeError.

Lifecycle

open(start_url=None) → Trinh

Open the browser for the profile and connect the control channel. Called automatically by with orbe.Trinh(...) as t:. Runs the proxy check on open — if the proxy is dead, in the wrong country or incompletely set up, it raises before a browser window is shown.

close() → None

Close the browser and the channel. Called automatically on leaving the with block. Safe to call more than once.

Navigate & wait

goto(url) → str (tab id)

Navigate the current tab to url. Returns the tab id; later commands target this tab.

wait(seconds) → None

A plain pause — a "reading" or "thinking" gap. Use between steps as a real user would.

wait_for(text, timeout=15.0, poll=0.4) → bool

Wait until an element carrying text appears (substring, case-insensitive). Returns True if seen within timeout, else False. Polls through the channel — no script runs in the page. Do not act on a page before you have waited for something distinctive on it.

Read the page

read() → str

Return all visible text on the page, read on the browser side (C++ renderer). Use it to learn what is on the page and to confirm an action worked.

elements() → list[dict]

List actionable elements (buttons, links, inputs) as {type, text, link, x, y, w, h} — the element's kind, its text, its link, and its viewport box. Use it to find precise coordinates when clicking by text is not enough.

Act like a person

click(text) → bool

Click the element carrying text (substring, case-insensitive; picks the smallest matching box, so you hit the real control, not its container). The mouse moves there with human timing. Returns False if no such element exists yet — in that case wait_for or read again rather than guessing coordinates.

click_xy(x, y) → None

Click a viewport coordinate, for when you already know the point (for example from elements() or a screenshot).

type(text, enter=False) → None

Type text with human rhythm into the focused element — click the field first. enter=True presses Enter after the last character.

scroll(dy, x=400, y=400) → None

Scroll one real human gesture from point (x, y). dy only chooses the direction (negative = up); the distance is one human gesture, not an exact pixel amount. After scrolling, read or screenshot to see where it landed.

scroll_until(text, max_cu_chi=15, nghi=0.6) → bool

Scroll down with human gestures, repeating until the page shows text or the bottom is reached (the page text stops changing). Returns True if found. This is the right way to "scroll to X" — do not guess pixel amounts.

Screenshot

screenshot(path=None) → bytes (PNG)

Capture the visible viewport through the compositor. The image is a lossless PNG of the page as it really renders — it carries no canvas noise (canvas is noised per-profile, but a screenshot is the true render), so it is reliable for verifying and debugging. Returns the PNG bytes; if path is given, also writes the file.

Safe by default

The public SDK wraps every command in a discipline layer. You do not opt in, and the proxy check and the checkpoint stop below cannot be switched off; pacing is on by default and can be turned off per session.

  • Out-of-hours warning. Automation is never stopped because of the time of day. When a profile works outside its usual hours — 7:00–23:00 by default in the proxy's timezone (without a proxy, your own IP's timezone, or the profile's country if that can't be looked up); with a platform hint, TikTok 8:00–24:00, YouTube and Google 6:00–24:00, Twitter 7:00–24:00, Facebook, Instagram and Shopee 7:00–23:00 — Orbe warns once per session and carries on, for example: "Outside usual active hours 7:00–23:00 (Asia/Ho_Chi_Minh); it is now 23:00. Automation continues — accounts active at unusual hours are more likely to be reviewed." The SDK prints it to stderr as [orbe] warning: …, the MCP server sends it as a warning notification, and the Workflow Editor shows it as a ! line in the run results. The warning appears only while pacing is on.
  • Third-party proxy limit. A profile outside the 20-profile limit opens without its proxy; look for the proxy_disabled flag in the Local API and MCP profile list, open result and batch or schedule result rows.
  • Proxy check before opening. If the profile has a proxy and it is unreachable, in the wrong country or incompletely set up, Orbe does not open — a run on the wrong IP is more expensive than a run that never started. A profile with no proxy opens directly on your own IP.
  • Checkpoint / captcha detection. After each state-changing step, Orbe reads the page (waiting for it to settle) and, if it sees a checkpoint or challenge — in the text or the URL — it stops, captures a screenshot, and reports it. Orbe never tries to solve or bypass a checkpoint.

Account-safety pacing

Orbe automation pauses like a person: about 1 in 8 actions (click, type, scroll, navigate) is followed by a 3–20 s rest. A tool call may take longer than the mouse movement itself; this is intentional, not a hang.

While it rests, the MCP server sends a progress message resting N s (account-safety pacing); the SDK prints that line to stderr, or calls your on_rest(seconds) callback in Python.

Pacing is on by default. You can turn it off for a session or a workflow:

  • Python — orbe.Trinh(profile_id, pacing="off");
  • other languages — orbe-sdk.cmd <profile-id> --pacing off;
  • MCP — open with "pacing": "off";
  • Workflow Editor — the Pacing: On button next to Run, saved per workflow; turning it off asks you to confirm.
Pacing is off: actions run back-to-back with no human-like pauses. Platforms flag machine-speed activity, so this raises the risk to your account.
Discipline is a wrapper around the same session, so it applies to the SDK, to flows, and to the MCP server alike — there is no "raw" path in the product that skips it.

Handling a block

When discipline stops a command, the SDK raises a discipline error and the MCP tool returns BLOCKED (…) — carrying an English message and, for a checkpoint, the matched phrase, the URL and a screenshot. Catch it and handle it; do not retry blindly. Each row below is a distinct block condition:

ClassWhat happenedWhat to do
orbe.CheckpointA checkpoint or challenge was detected on the page or in the URL. Carries the matched phrase, the URL and a screenshot.Stop this profile. Review by hand. Do not automate through it.
orbe.ProxyErrorThe profile's proxy is unreachable, in the wrong country, or its settings are incomplete.Fix the proxy before opening.
orbe.PageUnreadableThe page could not be read after retrying — treated as unsafe, not "clean".Let it stop; check connectivity and the page.
orbe.BehaviorDataMissingThe human-behaviour library is missing, so movement would be synthetic (and detectable).Reinstall or repair Orbe so the behaviour data is present.
orbe.LicenseDisabledThe account's license is not valid for this action.Sign in again and check your key in the dashboard.
orbe.LedgerErrorThe usage counter file is corrupt — the SDK fails closed rather than guessing.Investigate before forcing more actions.
import orbe

try:
    with orbe.Trinh("my-profile") as t:
        t.goto("https://example.com")
        t.click("Post")
except orbe.Blocked as e:
    # A block. str(e) is an English message describing the condition;
    # a checkpoint block also carries the matched phrase, URL and screenshot.
    notify_me(str(e))          # a human should look at this profile
    # do NOT retry the same action in a loop
Every discipline block subclasses orbe.Blocked, so except orbe.Blocked catches them all; catch a specific class from the table above when you want to handle one condition differently. str(e) is an English message, and a checkpoint block also carries the matched phrase, the URL and a screenshot.

orbe.RateLimited and orbe.OutsideHours still exist so older code that catches them keeps working, but Orbe no longer raises them: there are no action caps, and nothing is blocked because of the time of day.

When a new IP can't be obtained

With rotate on (or the profile's Rotate IP on open ticked), a failed rotation raises orbe.RotateFailed and the browser does not open. It is not a discipline block — it subclasses orbe.OrbeError, not orbe.Blocked. It carries .reason and .retry_after:

reasonMeaningWhat to do
cooldownThe port changed IP less than 3 minutes ago. .retry_after is the number of seconds to wait.Wait retry_after seconds, or open with rotate=False.
timeoutNo new IP after 60 s — the proxy may still be changing.Try again shortly.
apiThe proxy provider didn't change the IP.Try again; if it persists, check the port with your provider.
no_tokenNo proxy token is set, so the port can't be rotated.Add the token in Settings.

.retry_after is a whole number of seconds when reason is cooldown, otherwise None. Pass open_on_rotate_fail=True to open on the current IP instead.

Other languages Any language

Any language can drive the same session over a small line protocol. The installer adds the bridge orbe-sdk.cmd to your Orbe folder; start it as a subprocess with the profile id and exchange one JSON object per line on stdin/stdout (started with only the profile id and no input, it does nothing). A quick test from Command Prompt: (echo {"cmd":"open"}& echo {"cmd":"close"}) | "%LOCALAPPDATA%\Programs\Orbe\orbe-sdk.cmd" <profile-id>. If you installed Orbe elsewhere, use that folder instead.

"%LOCALAPPDATA%\Programs\Orbe\orbe-sdk.cmd" <profile-id> [--rotate on|off] [--open-on-rotate-fail]

→ {"cmd":"open","url":"https://example.com"}   ← {"ok":true,"result":null}
→ {"cmd":"goto","url":"https://example.com"}    ← {"ok":true,"result":"<tab_id>"}
→ {"cmd":"wait_for","text":"Sign in"}           ← {"ok":true,"result":true}
→ {"cmd":"click","text":"Sign in"}              ← {"ok":true,"result":true}
→ {"cmd":"screenshot"}                           ← {"ok":true,"result":{"png_b64":"…"}}
→ {"cmd":"close"}                                ← {"ok":true,"result":null}

Commands are the same set as the SDK: open · goto · wait · wait_for · click · click_xy · type · scroll · scroll_until · read · elements · screenshot · close. A failed command returns {"ok":false,"error":"…"} and never crashes the bridge. --rotate on|off and --open-on-rotate-fail go on the command line after the profile id (not in the open command); a failed rotation returns {"ok":false,"code":"RotateFailed","error":"…","reason":"…","retry_after":…}. stdout carries the JSON protocol only; diagnostics go to stderr. Read results line by line and match them to the order you sent.

Local API for your own tools

Orbe also runs a Local API that your own scripts and tools can call — on this computer only (127.0.0.1), never on your network. It is on by default, on a random port chosen when Orbe installs. Manage it in Settings → Local API (the Local API item in the sidebar opens it):

  • Enable Local API for external tools — turn it off if you don't use external tools;
  • Port and Apply — change the port;
  • Copy URL — the address, http://127.0.0.1:<port>/orbe/v1;
  • Copy key — every request must send this key in the X-Orbe-Key header; a missing or wrong key gets 401. Treat the key like a password — anyone with it can control your profiles.

The Local API drives profiles through the same internal channel as the SDK — no CDP and no debug port; a request for CDP is refused with an error.

MCP — use Orbe from an AI assistant MCP

Orbe ships an MCP server that exposes the same actions as tools, so an assistant such as Claude Code, Cursor or Codex can act inside a profile in natural language. It is traceless like the SDK: no CDP, no in-page script, no debug port.

Install

On the machine that has Orbe (Windows), in Command Prompt. The MCP server is built into Orbe.exe, so there is nothing else to install:

claude mcp add orbe -- "%LOCALAPPDATA%\Programs\Orbe\app\current\Orbe.exe" --mcp

If you installed Orbe in a different folder, use the Orbe.exe in that folder's app\current — it keeps pointing at the current version after updates. You drive the server through the orbe tools, not by name.

Tools

ToolWhat it does
openOpen a profile (profile, optional headless, url) — call this first. Optional rotate (boolean; blank follows the profile's Rotate IP on open) and open_on_rotate_fail (boolean, default false). A failed rotation returns isError with rotate_failed (<reason>): … and structured reason / retry_after.
gotoNavigate the current tab to url.
waitWait until the page shows text (returns found), or wait seconds.
readRead all visible text on the page.
elementsList actionable elements with their text and box.
clickClick the element carrying text, or coordinates x,y.
typeType text into the focused element; enter: true to submit.
scrollScroll one human gesture in the direction of dy.
scroll_untilScroll down until text appears or the bottom is reached.
screenshotCapture the page, returns a PNG.
closeClose the profile.
list_blocksList the workflow blocks Orbe supports and their fields — read before drafting a workflow. Data only; no profile needed.
submit_flowSubmit a workflow (built from list_blocks steps) into Orbe as a draft — validated and saved, never run; the user reviews and runs it in the Workflow Editor. Data only.

The last two tools let an assistant build a workflow for the user rather than drive the browser directly: it reads list_blocks, writes the flow, and submit_flow drops it into the Workflow Editor as a draft to review — it never auto-runs. See Build with AI.

Several profiles can be open at once; any tool with profile left blank targets the most recently opened one.

How an assistant should work

  1. open → goto → wait for a distinctive piece of text before acting.
  2. read to learn the page; screenshot when layout or images matter.
  3. Click by the text on the element — the most reliable way. For an icon with no text, read coordinates from a screenshot and click x,y.
  4. To type into a field: click it first, then type.
  5. To reach something below the fold, use scroll_until, not repeated scroll guesses.
  6. After each important action, read or wait to confirm the page changed — do not assume success.
  7. close when done.
If discipline stops a tool, it returns BLOCKED (<code>): <reason> with isError and structured details (including the checkpoint phrase, URL and screenshot). The assistant must handle it — stop, report, or wait — not click on regardless.

Rules for the assistant

  • Do not mix other automation tools into an Orbe profile — Playwright, Puppeteer, Selenium or anything that attaches over CDP. Attaching once leaves exactly the trace Orbe exists to avoid.
  • Move like a person. Timing is already humanized; your part is not to fire dozens of actions back to back without reading the page.
  • Do not enter a password or secret the user has not given you in this session.

Recipes

Complete, runnable versions of these are on this site under examples/ — login_then_post.py, fill_form.py, scrape_list.py and fleet_multi_profile.py (many profiles at once) — each using only orbe and the standard library, with credentials read from the environment. The snippets below show the shape.

Log in, then confirm

import orbe

with orbe.Trinh("my-profile") as t:
    t.goto("https://example.com/login")
    t.wait_for("Password")
    t.click("Email")
    t.type("me@example.com")
    t.click("Password")
    t.type("...", enter=True)
    if t.wait_for("Your feed", timeout=20):
        print("logged in")
    else:
        t.screenshot("login-stuck.png")   # something to look at by hand

Reach something below the fold

with orbe.Trinh("my-profile") as t:
    t.goto("https://example.com/long-page")
    if t.scroll_until("Load more"):
        t.click("Load more")

Click a precise element with elements()

with orbe.Trinh("my-profile") as t:
    t.goto("https://example.com")
    for el in t.elements():
        if el["type"] == "button" and "Follow" in (el["text"] or ""):
            t.click_xy(el["x"] + el["w"] // 2, el["y"] + el["h"] // 2)
            break

What Orbe does not do

No captcha solving No ban guarantees No CDP / debug port

Automation removes the automation trace; it does not change how a platform judges an account. Orbe gives every account a consistent, real-looking machine, its own IP, and human input — but how you nurture the account is still your part. Any tool that promises bans will never happen is not being honest with you.

See also Get started and Proxy.