# Anchor (https://tenki.cloud/docs/sandbox/anchor)

> For the complete documentation index, see [llms.txt](https://tenki.cloud/llms.txt)

Start from Tenki's pre-built Anchor image and connect to a remote browser over CDP.

Tenki's public `tenki/anchor:stable` image starts with the standard [`sandbox` base image](https://tenki.cloud/docs/sandbox/base-image.md) and adds `playwright-core` plus the `anchor-smoke` command. It does not include a local browser, an Anchor API key, or a browser profile. Your code connects to an Anchor-managed browser over CDP.

## ## Anchor Browser: production-grade browsers for agents

**The missing piece for agents running in your sandbox.**

Your sandbox gives agents a place to run. Anchor gives them a browser they can actually use once they get there. Together, that is the full stack an agent needs, compute and browser, without your team stitching it together.

**Why agents need this:**

Agents that reason well and click well still get stopped cold in production by things no model upgrade fixes:

* **Bot detection:** Cloudflare, Akamai, DataDome, and reCAPTCHA are built to keep automated browsers out.
* **Authentication at scale:** MFA and session management assume a human at a keyboard, and break down at hundreds or thousands of concurrent agent sessions.
* **Fragile automations:** dynamic pages and brittle selectors mean tasks slow down and fail as workflows get longer.
* **Runaway cost:** retries, token spend, and infra add up fast at scale.

**What Anchor brings into your sandbox:**

* 🛡️ &#x2A;*Anchor Chromium:** a hardened Chromium fork with humanized fingerprints and human-like mouse and keystroke behavior. Stealth mode, proxies, captcha solving, and Cloudflare Web Bot Auth are available as add-ons.
* 🌐 &#x2A;*Anchor VPN:** a geo-aware network built into the browser, so agent traffic looks like a trusted user rather than flagged datacenter or third-party proxy traffic. Anchor enables it per account.
* 🔐 &#x2A;*Managed Authentication:** Identities or browser profiles that carry saved credentials, MFA, and persistent sessions, so agents log in once and stay logged in. You attach them as session options.
* ⚡ &#x2A;*Self-healing automation:** the Web Action Cache in Anchor Tasks lets previously seen flows run deterministically instead of re-reasoning every click, so multi-hundred-step tasks stay fast and keep running when a page changes.

All of it runs on Anchor's side of the CDP connection. The Tenki image ships `playwright-core` ready to connect, so there is no browser-hardening layer for your team to build or maintain, and credentials never land in the image, template, or snapshot. None of these are on automatically. The sample below opens a default browser session; enabling them takes Anchor plan features or session options, and [Anchor's documentation](https://docs.anchorbrowser.io/) covers each one.

## ## Start a session

Create an [Anchor API key](https://app.anchorbrowser.io/api-keys), export it locally, then pass it only to the session:

```bash
export ANCHOR_API_KEY=<your-anchor-api-key>

tenki sandbox create \
  --image tenki/anchor:stable \
  --env "ANCHOR_API_KEY=$ANCHOR_API_KEY" \
  --name anchor-demo
```

The shell history contains the environment variable reference, not the key value. Do not add the key to a template, snapshot, source file, or image.

Run the built-in connectivity check:

```bash
tenki sandbox exec --session anchor-demo -- anchor-smoke https://example.com
```

The command creates an Anchor session, connects with Playwright, loads the requested URL, prints its final URL and title, and ends the Anchor session. A successful result looks like:

```json
{ "url": "https://example.com/", "title": "Example Domain" }
```

Terminate the Tenki session when you finish:

```bash
tenki sandbox terminate anchor-demo
```

## ## Use Playwright in your code

`playwright-core` is installed under `/home/tenki/node_modules`, so JavaScript and TypeScript projects below `/home/tenki` can import it without installing another copy. Create the Anchor session through its API, connect to the returned CDP URL, and always end the remote session in a `finally` block. The empty request body asks for a default session; pass [session options](https://docs.anchorbrowser.io/quickstart/create-session) there to attach a profile, an Identity, or a proxy.

```javascript

const apiKey = process.env.ANCHOR_API_KEY;
if (!apiKey) throw new Error("ANCHOR_API_KEY is required");

const response = await fetch("https://api.anchorbrowser.io/v1/sessions", {
  method: "POST",
  headers: {
    "anchor-api-key": apiKey,
    "content-type": "application/json",
  },
  body: "{}",
});
if (!response.ok) throw new Error(`Anchor returned HTTP ${response.status}`);

const payload = await response.json();
const session = payload.data ?? payload;
let browser;

try {
  browser = await chromium.connectOverCDP(session.cdp_url);
  const context = browser.contexts()[0] ?? (await browser.newContext());
  const page = context.pages()[0] ?? (await context.newPage());
  await page.goto("https://example.com");
  console.log(await page.title());
} finally {
  await browser?.close();
  await fetch(`https://api.anchorbrowser.io/v1/sessions/${session.id}`, {
    method: "DELETE",
    headers: { "anchor-api-key": apiKey },
  });
}
```

Write the script into the sandbox or clone your project there, then run it with Node.js.

## ## Pin an exact build

`stable` moves to each newly published build. When a workload has to stay on the exact build it was tested against, resolve the tag once and launch the snapshot reference it returns:

```bash
tenki sandbox registry resolve tenki/anchor:stable
# image_id    : <image-id>
# snapshot_id : <snapshot-id>

tenki sandbox create --image tenki/anchor@<snapshot-id>
```

A snapshot reference never moves, so it keeps launching that build after `stable` advances.