Back to Knowledge Hub
Getting Started

Browser-Use Setup with a Controlled Browser

Configure browser-use with an explicit Chromium executable and profile, verify the launch, and keep human approval around consequential browser actions.

BotBrowser Team

Browser-Use Setup with a Controlled Browser
Documentation

Want the structured docs for Getting Started?

This article lives in the editorial library. For step-by-step setup, reference material, and ongoing updates, jump into the docs section.

Browser-use can plan browser tasks, but its agent loop does not choose a trustworthy executable or decide whether a consequential action is safe. BotBrowser can provide a profile-backed Chromium executable for an authorized workflow; the operator still has to select the executable and profile, verify what started, and approve actions that change accounts, money, or data. The browser automation getting-started map explains the general first run; this page focuses on the browser-use handoff.

For browser-use specifically, BotBrowser supports the explicit Chromium launch and --bot-profile argument shown below; it does not provide the agent framework, select a task policy, or guarantee a site's classification. Keep that product boundary in the run record so a working launch is not mistaken for a completed business action.

An operator gives browser-use a task, browser-use launches an explicit executable and profile, a fixture is verified, and an approval gate precedes consequential actions

TL;DR

  • Treat browser-use as a planner and browser controller, not as a profile or policy authority.
  • Pass an explicit Chromium executable and an approved profile argument through the underlying Playwright launch.
  • Read back the running process and a page on an owned fixture before giving the agent a real task.
  • Pause for an operator before credentials, purchases, deletion, permission changes, or any irreversible submission.
  • A correct launch proves configuration only; it does not promise a detector or application outcome.

Contents

Separate planning, launching, and approval

When the agent uses an MCP server rather than launching Chromium itself, the headless-browser ownership guide explains which component controls startup arguments and which results reach the agent.

Browser-use turns a natural-language task into browser actions. Its documentation and public repository describe an agent framework built around a Playwright-driven browser; they do not make the framework a browser vendor, a profile issuer, or an authorization system. Keep three owners visible in the code: browser-use owns task planning, the launcher owns the process and profile, and an operator owns approval for consequential steps. The direct Playwright profile guide covers the lower-level launch contract.

Make the ownership visible in the data passed between layers. The agent receives a task string and a page capability, the launcher receives executable_path and args, and the approval service receives a proposed action with its target and parameters. No layer should infer the other layer's authority. In particular, a browser-use success status is not an approval token, and an approved profile is not permission to use a customer's account.

The separation matters when a model says that a task is complete. A completed plan can mean that the agent reached a page or clicked a control; it cannot prove that the intended binary started, that the profile was loaded, or that a remote service accepted the session. Those are separate observations and need separate checks. Store the status as planned, verified, awaiting-approval, or finished so an operator can see which fact was actually established.

Use an owned staging route for the first run. A local fixture can expose a fixed build identifier, a consent state, and a harmless button, while a third-party page can change its markup or policy between runs. Keep the agent's task small until the process and fixture checks agree.

The fixture should make the safe boundary observable. Include a build marker, a consent marker, and a read-only action whose response is deterministic. Avoid a real login form in this stage: a login prompt is an approval event, not a readiness signal. Version the fixture beside the agent code, and put its version in the receipt. A changed fixture otherwise looks like a browser regression even when the executable and profile stayed constant.

Configure an explicit executable and profile

Browser-use's Python configuration ultimately reaches a Playwright browser launch. The exact constructor names can change with a browser-use release, so pin the package and consult its current configuration reference. The invariant is the launch contract: set executable_path to the approved BotBrowser binary and pass the profile as a browser argument, rather than relying on a bundled browser or a page script.

import asyncio
from browser_use import Agent, Browser, BrowserConfig

async def main():
    browser = Browser(
        config=BrowserConfig(
            headless=True,
            executable_path="/opt/botbrowser/chrome",
            args=["--bot-profile=/srv/profiles/approved.enc"],
        )
    )
    agent = Agent(
        task="Open the owned staging fixture and report its build identifier. Do not sign in or submit anything.",
        browser=browser,
    )
    await agent.run()

asyncio.run(main())

This example illustrates the boundary, not a universal browser-use API promise. Verify the option names against the version you pin. The profile flag is a BotBrowser command-line input, so it belongs in the browser's argument list. Keep the path absolute and load the profile before the first page opens. The BotBrowser CLI flags reference lists the supported flag spelling and tier constraints.

Do not install a full framework package that silently downloads another Chromium and then assume the profile is active. If the framework provides a bundled-browser default, disable it or use the compatible core launcher. Keep the executable path, profile identifier, framework version, browser version, and run identifier in one redacted record. Never put profile contents, cookies, tokens, or proxy credentials in that record.

Keep task text away from launch policy

The task prompt should describe the owned page and the harmless observation. It should not contain a new executable path, a secret, or an instruction to weaken a policy. Configuration belongs in reviewed deployment code. A model that can rewrite its own launch arguments can also erase the very boundary the operator meant to review.

Use a narrow task contract such as read build marker and return JSON. Do not pass a broad instruction such as complete the checkout to the first run. A narrow contract gives the reviewer one expected output and one stop condition. Once the fixture run is stable, add one reversible interaction at a time and retain the previous receipt as the comparison baseline.

Verify the process and page-visible fixture

Verification has two independent readings. First, inspect the process that Playwright spawned and compare its executable path and arguments with the declared values. Second, ask an owned fixture page for stable, non-sensitive values. A page can report its browser-visible contract, but it cannot prove which process launched it; the process check cannot prove that an application rendered the expected state. Keep both.

async def verify(page, browser, expected_executable, expected_profile):
    process = browser.playwright_browser.process
    observed_executable = process.args[0] if process and process.args else None
    observed_args = process.args if process else []
    fixture = await page.evaluate("""() => ({
      build: document.querySelector('[data-build]')?.dataset.build ?? null,
      consent: document.querySelector('[data-consent]')?.dataset.consent ?? null,
      userAgent: navigator.userAgent
    })""")
    return {
        "executableMatches": observed_executable == expected_executable,
        "profileArgumentPresent": any(expected_profile in arg for arg in observed_args),
        "fixture": fixture,
    }

The expected fixture result is a known build string such as staging-2026-11-06, a consent value of not-requested, and a non-empty user-agent string. The user-agent is an observation, not a detector verdict. If either executable or profile comparison fails, stop before delegating a real task and classify the issue as launch configuration. The profile management article explains why a profile identifier and its contents should be tracked separately.

Record a small JSON receipt:

{
  "runId": "browser-use-check-20261106-01",
  "declared": {
    "executable": "/opt/botbrowser/chrome",
    "profile": "approved.enc",
    "fixture": "staging-2026-11-06"
  },
  "observed": {
    "executableMatches": true,
    "profileArgumentPresent": true,
    "fixtureBuild": "staging-2026-11-06",
    "consent": "not-requested"
  },
  "firstFailure": null
}

The receipt is evidence for this launch and fixture only. It does not establish that a different origin will show the same values, that the profile is suitable for a customer account, or that a site's risk system will return any particular result.

Compare a baseline before widening scope

Run the same fixture twice with the same executable, profile identifier, framework lock, and fixture build. A baseline pair catches accidental changes in the launch wrapper before an agent is allowed to navigate elsewhere. Compare the process argument list, the fixture fields, and the close result. Do not compare volatile timestamps or page text that the fixture does not promise.

When a baseline differs, preserve the first failing receipt and stop. If the process path changed, inspect the deployment image and package lock. If the profile argument disappeared, inspect the configuration adapter. If only the fixture changed, deploy the matching fixture build. This order prevents a page-level workaround from hiding a launcher defect.

Keep credentials outside the agent loop

Credentials, payment details, recovery codes, and private profile files should enter through a reviewed secret or consent flow. They should not appear in the task prompt, the agent trace, the screenshot folder, or the JSON receipt. An operator can approve a form after checking its visible target and values; the agent does not need to read or repeat the secret to perform the navigation.

For a customer-facing workflow, define the approval record before writing the agent task. Include the destination origin, the action type, the visible amount or record identifier, and an expiry. Exclude page text that is not needed for the decision. The approval service can then reject an origin or amount change even if the model proposes it after a navigation.

The same approval record can drive a dry-run mode. In dry-run, browser-use may navigate through the owned workflow and collect the fields an operator would review, but the final control remains disabled. A dry-run receipt should say mode: "preview" and include the exact target origin. Promote to an active mode only after the operator has compared the receipt with the intended workflow. This turns a language-model suggestion into a reviewable change rather than an implicit command.

Keep the browser lifecycle inside one async scope. Create the browser, run the fixture, close the context, and close the process in a finally block. A stale process can hold an old profile and make the next run appear to succeed with different inputs. Record contextClosed and browserClosed as booleans, but do not treat cleanup as proof that a remote service discarded server-side state.

The agent trace should contain decisions, not private page dumps. Keep the task identifier, tool name, target origin, approval state, and first failure. Redact form values, cookies, local storage, screenshots containing account data, and the full profile path when it reveals a customer identifier. A short trace is easier to compare with the process receipt and less likely to become a second copy of the account.

A reviewable run has one owner for each failure. Launcher owners fix an executable or argument mismatch. Fixture owners fix a missing build or consent marker. Application owners fix a staging route that changed its contract. Operators decide whether a login or write is allowed. Browser-use should report the first owner-facing error and stop rather than hide it behind a retry loop.

This ownership model also keeps support conversations precise. Attach the redacted receipt, the pinned package versions, and the first failing layer. Do not attach a complete agent trace when a process argument already identifies the problem. A small handoff lets a reviewer reproduce the check without receiving customer material or silently changing the task scope.

The reviewer can compare two receipts line by line: the declared executable, the profile argument, the fixture build, the consent marker, and the first failure. Those fields are enough to decide whether another run is useful. If the target origin, profile identity, or proposed action changes, issue a new run identifier instead of overwriting the earlier record.

For a long-running agent, repeat the read-only fixture at a checkpoint before the first consequential action. A browser process can remain alive while a deployment, profile file, or policy changes around it. The checkpoint catches that drift and gives the operator a fresh observation to approve.

Use a decision table for operator handoff

An agent can continue only when the declared and observed setup agrees and the next action is reversible. A human should own the transition whenever an action requires a credential, consent, payment, deletion, permission grant, or an uncertain remote mutation.

ObservationAgent may continueOperator action
Executable and profile match; owned fixture is read-onlyRead the next staging pageReview the task scope
Executable differs or profile argument is absentNoFix launch configuration and rerun the fixture
Fixture asks for login or permissionNoSupply credentials or consent through the approved flow
Agent is about to purchase, delete, publish, or sendNoInspect the final parameters and approve once
Remote action timed out after a possible submissionNo blind retryQuery an idempotent status endpoint or hand off to the owner

This table is an operating boundary, not a promise about model behavior. Enforce it in the surrounding application with an explicit pause or approval callback. Do not rely on a sentence in the task prompt to protect a real account.

Failure fixture and bounded recovery

Test the stop path with a fixture that intentionally omits the build marker. The agent should report a missing marker and stop; it should not keep clicking until a different page happens to render one.

async def read_build(page):
    value = await page.locator("[data-build]").get_attribute("data-build")
    if value is None:
        raise RuntimeError("owned fixture missing data-build; stop delegation")
    return value

Keep recovery ordered. A missing process argument is a launcher problem. A missing fixture marker is a fixture or deployment problem. A login prompt is an approval boundary. A timeout after a write is an uncertain remote outcome. Restarting the agent for all four cases hides ownership and can duplicate a write.

When the binary is correct but the page differs, compare the fixture build and application deployment before changing profile values. When the profile argument is correct but page-visible values differ, capture the redacted receipt and inspect the selected profile's schema and browser version. Do not add page-level patches to make one value look consistent; that changes the experiment and can create a new mismatch elsewhere.

FAQ

Does browser-use guarantee a site's detector result?

No. It coordinates browser actions. A selected executable and profile can make a controlled launch reproducible, but neither browser-use nor BotBrowser guarantees a third-party detector or application verdict.

Can the agent choose a profile at runtime?

It should not choose from unrestricted files. Resolve an approved profile in deployment code, pass only its identifier or path to the launcher, and record the selection rule. Let an operator change that decision when the workflow requires a different account or region.

Should an agent submit a purchase after it finds the right item?

Not without an explicit operator checkpoint. The agent may prepare a reviewable cart or form on an owned environment, while a human confirms recipient, amount, consent, and final submission.

Is a page-visible user agent enough to verify the launch?

No. It confirms one browser-visible value. Pair it with process readback, the profile argument check, and a fixed fixture result so a bundled or misconfigured browser cannot pass by accident.

Practical conclusion

Set browser-use up as a three-part contract: reviewed launch configuration, an owned verification fixture, and an operator approval boundary. Start the explicit executable with the approved profile, compare process arguments and fixture values, and stop on any mismatch or consequential action. That sequence makes the agent run auditable without claiming a detector evasion, a pass rate, or a remote site's decision. Record the executable path, profile identifier, fixture build, consent state, and first failure in every receipt; omit cookies, tokens, and page contents.

Sources

#Browser-Use#AI Agents#Browser Automation#Profiles#Operator Approval

This article is part of the guide: Browser Automation Getting Started: A First Run Map

Run the same check in BotBrowser

Load a profile, keep the signals you just read about consistent inside the browser, and confirm the result on your own machine before a rollout.