# Tabs & Navigation

Tabs are the unit of work in the box browser. `box.browser` opens and lists them. Every page operation, from navigation to screenshots to AI actions, runs on a specific `Tab` handle.

## Open a tab

`tab.create` opens a tab, navigates it to a URL, and waits for the requested lifecycle state. The first call also boots Chromium if it is not running yet.

<CodeGroup>
```typescript box.ts
const tab = await box.browser.tab.create("https://upstash.com", {
  waitUntil: "domcontentloaded",
  timeout: 30_000,
})

console.log(tab.id, tab.url, tab.title)
```

```python box.py
tab = box.browser.tab.create(
    "https://upstash.com",
    wait_until="domcontentloaded",
    timeout=30_000,
)

print(tab.id, tab.url, tab.title)
```
</CodeGroup>

- `waitUntil`: when navigation counts as done. One of `"load"` (default), `"domcontentloaded"`, or `"networkidle"`.
- `timeout`: navigation timeout in milliseconds. Defaults to `30000`. Pass `0` to disable it.

## Navigate

`goto` navigates the tab and returns the resulting page's content (title, URL, text, and links):

<CodeGroup>
```typescript box.ts
const page = await tab.goto("https://upstash.com/docs")
console.log(page.title, page.url)
```

```python box.py
page = tab.goto("https://upstash.com/docs")
print(page.title, page.url)
```
</CodeGroup>

Unlike `tab.create`, `goto` has no `waitUntil` or `timeout` options. It waits for the page to load with a fixed 60 second deadline.

## List and re-attach

Tab handles are addressed by their Chrome DevTools Protocol target id, which stays stable across navigations. You can store a tab id and re-attach to the same tab later, even from a different process:

<CodeGroup>
```typescript box.ts
// List the box's open tabs
const tabs = await box.browser.listTabs()
for (const t of tabs) {
  console.log(t.id, t.url, t.title)
}

// Re-attach to a tab by id (no network call)
const same = box.browser.getTab(tab.id)
await same.goto("https://news.ycombinator.com")
```

```python box.py
# List the box's open tabs
tabs = box.browser.list_tabs()
for t in tabs:
    print(t.id, t.url, t.title)

# Re-attach to a tab by id (no network call)
same = box.browser.get_tab(tab.id)
same.goto("https://news.ycombinator.com")
```
</CodeGroup>

<Note>
  A handle's `url` and `title` fields are the last known values from
  `tab.create` or `listTabs`. They are not updated live. Use
  [`tab.content()`](/box/overall/browser/reading-pages) to read the current
  state of the page.
</Note>

## Close a tab

<CodeGroup>
```typescript box.ts
await tab.close()
```

```python box.py
tab.close()
```
</CodeGroup>

Multiple tabs can be open at once. Each is independent, and operations on one do not affect the others. This is useful for comparing pages side by side or running [AI tasks](/box/overall/browser/ai-actions) against several pages in sequence.
