> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentcard.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Browser Use

> Use Agentcard with Browser Use to let your agent make purchases with your users' cards.

Let your agent pay with your users' own cards while it shops in a [Browser Use](https://browser-use.com) browser, whether your own agent does the shopping or Browser Use's hosted agent does. The Agentcard SDK connects to the browser through Playwright over its `cdpUrl`, the same way it attaches to any CDP browser. Browser Use lets several connections share one browser, so the SDK and the agent work in the same browser at the same time.

|                     | Your agent shops                    | Browser Use's agent shops                          |
| ------------------- | ----------------------------------- | -------------------------------------------------- |
| You create          | A browser, with `browsers.create()` | An agent run, with `runs.create()`                 |
| The SDK attaches to | That browser's `cdpUrl`             | The run's browser, before the shopping task starts |

You need a user with a card in the Vault first. See [Adding a card](/vault/adding-a-card).

## Install

```bash theme={null}
npm i @agent-cards/checkout@0.17.0 browser-use-sdk playwright-core
```

## Shop with your own agent

Create a Browser Use browser, connect Playwright to its `cdpUrl`, and attach Agentcard to the page before your agent reaches the payment form.

```ts theme={null}
import { BrowserUse } from 'browser-use-sdk/v4';
import { chromium } from 'playwright-core';
import { VaultClient, attachToPlaywright } from '@agent-cards/checkout';

const bu = new BrowserUse({ apiKey: process.env.BROWSER_USE_API_KEY! });
const session = await bu.browsers.create({ proxyCountryCode: 'us' });
const browser = await chromium.connectOverCDP(session.cdpUrl!);
const page = browser.contexts()[0].pages()[0];

const vault = new VaultClient({
  clientId: process.env.AGENTCARD_CLIENT_ID!,
  clientSecret: process.env.AGENTCARD_CLIENT_SECRET!,
});
await vault.syncRegistry();

const checkout = await attachToPlaywright(page, {
  vault,
  user: 'usr_8f3k2m',
  merchant: 'shop.agentcard.sh',
  amount: 583,
  currency: 'usd',
  onApprovalUrl: (url) => sendToUser(url),
});

// Now let the agent shop on this page.
await page.goto('https://shop.agentcard.sh');
```

An agent built on Browser Use's open-source Python library connects to the same browser. Give it the same `cdpUrl`, and keep the Node process above running while the agent shops:

```python theme={null}
from browser_use import Agent, Browser

browser = Browser(cdp_url=cdp_url, keep_alive=True)  # the cdpUrl from above
agent = Agent(task=task, llm=llm, browser=browser)
await agent.run()
```

The agent types the placeholder card, and the SDK pauses the payment until the user approves. With `keep_alive=True`, the browser stays open after the agent finishes, so you can still confirm the order with the merchant.

## Shop with Browser Use's agent

When Browser Use's hosted agent does the shopping, attach Agentcard before the shopping task starts. A run starts working as soon as you create it, so open the session with a first run that only opens the store. Attach Agentcard to that run's browser, wait until it is ready, then give the shopping task to a second run in the same session. Browser Use keeps a session on the same browser between runs.

```ts theme={null}
import type { Page } from 'playwright-core';

// 1. A first run opens the store and buys nothing.
const opener = await bu.runs.create({
  task: 'Open https://shop.agentcard.sh and stop there. Do not click anything.',
});
const ready = await bu.runs.waitForEvent(opener.id, 'browser.ready');
const browserId = ready.data.browser_session_id as string;
const res = await fetch(`https://api.browser-use.com/api/v4/browsers/${browserId}`, {
  headers: { 'X-Browser-Use-API-Key': process.env.BROWSER_USE_API_KEY! },
});
const { cdpUrl } = await res.json();

// 2. Attach Agentcard to every page, and wait until it is attached.
const browser = await chromium.connectOverCDP(cdpUrl);
const context = browser.contexts()[0];
const attach = (page: Page) =>
  attachToPlaywright(page, {
    vault,
    user: 'usr_8f3k2m',
    merchant: 'shop.agentcard.sh',
    amount: 583,
    currency: 'usd',
    onApprovalUrl: (url) => sendToUser(url),
  });
const checkouts = await Promise.all(context.pages().map(attach));
// The agent can open the checkout in a new tab, so attach to every page it opens.
context.on('page', (page) => {
  attach(page).then(
    (checkout) => checkouts.push(checkout),
    (err) => console.error('Agentcard could not attach to a new tab', err),
  );
});
await bu.runs.waitForCompletion(opener.id);

// 3. The shopping task runs in the same session, on the browser Agentcard is attached to.
// The placeholder the agent types: any of Stripe's published test cards.
const card = process.env.PLACEHOLDER_CARD_NUMBER!;
const run = await bu.runs.create({
  sessionId: opener.sessionId,
  task: `Buy one Enamel Camp Mug. Pay with card ${card}, expiry 12/34, CVC 123, and click Pay once. The payment then waits for the cardholder to approve on their phone. Do not click Pay again. Wait until the page shows the order is paid.`,
});
const dispatched = await bu.runs.waitForEvent(run.id, 'run.dispatched');
if (dispatched.data.browser_session_id !== browserId) {
  // Browser Use moved the session to a new browser, and Agentcard is not attached there.
  await bu.runs.cancel(run.id);
  throw new Error('The session moved to a new browser. Attach to it and start the purchase again.');
}
await bu.runs.waitForCompletion(run.id);
```

Browser Use can move a session to a new browser, for example after the old one times out. The shopping run names its browser when it is dispatched, before the agent takes its first step, so the example cancels the run there instead of letting the agent pay in a browser Agentcard is not attached to.

Put the placeholder card in the task, and tell the agent that the payment waits for the user after Pay. Send the approval link to the user over your own app or thread, and keep it out of the task and your logs: the link opens the approval screen for this payment, and only the user should see it.

## Stop the browser

A Browser Use browser keeps running until it times out or you stop it, and a run's browser stays open after the run finishes. Closing the Playwright connection does not stop it. Once you have confirmed the order with the merchant, stop the browser:

```ts theme={null}
await bu.browsers.stop(session.id); // or browserId, for a run's browser
```

## Next

The rest of the flow is identical to any Vault purchase: placeholder card, passkey approval, real card swapped in, confirm with the merchant. Follow the [Vault Quickstart](/vault/quickstart) from step 4, or read [Completing a purchase](/vault/completing-a-purchase).
