Skip to content
09 / Developer API

Browser API: functions and examples

Connect through Python, Node.js, Java, or Go. This reference covers profile configuration, browser sessions, page observation, input, files, and saved Skills, following the GitHub API examples.

Install and make your first call

pip install kingai-browser
python -m kingai_browser install

Sign in to your KingAI account and prepare the unique saved profile named 默认环境. The example starts that profile, reads a page, and releases control while keeping the browser window open. To select a different saved profile, pass its real profile_id to api.start().

from kingai_browser import KingAI

with KingAI() as api:
    browser = api.start()
    try:
        browser.goto("https://www.kingaibrowser.cn/")
        print(browser.read())
    finally:
        browser.detach()

Each recipe below is independent, not a script to run from top to bottom. Select the operation you need and substitute real profile, session, element, and Skill IDs. The snippets illustrate the documented API; they are not a claim that every operation has been tested on your target site.

  1. Calling conventions and four languages
  2. Profiles and configuration
  3. Starting, attaching, and ownership
  4. Tabs and navigation
  5. Reading, snapshots, and DOM queries
  6. Waiting, clicking, typing, and scrolling
  7. JavaScript evaluation and bounded previews
  8. Screenshots, PDF, and file transfer
  9. Cookies and Storage
  10. Saved Skill workflows
  11. The installed tool catalog
  12. Errors and execution results

01 · Calling conventions and four languages

Python, Node.js, Java, and Go share tool names and raw JSON fields. Session-level call methods inject session_id; raw field names are not converted to camelCase. Later recipes use Python, with api as a connected KingAI client and browser as a running session.

Calling conventions and four languages — function reference
Function / callPurpose
launch()Connect and start a profile, returning a BrowserSession; for ordinary Python scripts.
KingAIExplicit client ownership, profile CRUD, tool discovery, and session management.
BrowserAutomationAn Agent action and state facade over the same SDK, for Agent adapters.
agent_browser.execute(action, **arguments)Dispatch actions such as go_to_url, query, click_element, input_text, extract_content, or mcp_call. Element actions require an observed ref or exact selector.
agent_browser.get_current_state()Observe the live page, snapshot, and tabs; return a state dictionary including interactive_elements, not a cached lookup.
agent_browser.describe_error(error)Describe an error as structured information for the Agent adapter.
agent_browser.close()Disconnect the facade’s MCP connection and keep the window open, as does context exit; distinct from session close_browser().
browser.call(name, **arguments)Python session-level tool call.
await browser.call(name, arguments)Node.js: await every operation.
browser.call(name, Map.of(...))Java: returns a Jackson JsonNode.
browser.Call(ctx, name, kingai.Arguments{...})Go: pass a context and handle the returned error.

BrowserAutomation: Agent actions and state

These entry points are layers of one SDK using the same installed MCP/Runtime, not three browser engines. Import BrowserAutomation from kingai_browser. It dispatches actions and collects state; it is not an AI model or autonomous planner. Page-changing actions collect follow-up observations. Failed observation never automatically replays input, and the Agent must assess business success from the page.

import json
from kingai_browser import BrowserAutomation

with BrowserAutomation(profile_id="actual-saved-profile-id") as agent_browser:
    # Replace the ID with one from KingAI.profiles(); do not invent one.
    result = agent_browser.execute("go_to_url", url="https://example.com")
    state = agent_browser.get_current_state()
    print(state["url"], state["title"])

    snapshot = json.loads(state["interactive_elements"])
    for element in snapshot.get("elements", []):
        print(element.get("ref"), element.get("name"))

    # Query through the facade rather than guessing an element index.
    links = agent_browser.execute("query", arguments={"selector": "a", "limit": 10})
    print(links)

Real IDs, session reuse, and OpenManus

Replace the example profile ID with one returned by KingAI.profiles(); omit profile_id only to use the unique existing default. Resume through BrowserAutomation(session_id="actual-active-session-id") only when attaching is permitted, without also passing profile_id. Reuse query()/snapshot() on an existing BrowserSession instead of starting another facade. OpenManus browser_use is a tool name whose implementation delegates to BrowserAutomation.execute() and get_current_state(); it is not the SDK class itself.

Generic calls in four languages

Python

# Python: arbitrary installed tool; keyword arguments bind to the current session.
result = browser.call("browser_query", selector="#name", include_html=True)

Node.js

// Node.js: same tool and raw arguments; await every operation.
const result = await browser.call('browser_query', { selector: '#name', include_html: true });

Java

// Java: Session.call injects session_id, Jackson JsonNode is returned.
JsonNode result = browser.call("browser_query", Map.of("selector", "#name", "include_html", true));

Go

// Go: Session.Call injects session_id. Always propagate the returned error.
result, err := browser.Call(ctx, "browser_query", kingai.Arguments{"selector": "#name", "include_html": true})
if err != nil { return err }

02 · Profiles and configuration

Creating or updating a profile does not start a browser. Names must be unique. Close the profile before updating it; group_name must identify an existing group. A patch merges objects recursively and replaces arrays. Delete only a profile you explicitly intend to remove.

Profiles and configuration — function reference
Function / callPurpose
api.profiles()List saved profile summaries.
api.create_profile(name, language="en-US")Create a profile and return its profileId.
api.profile(profile_id)Read a saved profile.
api.update_profile(profile_id, name=..., patch=...)Update the name and configuration.
api.delete_profile(profile_id, confirm=True)Explicitly delete a closed profile.

Python

saved = api.profiles()                        # profiles_list: saved summaries
created = api.create_profile("Unique example", language="en-US")
profile_id = created["profileId"]             # ID returned by creation
summary = api.profile(profile_id)             # profiles_get
api.update_profile(profile_id, name="Configured example", patch={
    "locale": {"language": "en-US", "accept_languages": "en-US,en"}
})
updated = api.profile(profile_id)
# Optional, destructive: only after explicitly closing this environment.
# api.delete_profile(profile_id, confirm=True)

03 · Starting, attaching, and ownership

api.start() uses the unique saved profile named 默认环境. A missing default is an error, never a silent temporary-profile fallback. Temporary mode requires temporary=True. Attaching is subject to server ownership rules; inspect sessions after a disconnect. Python with launch() and Java automatic Session.close() detach owned connections and preserve windows. Explicit browser shutdown uses Python close_browser()/close(), Node.js closeBrowser()/close(), Java closeBrowser(), or Go CloseBrowser()/Close(). Methods named close do not have identical ownership semantics across languages.

Starting, attaching, and ownership — function reference
Function / callPurpose
api.start(profile_id=..., headless=False)Start a saved profile and return a browser session.
api.sessions()Inspect active sessions.
api.attach(session_id)Attach when ownership rules permit.
browser.detach()Release control and preserve the browser window.
browser.close() / browser.close_browser()Python: explicitly close the browser.
api.close()Close this client’s MCP connection.

Python

browser = api.start(profile_id=profile_id, headless=False)
session_id = browser.session_id
active = api.sessions()                       # inspect real active sessions
# Another client can request attach only if server ownership rules allow it:
# browser = api.attach(session_id)
browser.detach()                             # leave browser available
# browser.close()                            # explicitly close the browser
# api.close()                                # only close this client's MCP

04 · Tabs and navigation

Operations target the selected tab. Serialize tab switches and input; a session is not a concurrent multi-Page model. Use a real returned targetId and close only the intended tab. The local demo.html URL in the recipe requires your own running demo page.

Tabs and navigation — function reference
Function / callPurpose
browser.new_tab(url)Open a tab and read its returned targetId.
browser.tabs()List tabs.
browser.activate_tab(target_id)Activate a tab.
browser.goto(url)Navigate the selected tab.
browser.close_tab(target_id)Explicitly close a tab.

Python

opened = browser.new_tab("http://127.0.0.1:8765/demo.html")
target_id = opened["targetId"]
all_tabs = browser.tabs()
browser.activate_tab(target_id)
browser.goto("http://127.0.0.1:8765/demo.html")
# Explicitly close ONLY a tab you created and no longer need:
# browser.close_tab(target_id)

05 · Reading, snapshots, and DOM queries

For ordinary Python automation, call query() and snapshot() on your current session after opening a page. No browser_state object or Agent framework is required. Unfiltered query() enumerates bounded DOM summaries; snapshot(mode="interactive") focuses on interaction candidates, while the default compact snapshot can also include contextual text and structure.

Reading, snapshots, and DOM queries — function reference
Function / callPurpose
browser.read()Read page content.
browser.snapshot(mode="interactive", limit=30, max_chars=12000)Capture a bounded interactive snapshot.
browser.query(selector=..., include_html=True, limit=20)Query elements with bounded outerHTML.
browser.query(cursor=next_cursor)Continue the same captured observation.

Open a page and obtain DOM elements

The executable portion reads links on example.com without clicking or submitting. The commented #name input recipe requires a page that actually contains that field. Responses are JSON observations, not live DOM objects supporting element.click(), or a complete unbounded HTML document. Dispatch actions through SDK click/fill methods. Fields can include ref, tag, role, name, attributes, text, bounds, states, and frameId, depending on the installed server and observation mode. Exiting with launch() preserves the window.

from kingai_browser import launch

with launch() as browser:
    browser.new_tab("https://example.com")
    browser.wait(selector="body", state="visible", timeout_ms=15000)

    # Read a compact DOM/accessibility observation with actionable refs.
    snapshot = browser.snapshot(mode="interactive", limit=30)
    print(snapshot.get("text", ""))

    # Query actual DOM elements and request bounded outerHTML when needed.
    result = browser.query(selector="a", include_html=True, limit=20)
    for element in result.get("elements", []):
        print(element.get("ref"), element.get("tag"), element.get("name"))
        print(element.get("attributes", {}))

    # On a page containing your own form, query the exact intended input:
    # found = browser.query(selector="#name", limit=2)["elements"]
    # if len(found) != 1:
    #     raise RuntimeError("Expected exactly one input")
    # browser.fill(ref=found[0]["ref"], text="KingAI", humanize=False)

Where interactive_elements comes from

interactive_elements belongs to the optional BrowserAutomation facade. Python capture_state() assembles it during observation; it is not stored in the browser or profile database. The fragment below only explains assignment; real state also contains url, title, session_id, tabs, page_content, and help. The value is a JSON string of the entire bounded snapshot response, not an element list. The facade currently requests the default compact snapshot, so the historical field name does not imply interactive-only content.

snapshot = browser.snapshot(max_chars=20000)
state = {"interactive_elements": json.dumps(snapshot, ensure_ascii=False)}

Parse the string before reading elements

Parse with json.loads(), then read the elements array and inspect text and truncated. Do not iterate the interactive_elements string itself. If launch()/KingAI already opened the page, keep using that session instead of starting the default profile again. A new facade should explicitly attach an authorized active session_id. Refresh refs after navigation or DOM replacement. Continue pagination using only the returned cursor, without resending filters.

import json
from kingai_browser import BrowserAutomation

with BrowserAutomation() as agent_browser:
    agent_browser.execute("go_to_url", url="https://example.com")
    browser_state = agent_browser.get_current_state()
    snapshot = json.loads(browser_state["interactive_elements"])
    for element in snapshot.get("elements", []):
        print(element.get("ref"), element.get("tag"), element.get("name"))
    print(snapshot.get("text", ""))
    print("Snapshot truncated:", snapshot.get("truncated", False))

Snapshot budgets and query pagination

Python

page = browser.read()                         # readable page content
snapshot = browser.snapshot(mode="interactive", limit=30, max_chars=12000)
query = browser.query(selector="input, textarea, button", include_html=True, limit=20)
elements = query["elements"]                 # bounded DOM summaries, not live DOM objects
for element in elements:
    print(element.get("ref"), element.get("tag"), element.get("name"))
# Follow the SAME captured observation without resending filters:
if query.get("nextCursor"):
    next_page = browser.query(cursor=query["nextCursor"])

06 · Waiting, clicking, typing, and scrolling

Use either selector or ref, not both. Replace the form selectors with real elements from your target page. fill replaces content; type appends. Basic recipes explicitly set humanize=False; enabling humanization requires a valid entitlement. Dispatch is not business success: observe the result. Java and Go input convenience methods also accept options.

Waiting, clicking, typing, and scrolling — function reference
Function / callPurpose
browser.wait(selector=..., state="visible", timeout_ms=15000)Wait for a page condition.
browser.fill(ref=..., text=..., humanize=False)Replace input text.
browser.type(ref=..., text=..., humanize=False)Append text.
browser.click(selector, humanize=False)Click an element.
browser.key("Tab", humanize=False)Send a key.
browser.hover(selector, humanize=False)Hover over an element.
browser.scroll(300, humanize=False)Scroll the page.

Python

browser.wait(selector="#name", state="visible", timeout_ms=15000)
found = browser.query(selector="#name", limit=2)
if len(found["elements"]) != 1:
    raise RuntimeError("Expected exactly one name input")
name_ref = found["elements"][0]["ref"]
browser.fill(ref=name_ref, text="KingAI", humanize=False)     # replace existing text
browser.type(ref=name_ref, text=" SDK", humanize=False)      # append text
browser.key("Tab", humanize=False)
browser.hover("#submit", humanize=False)
browser.scroll(300, humanize=False)
browser.click("#submit", humanize=False)
browser.wait(selector='#result[data-submitted="true"]', timeout_ms=10000)
result_text = browser.evaluate("document.querySelector('#result').textContent")

07 · JavaScript evaluation and bounded previews

evaluate retains raw evaluation semantics. evaluate_preview returns a bounded preview; truncated means partial output. A large evaluate result can return RESULT_TOO_LARGE after execution has already happened. Never rerun a side-effect expression just to retrieve output. Node.js/Java use evaluatePreview; Go uses EvaluatePreview.

JavaScript evaluation and bounded previews — function reference
Function / callPurpose
browser.evaluate(expression)Evaluate a JavaScript expression.
browser.evaluate_preview(expression)Return a bounded result preview.

Python

title = browser.evaluate("document.title")
preview = browser.evaluate_preview("({title:document.title,text:document.body.innerText})")
if preview.get("truncated"):
    print("Preview is partial; request selected fields or read-only pages of data")

08 · Screenshots, PDF, and file transfer

Configure absolute file_roots, download_dir, and artifact_dir paths on the client. Uploads must stay inside permitted roots. Screenshot and PDF responses describe server-produced artifacts; do not assume a byte array. Upload and download recipes require actual file inputs or download links.

Screenshots, PDF, and file transfer — function reference
Function / callPurpose
browser.screenshot()Create a screenshot.
browser.pdf()Create a PDF.
browser.upload(paths, selector=...)Upload files through a real file input.
browser.download(selector=...)Download using a real download link.

Python

# Configure absolute trusted paths when constructing the client:
# KingAI(file_roots=[r"D:\demo\uploads"],
#        download_dir=r"D:\demo\downloads", artifact_dir=r"D:\demo\artifacts")
image = browser.screenshot()
document = browser.pdf()
# Target-page examples; the local form does not contain these elements:
# browser.upload([r"D:\demo\uploads\document.txt"], selector='input[type="file"]')
# browser.download(selector="#download-link")

09 · Cookies and Storage

These methods read site state. Keep cookies and storage out of public logs. Read the installed tool schema before calling state-changing extensions; do not invent setter parameters.

Cookies and Storage — function reference
Function / callPurpose
browser.cookies()Read cookies.
browser.storage()Read site storage.

Python

cookies = browser.cookies()
storage = browser.storage()
# Do not print/export cookies or storage into public logs.

10 · Saved Skill workflows

List Skills, inspect a real skill_id, then run it with its declared parameters. Obtain the runId from the returned start result. Parameters differ by Skill; Java/Go can use generic call / Call when a convenience method is unavailable.

Saved Skill workflows — function reference
Function / callPurpose
api.skills()List saved Skills.
api.describe_skill(skill_id)Inspect a Skill and its parameters.
api.run_skill(profile_id, skill_id, **options)Start replay with declared options.
api.skill_status(run_id)Read run status.
api.cancel_skill(run_id)Explicitly cancel a run.
api.skill_runs()List Skill runs.

Python

skills = api.skills()
# Use a real skill_id from the list, then inspect required parameters:
# description = api.describe_skill(skill_id)
# started = api.run_skill(profile_id, skill_id, **options_from_description)
# status = api.skill_status(started["runId"])
# api.cancel_skill(started["runId"])  # only if you intend to cancel
runs = api.skill_runs()

11 · The installed tool catalog

Convenience methods do not cover every installed capability. Inspect names, required fields, and descriptions for iframe, network, console, and other tools before a generic call. Run the following commands from the GitHub repository root after obtaining its example scripts; these are not commands shipped by the pip package.

Repository example commands

python python/examples/mcp_tool_catalog.py
python python/examples/mcp_tool_catalog.py --tool browser_query

12 · Errors and execution results

KingAIError exposes a structured error code. Do not automatically replay a click or input with an unknown outcome. Use request_status only with a real Runtime request ID supplied by the backend; a JSON-RPC ID is not a substitute. PAGE_NOT_VISIBLE requires restoring and activating the page. Ownership, account limits, and leases still apply.

Errors and execution results — function reference
Function / callPurpose
KingAIError.codeRead the error code without exposing sensitive details.

Python

from kingai_browser import KingAIError
try:
    page = browser.read()
except KingAIError as error:
    print(error.code)  # keep structured details private unless sanitized
    raise             # no automatic replay of a previous click/type

See GitHub for detailed code usage and the API examples →