| name | kernel-agent-browser |
| description | Best practices for using agent-browser with Kernel cloud browsers. Use when automating websites with agent-browser -p kernel, tuning stealth or proxy behavior, persisting profiles, handling iframes, discovering Kernel session IDs or live views, or cleaning up cloud sessions. |
Agent-Browser with Kernel Cloud Browsers
This skill documents best practices for using agent-browser's built-in Kernel provider (-p kernel) for cloud browser automation.
When to Use This Skill
Use this skill when you need to:
- Automate websites using
agent-browser -p kernel commands
- Handle bot detection on sites with aggressive anti-bot measures
- Persist login sessions across automation runs using profiles
- Work with iframes including cross-origin payment forms
- Get live view URLs for debugging or manual intervention
- Find the underlying Kernel session ID for advanced Playwright scripting
- Create site-specific automation skills for new websites
References
Prerequisites
Load the kernel-cli skill for Kernel CLI installation and authentication.
Environment Variables
Set these before your first agent-browser -p kernel call. The CLI holds state between invocations.
| Variable | Description | Default |
|---|
KERNEL_API_KEY | Required. Your Kernel API key for authentication | (none) |
KERNEL_HEADLESS | Run browser in headless mode (true/false) | true |
KERNEL_STEALTH | Launch a stealth browser (true/false) | false |
KERNEL_TIMEOUT_SECONDS | Session timeout in seconds | 300 |
KERNEL_PROFILE_NAME | Currently unusable with -p kernel in agent-browser 0.33.0; use the CDP workaround below | (none) |
Recommended Configuration
Set options explicitly; agent-browser reads them when it creates the provider session.
export KERNEL_API_KEY="your-api-key"
export KERNEL_TIMEOUT_SECONDS=600
export KERNEL_HEADLESS=false
export KERNEL_STEALTH=true
Profile Persistence
Warning: KERNEL_PROFILE_NAME doesn't work with -p kernel in agent-browser 0.33.0. It sends profile as a string instead of the object required by Kernel, so session creation fails with HTTP 400. It also doesn't set save_changes. Profiles must be pre-created.
Until this is fixed upstream, create the browser with the Kernel CLI and attach agent-browser over CDP. Don't combine -p kernel with --cdp.
PROFILE_NAME=mysite
kernel profiles get "$PROFILE_NAME" >/dev/null
BROWSER=$(kernel browsers create --profile-name "$PROFILE_NAME" --save-changes --timeout 600 -o json)
SESSION_ID=$(jq -er '.session_id' <<<"$BROWSER")
CDP_URL=$(jq -er '.cdp_ws_url' <<<"$BROWSER")
trap 'kernel browsers delete "$SESSION_ID" >/dev/null 2>&1 || true' EXIT
agent-browser --session mysite --cdp "$CDP_URL" open https://example.com
agent-browser --session mysite snapshot -i
agent-browser --session mysite close
kernel browsers delete "$SESSION_ID"
trap - EXIT
Don't print or share CDP_URL; it grants browser access. Deleting the CLI-created session finalizes --save-changes, so later sessions can reuse the authenticated profile.
Basic Usage
agent-browser -p kernel open <url>
agent-browser -p kernel snapshot -i
agent-browser -p kernel click @e1
agent-browser -p kernel fill @e2 "text"
agent-browser -p kernel close
For provider-managed sessions, use -p kernel with each command. For the profile/CDP workaround, reuse the same --session name and don't add -p kernel.
Semantic Selectors (Recommended)
Instead of ephemeral @e refs that change on every page load, use semantic selectors via the find command for more stable, readable automation:
agent-browser -p kernel find role button click --name "Log In"
agent-browser -p kernel find role textbox fill "user@email.com" --name "Email"
agent-browser -p kernel find text "View Menus" click
agent-browser -p kernel find text "Submit Order" click
agent-browser -p kernel find label "Username" fill "myuser"
agent-browser -p kernel find label "Password" fill "secret123"
agent-browser -p kernel find placeholder "Search..." type "query"
agent-browser -p kernel find testid "submit-btn" click
agent-browser -p kernel find first "li.item" click
agent-browser -p kernel find nth 2 ".card" hover
When to Use Which Selector
| Selector Type | Best For | Stability |
|---|
find role --name | Buttons, links, navigation | ⭐⭐⭐ Most stable |
find label | Form inputs with labels | ⭐⭐⭐ Most stable |
find text | Clickable text elements | ⭐⭐ Stable |
find testid | Sites with test attributes | ⭐⭐⭐ Most stable |
find placeholder | Search boxes, inputs | ⭐⭐ Stable |
@e refs | Unknown sites, quick iteration | ⭐ Ephemeral |
Recommendation: Use find for production automation. Use @e refs for exploration and quick prototyping, then convert to semantic selectors.
Find the Kernel Session and Live View
Match agent-browser's CDP endpoint to the active Kernel session. Compare the URL without its query string: the CLI and agent-browser can hold different short-lived jwt query values for the same session. The endpoint's scheme, host, and path remain stable. This is more reliable than guessing from creation time when several sessions share a profile. This workflow requires jq.
CDP_URL="$(agent-browser -p kernel get cdp-url)"
CDP_ENDPOINT="${CDP_URL%%\?*}"
SESSION_ID="$(
kernel browsers list --status active --limit 100 -o json |
jq -r --arg endpoint "$CDP_ENDPOINT" \
'.[] | select((.cdp_ws_url | split("?")[0]) == $endpoint) | .session_id' |
head -n 1
)"
test -n "$SESSION_ID"
kernel browsers view "$SESSION_ID"
Do not print or share the CDP URL; it grants browser access. Share a live view URL only with the intended user. A headless session has no live view. If you use --session <name>, include it on every agent-browser command, including get cdp-url.
Handling Bot Detection
Stealth and Proxy Routing
Stealth is opt-in in current agent-browser releases. Set KERNEL_STEALTH=true before the first command for a session; changing it later does not reconfigure the running browser.
A stealth browser can use Kernel's default stealth proxy. If that proxy causes a site-specific network or reputation failure and direct metro egress is acceptable, change the running session without disabling stealth:
kernel browsers update "$SESSION_ID" --disable-default-proxy
kernel browsers update "$SESSION_ID" --disable-default-proxy=false
Direct egress changes the public IP and can reduce anti-bot protection. Prefer the default proxy unless testing shows it is the problem. For a configured Kernel proxy, use --proxy-id <proxy-id>; remove it with --clear-proxy.
Manual Login Fallback
If automated login fails:
- Resolve
SESSION_ID using the CDP-matching workflow above.
- Run
kernel browsers view "$SESSION_ID" and give the URL only to the intended user.
- Ask the user to complete login, then continue in the same agent-browser session.
- To persist the login, use the CLI-created profile/CDP workflow above. Close agent-browser, then delete the Kernel session so
--save-changes finalizes.
JavaScript Fallback for Tricky Elements
Some elements (especially on bot-protected sites) don't respond to standard commands:
agent-browser -p kernel eval "document.querySelector('.submit-btn').click()"
agent-browser -p kernel eval "
const el = document.querySelector('#email');
el.value = 'user@example.com';
el.dispatchEvent(new Event('input', {bubbles: true}));
el.dispatchEvent(new Event('change', {bubbles: true}));
"
agent-browser -p kernel eval "document.querySelector('[data-testid=\"submit\"]').click()"
Anti-Bot Form Fields
Some payment processors (e.g., Point and Pay) use decoy form fields. Only fill fields matching specific patterns:
agent-browser -p kernel eval "
const realInputs = Array.from(document.querySelectorAll('input'))
.filter(el => el.name && el.name.startsWith('xeiinput'));
// Fill only these inputs
"
Handling Iframes
Same-Origin Iframes
Use the frame command to switch context:
agent-browser -p kernel frame "#iframe-id"
agent-browser -p kernel snapshot -i
agent-browser -p kernel click @e1
agent-browser -p kernel frame main
Cross-Origin Iframes
Try agent-browser frame first; current releases can switch into iframe context, including many cross-origin frames. If an out-of-process or payment iframe still fails, resolve SESSION_ID and use Kernel's Playwright executor:
kernel browsers playwright execute "$SESSION_ID" '
const frame = page.frameLocator("#payment-iframe");
await frame.locator("#card-number").fill("4111111111111111");
await frame.locator("#submit").click();
'
Return to the main document with agent-browser -p kernel frame main after frame interactions.
Waiting Strategies
Smart waits are critical for fast, reliable automation. Using condition-based waits instead of fixed timeouts can reduce execution time by 50%+ while improving reliability.
Smart Waits (Recommended)
agent-browser -p kernel wait --load domcontentloaded
agent-browser -p kernel wait --load networkidle
agent-browser -p kernel wait --url "**/dashboard"
agent-browser -p kernel wait --url "**/order-confirmation"
agent-browser -p kernel wait --text "Password"
agent-browser -p kernel wait --text "Order confirmed"
agent-browser -p kernel wait --fn "window.appReady === true"
agent-browser -p kernel wait --fn "document.querySelector('.spinner') === null"
agent-browser -p kernel wait "#login-form"
agent-browser -p kernel wait ".results-loaded"
Fixed Waits (Last Resort)
agent-browser -p kernel wait 2000
Element Refs Best Practices
Element refs (@e1, @e2, etc.) are ephemeral and change:
- After page navigation
- After significant DOM updates
- Between browser sessions
Always take a fresh snapshot before interacting:
agent-browser -p kernel snapshot -i
agent-browser -p kernel click @e5
Filtering Snapshots
agent-browser -p kernel snapshot -i | grep -i "button\|submit"
agent-browser -p kernel snapshot -s "#main-content" -i
Login Patterns
Single-Page Form (Optimized)
Username and password on the same page:
agent-browser -p kernel open https://example.com/login
agent-browser -p kernel wait --load domcontentloaded
agent-browser -p kernel find label "Email" fill "user@example.com"
agent-browser -p kernel find label "Password" fill "secret123"
agent-browser -p kernel find role button click --name "Sign In"
agent-browser -p kernel wait --url "**/dashboard"
Two-Step Form (Optimized)
Username first, then password on a second screen:
agent-browser -p kernel open https://example.com/login
agent-browser -p kernel wait --load domcontentloaded
agent-browser -p kernel find label "Username" fill "myuser"
agent-browser -p kernel press Enter
agent-browser -p kernel wait --text "Password"
agent-browser -p kernel find label "Password" fill "secret123"
agent-browser -p kernel press Enter
agent-browser -p kernel wait --url "**/home"
Modal Login
Login form appears in a modal overlay:
agent-browser -p kernel find text "Log In" click
agent-browser -p kernel wait --text "Password"
agent-browser -p kernel find label "Email" fill "user@example.com"
agent-browser -p kernel find label "Password" fill "password123"
agent-browser -p kernel find role button click --name "Sign In"
agent-browser -p kernel wait --url "**/dashboard"
Fallback: JavaScript for Tricky Modals
Some modals don't expose accessible labels:
agent-browser -p kernel eval "document.querySelector('.login-link').click()"
agent-browser -p kernel wait 1000
agent-browser -p kernel eval "
document.getElementById('username').value = 'user@example.com';
document.getElementById('username').dispatchEvent(new Event('input', {bubbles: true}));
document.getElementById('password').value = 'password123';
document.getElementById('password').dispatchEvent(new Event('input', {bubbles: true}));
document.querySelector('button[type=submit]').click();
"
agent-browser -p kernel wait --url "**/dashboard"
Handling New Tabs
Some links open in new tabs:
agent-browser -p kernel click @e38
agent-browser -p kernel tab 1
agent-browser -p kernel wait 2000
agent-browser -p kernel snapshot -i
Screenshots and Debugging
agent-browser -p kernel screenshot ~/Downloads/page.png
agent-browser -p kernel screenshot ~/Downloads/full.png --full
agent-browser -p kernel console
agent-browser -p kernel errors
agent-browser -p kernel get url
Session Management
Cleanup
Close the same named agent-browser session you opened. This saves profile changes and deletes its Kernel browser:
agent-browser -p kernel close
If agent-browser is unavailable or close fails, delete the orphan explicitly:
kernel browsers delete "$SESSION_ID"
Do not use close --all when unrelated agent-browser sessions may be running.
Multiple Sessions
Run parallel browser sessions with named sessions:
agent-browser -p kernel --session site1 open https://site1.com
agent-browser -p kernel --session site2 open https://site2.com
agent-browser -p kernel session list
Common Gotchas
- Refs change after navigation: Re-snapshot after links, submissions, or major DOM updates.
- Wait for outcomes: Use URL, text, load-state, or JavaScript conditions after asynchronous actions.
- Provider settings are launch-time settings: Close the current session before changing
KERNEL_HEADLESS, KERNEL_STEALTH, or timeout.
- Profile persistence needs the CDP workaround:
KERNEL_PROFILE_NAME is currently broken. Close agent-browser, then delete the CLI-created Kernel session to finalize --save-changes.
- Stealth is not sufficient for every site: Compare proxy routing, use manual login, or fall back to direct Playwright for difficult frames.
Quick Reference
export KERNEL_TIMEOUT_SECONDS=600
agent-browser -p kernel open https://example.com
agent-browser -p kernel wait --load domcontentloaded
agent-browser -p kernel find label "Email" fill "user@example.com"
agent-browser -p kernel find label "Password" fill "secret"
agent-browser -p kernel find role button click --name "Submit"
agent-browser -p kernel wait --url "**/success"
agent-browser -p kernel snapshot -i
agent-browser -p kernel fill @eN "text"
agent-browser -p kernel click @eM
CDP_URL="$(agent-browser -p kernel get cdp-url)"
CDP_ENDPOINT="${CDP_URL%%\?*}"
SESSION_ID="$(kernel browsers list --status active --limit 100 -o json |
jq -r --arg endpoint "$CDP_ENDPOINT" \
'.[] | select((.cdp_ws_url | split("?")[0]) == $endpoint) | .session_id' |
head -n 1)"
test -n "$SESSION_ID"
kernel browsers view "$SESSION_ID"
agent-browser -p kernel close
Selector Cheat Sheet
agent-browser -p kernel find role button click --name "Submit"
agent-browser -p kernel find role link click --name "Next"
agent-browser -p kernel find text "Click here" click
agent-browser -p kernel find label "Email" fill "user@example.com"
agent-browser -p kernel find placeholder "Search" type "query"
agent-browser -p kernel find testid "username-input" fill "myuser"
agent-browser -p kernel wait --load domcontentloaded
agent-browser -p kernel wait --text "Success"
agent-browser -p kernel wait --url "**/dashboard"
agent-browser -p kernel wait --fn "window.loaded === true"