Deterministic rerun lets you run a browser task once with a full agent, then re-execute the same task instantly using a cached script — no LLM, up to 99% cheaper.
Quick start
Use {{double brackets}} around values that can change between runs. The first call runs the full agent. Every subsequent call with the same template uses the cached script.
from browser_use_sdk.v3 import AsyncBrowserUse
client = AsyncBrowserUse()
workspace = await client.workspaces.create(name="my-scraper")
# First call — agent explores, creates script (~$0.10, ~60s)
result = await client.run(
"Get the top {{5}} stories from https://news.ycombinator.com as JSON",
workspace_id=str(workspace.id),
)
# Second call — cached script, different param ($0 LLM, ~5s)
result2 = await client.run(
"Get the top {{10}} stories from https://news.ycombinator.com as JSON",
workspace_id=str(workspace.id),
)
How it works
You send a task with {{brackets}}
The brackets mark which parts are parameters:"Get prices from {{example.com}} for {{electronics}}"
{{example.com}} → parameter 1
{{electronics}} → parameter 2
The system strips the values to create a template: "Get prices from {{}} for {{}}". System hashes the template
Template "Get prices from {{}} for {{}}" is hashed to a unique ID like a7f3b2c1.
The system checks the workspace for scripts/a7f3b2c1.py.
Cache miss → agent creates script
If no script exists, the full agent runs your task. After completing it, the agent saves a standalone Python script that reproduces the result deterministically — no AI needed.
Cache hit → script executes directly
If the script exists, it runs directly with the new parameter values. No agent, no LLM. Just the script in a sandbox with browser and proxy.
Auto-detection
Caching activates automatically when both conditions are met:
- The task contains
{{ and }}
- A
workspace_id is provided
No extra flags needed. You can override with cache_script:
| Value | Behavior |
|---|
None (default) | Auto-detect from {{brackets}} + workspace |
True | Force-enable, even without brackets |
False | Force-disable, even if brackets are present |
Examples
Parameterized scraping
Run once, then loop over different keywords at $0 LLM each:
# Agent figures out how to scrape intro.co on first call
result = await client.run(
"Go to {{https://intro.co/marketplace}} and get all {{logistics}} experts as JSON",
workspace_id=str(workspace.id),
)
# Instant reruns with different keywords
for keyword in ["CEO", "marketing", "finance", "e-commerce"]:
result = await client.run(
f"Go to {{{{https://intro.co/marketplace}}}} and get all {{{{{keyword}}}}} experts as JSON",
workspace_id=str(workspace.id),
)
print(f"{keyword}: {len(result.output)} experts, LLM cost: ${result.llm_cost_usd}")
No parameters — cache the exact task
Append empty brackets {{}} to signal “cache this exact task”:
result = await client.run(
"Get the current Bitcoin price from coinmarketcap.com {{}}",
workspace_id=str(workspace.id),
)
# Same task again — cached
result2 = await client.run(
"Get the current Bitcoin price from coinmarketcap.com {{}}",
workspace_id=str(workspace.id),
)
Multiple parameters
result = await client.run(
"Go to https://help.netflix.com/en/node/24926/ax and get subscription prices for {{Germany,France,Japan}}",
workspace_id=str(workspace.id),
)
# Different countries — cached
result2 = await client.run(
"Go to https://help.netflix.com/en/node/24926/ax and get subscription prices for {{US,UK,Brazil}}",
workspace_id=str(workspace.id),
)
Force enable / disable
# Force-enable without brackets
result = await client.run(
"Get the top stories from Hacker News",
workspace_id=str(workspace.id),
cache_script=True,
)
# Force-disable even with brackets
result = await client.run(
"Explain what {{templates}} means in Jinja",
workspace_id=str(workspace.id),
cache_script=False,
)
Inspecting cached scripts
You can download and inspect the scripts the agent created:
files = await client.workspaces.files(workspace.id, prefix="scripts/")
for f in files.files:
print(f"{f.path} ({f.size} bytes)")
# Download a script to inspect it
await client.workspaces.download(workspace.id, "scripts/a7f3b2c1.py", to="./my_script.py")
Cost comparison
| LLM cost | Browser + proxy | Time |
|---|
| First call (agent) | ~$0.05–1.00 | Yes | ~30–120s |
| Cached calls | $0 | Yes | ~3–10s |
The browser and proxy still run for cached calls (the script may need them), so there is a small infrastructure cost per execution. LLM cost drops to zero.