> ## Documentation Index
> Fetch the complete documentation index at: https://browseruse-0aece648-codex-docs-supported-exports.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Use https://docs.browser-use.com/llms.txt and its linked .md pages for current documentation. The managed full bundle is https://docs.browser-use.com/.well-known/llms-full.txt and can be cached for up to 24 hours. Do not use the obsolete /cloud/llms*.txt or /open-source/llms*.txt static exports.
> Choose Cloud API V4 for new agent integrations; V2 is the lower-cost option for simple tasks. Keep V3 examples explicitly versioned. The open-source browser-use library and hosted browser-use-sdk have different APIs.
> Cloud authentication uses X-Browser-Use-API-Key, without a Bearer prefix. Install or upgrade browser-use-sdk and use its explicit v4 import for V4. Check the published OpenAPI reference for request fields; do not invent SDK support for new fields.
> Cloud concurrency and HTTP request rate are separate. Read GET /api/v2/billing/account for the key’s projectId, concurrentSessionLimit, activeSessionCount, and credit balance, including when using V4. Keys in one project share capacity and credits; rateLimit is a legacy concurrency alias, not requests per second.
> Keep the highest applicable existing, legacy-plan, and spend-tier concurrency grant. Current spend tiers are 10 / 50 / 250 / 500 / 1000 at $0 / $200 / $1000 / $5000 / $25000 in qualifying project payments. Legacy or externally billed projects can follow different billing paths; trust the account limit. See https://docs.browser-use.com/cloud/guides/concurrency.md.
> Budget polling across the project: the standard general bucket is 25 requests/second, including V4 event reads and full run reads. Selected status reads have a separate higher bucket. Use bounded workers, stagger polls, respect Retry-After, and drain hasMore event pages after terminal status. A busy V4 session returns 409; its queue holds 10 pending messages and is not a project-wide batch queue.
> A completed run or closed CDP connection does not immediately stop its cloud browser. Stop unneeded owned browsers with PATCH /api/v4/browsers/{id} and {"action":"stop"}. A client wait timeout does not cancel the server-side run.
> Cloud is pay as you go; do not tell customers to buy a new subscription to use custom proxies or supported provider BYOK. Usage funding and model eligibility still apply. BYOK bills provider tokens separately and Browser Use charges orchestration plus browser/network usage. See https://docs.browser-use.com/cloud/guides/billing.md.
> Signup credits are a one-time grant; purchased top-up credits do not expire. Check the API key’s project before diagnosing missing credits. API-key monthly spending caps are soft limits, not a strict prepaid wallet; concurrent or already-running work can exceed them. Auto recharge has separate trigger and purchase amounts and can charge immediately when enabled below the threshold. Use https://browser-use.com/pricing for current rates.

# Rerunnable scripts

> Save a Browser Use task as a rerunnable script for repeated live data extraction and self-healing runs.

Teach a Cloud agent a repeated browser task once. It can save the working code
in its [workspace](/cloud/agent/workspaces). Later runs reuse that script,
fetch fresh data from the live site, and repair the code if the site changed.

This pattern works well for repeated data extraction, checks, and reports. The
example below collects the top five Hacker News stories. The first run writes
and tests the script. Every later run sends a new request to the live page.

<img src="https://mintcdn.com/browseruse-0aece648-codex-docs-supported-exports/pg6YX8jO9xwCWYaf/cloud/images/v4-scripts-light.svg?fit=max&auto=format&n=pg6YX8jO9xwCWYaf&q=85&s=2ac626ad6fe0370739d0f5bd4ff4795d" alt="A first agent run saves and tests script.py and a README in a workspace; later runs reuse the script and repair it only when necessary" noZoom className="block dark:hidden" width="1200" height="430" data-path="cloud/images/v4-scripts-light.svg" />

<img src="https://mintcdn.com/browseruse-0aece648-codex-docs-supported-exports/pg6YX8jO9xwCWYaf/cloud/images/v4-scripts-dark.svg?fit=max&auto=format&n=pg6YX8jO9xwCWYaf&q=85&s=c8ad54eac8f6f2cd540d99fa61c1f59f" alt="A first agent run saves and tests script.py and a README in a workspace; later runs reuse the script and repair it only when necessary" noZoom className="hidden dark:block" width="1200" height="430" data-path="cloud/images/v4-scripts-dark.svg" />

<Note>
  The file stays. The running process does not. Each later run starts an agent
  again, but it can reuse the code instead of rebuilding the browser workflow.
</Note>

## Save the working script

Create one workspace, then ask the first run to do the job and save a tested
script:

<CodeGroup>
  ```python Python theme={null}
  from browser_use_sdk.v4 import BrowserUse

  client = BrowserUse()
  workspace = client.workspaces.create(name="live-hn-data")

  first = client.runs.create(
      """
      Open https://news.ycombinator.com/ and return the top five story titles and
      URLs as JSON.

      Save a script at scripts/extract_top_stories.py that collects the same
      fields. The script must send a fresh request to the live page every time it
      runs. Do not hard-code story titles, save the page HTML, or read an old
      result. Print JSON with source_url set to https://news.ycombinator.com/ and
      include fetched_at, source_sha256, and stories.

      Run the script twice and save the outputs as proof/run-1.json and
      proof/run-2.json. Confirm both outputs have a fresh fetched_at value and
      five stories. Add scripts/README.md with the command to run it again.
      """,
      model="grok-4.5",
      workspace_id=workspace.id,
  )
  client.runs.wait_for_completion(first.id)

  saved = client.workspaces.files(workspace.id, prefix="scripts/")
  print([file.path for file in saved.files])
  print(f"Keep this workspace ID: {workspace.id}")
  ```

  ```typescript TypeScript theme={null}
  import { BrowserUse } from "browser-use-sdk/v4";

  const client = new BrowserUse();
  const workspace = await client.workspaces.create({ name: "live-hn-data" });

  const first = await client.runs.create({
    task: `
      Open https://news.ycombinator.com/ and return the top five story titles and
      URLs as JSON.

      Save a script at scripts/extract_top_stories.py that collects the same
      fields. The script must send a fresh request to the live page every time it
      runs. Do not hard-code story titles, save the page HTML, or read an old
      result. Print JSON with source_url set to https://news.ycombinator.com/ and
      include fetched_at, source_sha256, and stories.

      Run the script twice and save the outputs as proof/run-1.json and
      proof/run-2.json. Confirm both outputs have a fresh fetched_at value and
      five stories. Add scripts/README.md with the command to run it again.
    `,
    model: "grok-4.5",
    workspaceId: workspace.id,
  });
  await client.runs.waitForCompletion(first.id);

  const saved = await client.workspaces.files(workspace.id, {
    prefix: "scripts/",
  });
  console.log(saved.files.map((file) => file.path));
  console.log(`Keep this workspace ID: ${workspace.id}`);
  ```
</CodeGroup>

## Rerun it later

Copy the workspace ID from the first process. Pass that ID without a session ID
to start a new conversation with the saved files:

<CodeGroup>
  ```python Python theme={null}
  from browser_use_sdk.v4 import BrowserUse

  client = BrowserUse()
  workspace_id = "your-workspace-id"

  later = client.runs.create(
      """
      Run python scripts/extract_top_stories.py and return its JSON. Check that
      fetched_at is current, source_url is https://news.ycombinator.com/, and it
      has five stories. If the script fails or the result is malformed, inspect
      the live page and repair the saved script before returning the new result.
      """,
      model="grok-4.5",
      workspace_id=workspace_id,
  )
  result = client.runs.wait_for_completion(later.id)
  print(result.result)
  ```

  ```typescript TypeScript theme={null}
  import { BrowserUse } from "browser-use-sdk/v4";

  const client = new BrowserUse();
  const workspaceId = "your-workspace-id";

  const later = await client.runs.create({
    task: `
      Run python scripts/extract_top_stories.py and return its JSON. Check that
      fetched_at is current, source_url is https://news.ycombinator.com/, and it
      has five stories. If the script fails or the result is malformed, inspect
      the live page and repair the saved script before returning the new result.
    `,
    model: "grok-4.5",
    workspaceId,
  });
  const result = await client.runs.waitForCompletion(later.id);
  console.log(result.result);
  ```
</CodeGroup>

## Live data, not a cached answer

The saved script must request the source page on every execution. `fetched_at`
shows when the request ran, and `source_sha256` identifies the response body.
The data can stay the same between two runs when the page has not changed. The
script still fetched it again.

Do not put old output, page HTML, or fixed values inside the script. Save output
files only as optional history or proof.

## Can rerunnable tasks be cheaper at scale?

Reusing code can remove browser steps and model work that would otherwise be
repeated on every extraction. Every later run still starts a model and uses
tokens, so the savings depend on the task, site, and model. Compare the cost and
duration of the first run with later runs in your own project before making a
savings claim.

## Workspace or session?

* Pass `workspace_id` / `workspaceId` for a new conversation with the same
  files. The new run gets a new browser.
* Pass `session_id` / `sessionId` to continue the old conversation and its
  workspace. Cloud can also reuse that session's browser while it is still
  alive.

A saved script can break when a site changes. Ask the agent to check the live
result and self-heal the script instead of trusting stale output.
