curl -X POST https://win.oneshotagent.com/v1/tools/browser/profiles \
-H "Content-Type: application/json" \
-H "X-Agent-Proof: $AGENT_READ_PROOF" \
-H "X-Agent-ID: 0xYourWalletAddress" \
-d '{"name": "my-github-bot"}'
const profile = await agent.createBrowserProfile("my-github-bot");
console.log(profile.id); // "prof_abc123..."
profile = client.create_browser_profile("my-github-bot")
print(profile["id"])
{
"id": "prof_abc123",
"name": "my-github-bot"
}
Web & Browser
Browser Profiles
Create, list, and delete persistent browser profiles that retain cookies and session state across tasks
POST
/
v1
/
tools
/
browser
/
profiles
curl -X POST https://win.oneshotagent.com/v1/tools/browser/profiles \
-H "Content-Type: application/json" \
-H "X-Agent-Proof: $AGENT_READ_PROOF" \
-H "X-Agent-ID: 0xYourWalletAddress" \
-d '{"name": "my-github-bot"}'
const profile = await agent.createBrowserProfile("my-github-bot");
console.log(profile.id); // "prof_abc123..."
profile = client.create_browser_profile("my-github-bot")
print(profile["id"])
{
"id": "prof_abc123",
"name": "my-github-bot"
}
This page covers these tools: Create Profile, List Profiles, and Delete Profile.
An import sets up the profile without an agent task and checks it in a fresh browser before returning, which can take up to 150 seconds. Cookie values never enter task prompts or receipts. An imported cookie can still expire or be rejected by the target site.
For an exported storage state, use
Python has
Overview
A browser profile keeps cookies, local storage, and session state between browser tasks. Create one, then pass itsprofile_id to any task to reuse the logged-in state.
Authentication
Profile endpoints requireX-Agent-ID and a signed agent read proof; the SDK supplies both. In the cURL examples, AGENT_READ_PROOF is a proof signed by your wallet. Profiles are scoped to your agent. Creating one is free.
Create Profile
string
required
Profile name (1-100 characters).
object[]
Cookies with Playwright attributes:
name, value, either url or domain and path, and optionally expires (Unix seconds), httpOnly, secure, sameSite, partitionKey.object
Playwright-style
{ cookies, origins: [{ origin, localStorage: [{ name, value }] }] }. Use this or cookies, not both. IndexedDB and sessionStorage imports are rejected.curl -X POST https://win.oneshotagent.com/v1/tools/browser/profiles \
-H "Content-Type: application/json" \
-H "X-Agent-Proof: $AGENT_READ_PROOF" \
-H "X-Agent-ID: 0xYourWalletAddress" \
-d '{"name": "my-github-bot"}'
const profile = await agent.createBrowserProfile("my-github-bot");
console.log(profile.id); // "prof_abc123..."
profile = client.create_browser_profile("my-github-bot")
print(profile["id"])
{
"id": "prof_abc123",
"name": "my-github-bot"
}
List Profiles
Returns your agent’s profiles.curl https://win.oneshotagent.com/v1/tools/browser/profiles \
-H "X-Agent-Proof: $AGENT_READ_PROOF" \
-H "X-Agent-ID: 0xYourWalletAddress"
const profiles = await agent.listBrowserProfiles();
profiles = client.list_browser_profiles()
[
{ "id": "prof_abc123", "name": "my-github-bot" },
{ "id": "prof_def456", "name": "linkedin-scraper" }
]
Delete Profile
curl -X DELETE https://win.oneshotagent.com/v1/tools/browser/profiles/prof_abc123 \
-H "X-Agent-Proof: $AGENT_READ_PROOF" \
-H "X-Agent-ID: 0xYourWalletAddress"
await agent.deleteBrowserProfile("prof_abc123");
client.delete_browser_profile("prof_abc123")
Using Profiles with Tasks
Passprofile_id to a browser task to reuse the profile’s session state:
const profile = await agent.createBrowserProfile("linkedin-session", {
cookies: [{
name: "li_at",
value: process.env.LINKEDIN_LI_AT!,
domain: ".linkedin.com",
path: "/",
secure: true,
httpOnly: true,
sameSite: "None",
}],
});
const result = await agent.browser({
task: "Open the feed and report whether a signed-in member feed is visible.",
start_url: "https://www.linkedin.com/feed/",
profile_id: profile.id,
max_steps: 30,
});
agent.createBrowserProfile(name, { storage_state: state }), or client.create_browser_profile(name, storage_state=state) in Python. Run one task at a time per profile. When a login expires, import again into a new profile.
The deprecated secrets task field is rejected before payment and can’t substitute values inside JavaScript.
Interactive login and 2FA
Start a setup session when a site asks for a password, authenticator code, SMS code, or device approval. The user completes the login in a live browser, and the profile keeps the session. Requires TypeScript SDK 0.34.0+ or Python SDK 0.24.0+. This account-connection flow works for any supported login site. Wait for statusidle, then open live_url in a private view for the user, who completes the site’s login. Passwords, codes, and authenticator seeds are not API arguments and never enter agent prompts or receipts. Treat the live URL as a credential: don’t log it or show it to other users.
The private live_url points to live.browser-use.com, a vendor-hosted browser your application opens for its user. A OneShot-hosted setup page is tracked separately and is not in this release.
const profile = await agent.createBrowserProfile("linkedin");
let setup = await agent.startBrowserProfileSetup(profile.id, "https://www.linkedin.com/login/");
while (setup.status === "created" || setup.status === "running") {
await new Promise(resolve => setTimeout(resolve, 2000));
setup = await agent.getBrowserProfileSetup(profile.id);
}
if (setup.status !== "idle") throw new Error("Account setup did not become ready");
// Open setup.live_url privately; the user logs in and completes 2FA there.
// After the user confirms completion:
const saved = await agent.finishBrowserProfileSetup(profile.id);
// saved.stored_cookies contains names/domains/paths only, from a fresh browser
// inspected before website navigation. It does not assert LinkedIn accepted them.
start_browser_profile_setup(profile_id, start_url), get_browser_profile_setup(profile_id), and finish_browser_profile_setup(profile_id), plus async variants prefixed with a.
Over HTTP (authenticated): POST /v1/tools/browser/profiles/{id}/setup/start with { "start_url": "https://example.com/login" }, and /setup/status or /setup/finish with {}. Only the profile owner can run setup. Start reuses an existing setup, so check the returned status. Don’t run other tasks on the profile during setup.
Finish stops the session, waits for shutdown, then inspects the saved cookie jar in a fresh browser before any navigation. If verification fails, the profile is kept; retry finish. Cookies being present and the site accepting them are separate checks. Persistence uses the provider’s profile storage, not a client-side cookie export.
Setup expires after 15 minutes. Status and finish calls close expired sessions, and the lifecycle sweep closes abandoned ones on its next run. The profile survives expiry. Opening the login page runs a provider agent task with a $0.30 session allowance; the setup endpoints request no separate OneShot x402 payment. A saved profile skips a new 2FA challenge only while the site accepts its session.
This follows the vendor’s human checkpoint flow. It doesn’t store TOTP seeds or generate authenticator codes.